1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22%%----------------------------------------------------------------------
23%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
24%%----------------------------------------------------------------------
25
26-module(megaco_pretty_text_encoder).
27
28-behaviour(megaco_encoder).
29
30-export([encode_message/3, decode_message/3,
31	 decode_mini_message/3,
32
33	 version_of/2,
34
35	 encode_transaction/3,
36	 encode_action_requests/3,
37	 encode_action_request/3,
38	 encode_command_request/3,
39	 encode_action_reply/3]).
40
41%% Backward compatible funcs:
42-export([encode_message/2, decode_message/2,
43
44	 encode_transaction/1,
45	 encode_command_request/1,
46	 encode_action_reply/1]).
47
48%% Do we need these here?
49-export([trim_quoted_string/1,
50	 term_to_compact_string/1,
51	 term_to_pretty_string/1]).
52
53-export([token_tag2string/1, token_tag2string/2]).
54
55
56-include("megaco_text_tokens.hrl").
57-include_lib("megaco/src/engine/megaco_message_internal.hrl").
58
59-define(V1_PARSE_MOD,     megaco_text_parser_v1).
60-define(V2_PARSE_MOD,     megaco_text_parser_v2).
61-define(V3_PARSE_MOD,     megaco_text_parser_v3).
62-define(PREV3A_PARSE_MOD, megaco_text_parser_prev3a).
63-define(PREV3B_PARSE_MOD, megaco_text_parser_prev3b).
64-define(PREV3C_PARSE_MOD, megaco_text_parser_prev3c).
65
66
67%%----------------------------------------------------------------------
68%% Convert a 'MegacoMessage' record into a binary
69%% Return {ok, DeepIoList} | {error, Reason}
70%%----------------------------------------------------------------------
71
72encode_message(EncodingConfig,
73	       #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) ->
74    encode_message(EncodingConfig, V, MegaMsg).
75
76
77encode_message([{version3,_}|EC], 1, MegaMsg) ->
78    megaco_pretty_text_encoder_v1:encode_message(EC, MegaMsg);
79encode_message(EC, 1, MegaMsg) ->
80    megaco_pretty_text_encoder_v1:encode_message(EC, MegaMsg);
81encode_message([{version3,_}|EC], 2, MegaMsg) ->
82    megaco_pretty_text_encoder_v2:encode_message(EC, MegaMsg);
83encode_message(EC, 2, MegaMsg) ->
84    megaco_pretty_text_encoder_v2:encode_message(EC, MegaMsg);
85encode_message([{version3,prev3c}|EC], 3, MegaMsg) ->
86    megaco_pretty_text_encoder_prev3c:encode_message(EC, MegaMsg);
87encode_message([{version3,prev3b}|EC], 3, MegaMsg) ->
88    megaco_pretty_text_encoder_prev3b:encode_message(EC, MegaMsg);
89encode_message([{version3,prev3a}|EC], 3, MegaMsg) ->
90    megaco_pretty_text_encoder_prev3a:encode_message(EC, MegaMsg);
91encode_message([{version3,v3}|EC], 3, MegaMsg) ->
92    megaco_pretty_text_encoder_v3:encode_message(EC, MegaMsg);
93encode_message(EC, 3, MegaMsg) ->
94    megaco_pretty_text_encoder_v3:encode_message(EC, MegaMsg);
95encode_message(_EC, V, _MegaMsg) ->
96    {error, {bad_version, V}}.
97
98
99%%----------------------------------------------------------------------
100%% Convert a binary into a 'MegacoMessage' record
101%% Return {ok, MegacoMessageRecord} | {error, Reason}
102%%----------------------------------------------------------------------
103
104version_of(_EC, Bin) ->
105    case megaco_text_scanner:scan(Bin) of
106	{ok, _Tokens, V, _LastLine} ->
107	    {ok, V};
108	{error, Reason, Line} ->
109	    {error, {decode_failed, Reason, Line}}
110    end.
111
112
113decode_message(EC, Bin) ->
114    decode_message(EC, dynamic, Bin).
115
116decode_message([], _, Bin) when is_binary(Bin) ->
117    case megaco_text_scanner:scan(Bin) of
118	{ok, Tokens, 1, _LastLine} ->
119	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
120
121	{ok, Tokens, 2, _LastLine} ->
122	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
123
124	{ok, Tokens, 3, _LastLine} ->
125	    do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
126
127	{ok, _Tokens, V, _LastLine} ->
128	    {error, {unsupported_version, V}};
129
130	%% {error, Reason, Tokens, Line} ->
131	%%     scan_error(Reason, Line, Tokens, Bin);
132
133	{error, Reason, Line} ->               %% OTP-4007
134	    scan_error(Reason, Line, Bin) %% OTP-4007
135    end;
136decode_message([{version3,v3}], _, Bin) when is_binary(Bin) ->
137    case megaco_text_scanner:scan(Bin) of
138	{ok, Tokens, 1, _LastLine} ->
139	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
140
141	{ok, Tokens, 2, _LastLine} ->
142	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
143
144	{ok, Tokens, 3, _LastLine} ->
145	    do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
146
147	{ok, _Tokens, V, _LastLine} ->
148	    {error, {unsupported_version, V}};
149
150	{error, Reason, Tokens, Line} ->
151	    scan_error(Reason, Line, Tokens, Bin);
152
153	{error, Reason, Line} ->               %% OTP-4007
154	    scan_error(Reason, Line, Bin) %% OTP-4007
155    end;
156decode_message([{version3,prev3c}], _, Bin) when is_binary(Bin) ->
157    case megaco_text_scanner:scan(Bin) of
158	{ok, Tokens, 1, _LastLine} ->
159	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
160
161	{ok, Tokens, 2, _LastLine} ->
162	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
163
164	{ok, Tokens, 3, _LastLine} ->
165	    do_decode_message(?PREV3C_PARSE_MOD, Tokens, Bin);
166
167	{ok, _Tokens, V, _LastLine} ->
168	    {error, {unsupported_version, V}};
169
170	{error, Reason, Tokens, Line} ->
171	    scan_error(Reason, Line, Tokens, Bin);
172
173	{error, Reason, Line} ->
174	    scan_error(Reason, Line, Bin)
175    end;
176decode_message([{version3,prev3b}], _, Bin) when is_binary(Bin) ->
177    case megaco_text_scanner:scan(Bin) of
178	{ok, Tokens, 1, _LastLine} ->
179	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
180
181	{ok, Tokens, 2, _LastLine} ->
182	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
183
184	{ok, Tokens, 3, _LastLine} ->
185	    do_decode_message(?PREV3B_PARSE_MOD, Tokens, Bin);
186
187	{ok, _Tokens, V, _LastLine} ->
188	    {error, {unsupported_version, V}};
189
190	{error, Reason, Tokens, Line} ->
191	    scan_error(Reason, Line, Tokens, Bin);
192
193	{error, Reason, Line} ->               %% OTP-4007
194	    scan_error(Reason, Line, Bin) %% OTP-4007
195    end;
196decode_message([{version3,prev3a}], _, Bin) when is_binary(Bin) ->
197    case megaco_text_scanner:scan(Bin) of
198	{ok, Tokens, 1, _LastLine} ->
199	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
200
201	{ok, Tokens, 2, _LastLine} ->
202	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
203
204	{ok, Tokens, 3, _LastLine} ->
205	    do_decode_message(?PREV3A_PARSE_MOD, Tokens, Bin);
206
207	{ok, _Tokens, V, _LastLine} ->
208	    {error, {unsupported_version, V}};
209
210	{error, Reason, Tokens, Line} ->
211	    scan_error(Reason, Line, Tokens, Bin);
212
213	{error, Reason, Line} ->               %% OTP-4007
214	    scan_error(Reason, Line, Bin) %% OTP-4007
215    end;
216decode_message([{flex, Port}], _, Bin) when is_binary(Bin) ->
217    case megaco_flex_scanner:scan(Bin, Port) of
218	{ok, Tokens, 1, _LastLine} ->
219	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
220
221	{ok, Tokens, 2, _LastLine} ->
222	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
223
224	{ok, Tokens, 3, _LastLine} ->
225	    do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
226
227	{ok, _Tokens, V, _LastLine} ->
228	    {error, {unsupported_version, V}};
229
230	%% {error, Reason, Tokens, Line} ->
231	%%     scan_error(Reason, Line, Tokens, Bin);
232
233	{error, Reason, Line} ->               %% OTP-4007
234	    scan_error(Reason, Line, Bin) %% OTP-4007
235    end;
236decode_message([{version3,v3},{flex, Port}], _, Bin) when is_binary(Bin) ->
237    case megaco_flex_scanner:scan(Bin, Port) of
238	{ok, Tokens, 1, _LastLine} ->
239	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
240
241	{ok, Tokens, 2, _LastLine} ->
242	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
243
244	{ok, Tokens, 3, _LastLine} ->
245	    do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
246
247	{ok, _Tokens, V, _LastLine} ->
248	    {error, {unsupported_version, V}};
249
250	%% {error, Reason, Tokens, Line} ->
251	%%     scan_error(Reason, Line, Tokens, Bin);
252
253	{error, Reason, Line} ->               %% OTP-4007
254	    scan_error(Reason, Line, Bin) %% OTP-4007
255    end;
256decode_message([{version3,prev3c},{flex, Port}], _, Bin) when is_binary(Bin) ->
257    case megaco_flex_scanner:scan(Bin, Port) of
258	{ok, Tokens, 1, _LastLine} ->
259	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
260
261	{ok, Tokens, 2, _LastLine} ->
262	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
263
264	{ok, Tokens, 3, _LastLine} ->
265	    do_decode_message(?PREV3C_PARSE_MOD, Tokens, Bin);
266
267	{ok, _Tokens, V, _LastLine} ->
268	    {error, {unsupported_version, V}};
269
270	%% {error, Reason, Tokens, Line} ->
271	%%     scan_error(Reason, Line, Tokens, Bin);
272
273	{error, Reason, Line} ->               %% OTP-4007
274	    scan_error(Reason, Line, Bin) %% OTP-4007
275    end;
276decode_message([{version3,prev3b},{flex, Port}], _, Bin) when is_binary(Bin) ->
277    case megaco_flex_scanner:scan(Bin, Port) of
278	{ok, Tokens, 1, _LastLine} ->
279	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
280
281	{ok, Tokens, 2, _LastLine} ->
282	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
283
284	{ok, Tokens, 3, _LastLine} ->
285	    do_decode_message(?PREV3B_PARSE_MOD, Tokens, Bin);
286
287	{ok, _Tokens, V, _LastLine} ->
288	    {error, {unsupported_version, V}};
289
290	%% {error, Reason, Tokens, Line} ->
291	%%     scan_error(Reason, Line, Tokens, Bin);
292
293	{error, Reason, Line} ->               %% OTP-4007
294	    scan_error(Reason, Line, Bin) %% OTP-4007
295    end;
296decode_message([{version3,prev3a},{flex, Port}], _, Bin) when is_binary(Bin) ->
297    case megaco_flex_scanner:scan(Bin, Port) of
298	{ok, Tokens, 1, _LastLine} ->
299	    do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
300
301	{ok, Tokens, 2, _LastLine} ->
302	    do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
303
304	{ok, Tokens, 3, _LastLine} ->
305	    do_decode_message(?PREV3A_PARSE_MOD, Tokens, Bin);
306
307	{ok, _Tokens, V, _LastLine} ->
308	    {error, {unsupported_version, V}};
309
310	%% {error, Reason, Tokens, Line} ->
311	%%     scan_error(Reason, Line, Tokens, Bin);
312
313	{error, Reason, Line} ->               %% OTP-4007
314	    scan_error(Reason, Line, Bin) %% OTP-4007
315    end;
316decode_message(EC, _, Bin) when is_binary(Bin) ->
317    {error, {bad_encoding_config, EC}};
318decode_message(_EC, _, _BadBin) ->
319    {error, bad_binary}.
320
321
322do_decode_message(ParseMod, Tokens, Bin) ->
323    case (catch ParseMod:parse(Tokens)) of
324	{ok, MegacoMessage} ->
325	    {ok, MegacoMessage};
326	{error, Reason} ->
327	    parse_error(Reason, Tokens, Bin);
328
329	%% OTP-4007
330	{'EXIT', Reason} ->
331	    parse_error(Reason, Tokens, Bin)
332    end.
333
334
335decode_mini_message(EC, _, Bin) when is_binary(Bin) ->
336    megaco_text_mini_decoder:decode_message(EC, Bin).
337
338
339scan_error(Reason, Line, Bin) ->
340    scan_error(Reason, Line, [], Bin).
341
342scan_error("bad_property_parm: " ++ Reason, _Line, _Tokens, _Bin) ->
343    {error, {bad_property_parm, Reason}};
344scan_error(Reason, Line, Tokens, Bin) ->
345    %%     io:format("scanner error: "
346    %% 	      "~n   Reason: ~p"
347    %% 	      "~n   Line:   ~p"
348    %% 	      "~n   Tokens: ~p"
349    %% 	      "~n   Bin:    ~p"
350    %% 	      "~n", [Reason, Line, Tokens, Bin]),
351    {error, [{reason, Reason, Line}, {token, Tokens}, {chars, Bin}]}.
352
353parse_error(Reason, Tokens, Chars) ->
354%%     io:format("parse_error -> entry with"
355%%               "~n   Reason: ~p"
356%% 	      "~n   Tokens: ~p"
357%% 	      "~n   Chars:  ~p"
358%% 	      "~n", [Reason, Tokens, Chars]),
359    case Reason of
360	{Line, Mod, [Prefix, [$[, TokenStringRaw, $]]]} when
361	      is_integer(Line) andalso
362	      is_atom(Mod) andalso
363	      is_list(Prefix) andalso
364	      is_list(TokenStringRaw) ->
365	    TokenString = [l2i(X) || X <- TokenStringRaw, is_list(X)],
366	    ReasonStr = Prefix ++ TokenString,
367	    {error, [{reason, ReasonStr, Line}, {tokens, Tokens}, {chars, Chars}, {module, Mod}]};
368	_ ->
369	    {error, [{reason, Reason}, {token, Tokens}, {chars, Chars}]}
370    end.
371
372
373l2i(L) when is_list(L) ->
374    case (catch list_to_integer(L)) of
375	I when is_integer(I) ->
376	    I;
377	_ ->
378	    L
379    end.
380
381
382%%----------------------------------------------------------------------
383%% Convert a transaction record into a binary
384%% Return {ok, Bin} | {error, Reason}
385%%----------------------------------------------------------------------
386encode_transaction(Trans) ->
387    encode_transaction([], 1, Trans).
388
389encode_transaction([{version3,_}|EC], 1, Trans) ->
390    megaco_pretty_text_encoder_v1:encode_transaction(EC, Trans);
391encode_transaction(EC, 1, Trans) ->
392    megaco_pretty_text_encoder_v1:encode_transaction(EC, Trans);
393encode_transaction([{version3,_}|EC], 2, Trans) ->
394    megaco_pretty_text_encoder_v2:encode_transaction(EC, Trans);
395encode_transaction(EC, 2, Trans) ->
396    megaco_pretty_text_encoder_v2:encode_transaction(EC, Trans);
397encode_transaction([{version3,v3}|EC], 3, Trans) ->
398    megaco_pretty_text_encoder_v3:encode_transaction(EC, Trans);
399encode_transaction([{version3,prev3c}|EC], 3, Trans) ->
400    megaco_pretty_text_encoder_prev3c:encode_transaction(EC, Trans);
401encode_transaction([{version3,prev3b}|EC], 3, Trans) ->
402    megaco_pretty_text_encoder_prev3b:encode_transaction(EC, Trans);
403encode_transaction([{version3,prev3a}|EC], 3, Trans) ->
404    megaco_pretty_text_encoder_prev3a:encode_transaction(EC, Trans);
405encode_transaction(EC, 3, Trans) ->
406    megaco_pretty_text_encoder_v3:encode_transaction(EC, Trans);
407encode_transaction(_EC, V, _Trans) ->
408    {error, {bad_version, V}}.
409
410
411%%----------------------------------------------------------------------
412%% Convert a list of ActionRequest record's into a binary
413%% Return {ok, DeepIoList} | {error, Reason}
414%%----------------------------------------------------------------------
415encode_action_requests([{version3,_}|EC], 1, ActReqs) when is_list(ActReqs) ->
416    megaco_pretty_text_encoder_v1:encode_action_requests(EC, ActReqs);
417encode_action_requests(EC, 1, ActReqs) when is_list(ActReqs) ->
418    megaco_pretty_text_encoder_v1:encode_action_requests(EC, ActReqs);
419encode_action_requests([{version3,_}|EC], 2, ActReqs) when is_list(ActReqs) ->
420    megaco_pretty_text_encoder_v2:encode_action_requests(EC, ActReqs);
421encode_action_requests(EC, 2, ActReqs) when is_list(ActReqs) ->
422    megaco_pretty_text_encoder_v2:encode_action_requests(EC, ActReqs);
423encode_action_requests([{version3,v3}|EC], 3, ActReqs)
424  when is_list(ActReqs) ->
425    megaco_pretty_text_encoder_v3:encode_action_requests(EC, ActReqs);
426encode_action_requests([{version3,prev3c}|EC], 3, ActReqs)
427  when is_list(ActReqs) ->
428    megaco_pretty_text_encoder_prev3c:encode_action_requests(EC, ActReqs);
429encode_action_requests([{version3,prev3b}|EC], 3, ActReqs)
430  when is_list(ActReqs) ->
431    megaco_pretty_text_encoder_prev3b:encode_action_requests(EC, ActReqs);
432encode_action_requests([{version3,prev3a}|EC], 3, ActReqs)
433  when is_list(ActReqs) ->
434    megaco_pretty_text_encoder_prev3a:encode_action_requests(EC, ActReqs);
435encode_action_requests(EC, 3, ActReqs) when is_list(ActReqs) ->
436    megaco_pretty_text_encoder_v3:encode_action_requests(EC, ActReqs);
437encode_action_requests(_EC, V, _ActReqs) ->
438    {error, {bad_version, V}}.
439
440
441%%----------------------------------------------------------------------
442%% Convert a ActionRequest record into a binary
443%% Return {ok, DeepIoList} | {error, Reason}
444%%----------------------------------------------------------------------
445encode_action_request([{version3,_}|EC], 1, ActReq) ->
446    megaco_pretty_text_encoder_v1:encode_action_request(EC, ActReq);
447encode_action_request(EC, 1, ActReq) ->
448    megaco_pretty_text_encoder_v1:encode_action_request(EC, ActReq);
449encode_action_request([{version3,_}|EC], 2, ActReq) ->
450    megaco_pretty_text_encoder_v2:encode_action_request(EC, ActReq);
451encode_action_request(EC, 2, ActReq) ->
452    megaco_pretty_text_encoder_v2:encode_action_request(EC, ActReq);
453encode_action_request([{version3,v3}|EC], 3, ActReq) ->
454    megaco_pretty_text_encoder_v3:encode_action_request(EC, ActReq);
455encode_action_request([{version3,prev3c}|EC], 3, ActReq) ->
456    megaco_pretty_text_encoder_prev3c:encode_action_request(EC, ActReq);
457encode_action_request([{version3,prev3b}|EC], 3, ActReq) ->
458    megaco_pretty_text_encoder_prev3b:encode_action_request(EC, ActReq);
459encode_action_request([{version3,prev3a}|EC], 3, ActReq) ->
460    megaco_pretty_text_encoder_prev3a:encode_action_request(EC, ActReq);
461encode_action_request(EC, 3, ActReq) ->
462    megaco_pretty_text_encoder_v3:encode_action_request(EC, ActReq);
463encode_action_request(_EC, V, _ActReq) ->
464    {error, {bad_version, V}}.
465
466
467%%----------------------------------------------------------------------
468%% Convert a CommandRequest record into a binary
469%% Return {ok, DeepIoList} | {error, Reason}
470%%----------------------------------------------------------------------
471encode_command_request(CmdReq) ->
472    encode_command_request([], 1, CmdReq).
473
474encode_command_request([{version3,_}|EC], 1, CmdReq) ->
475    megaco_pretty_text_encoder_v1:encode_command_request(EC, CmdReq);
476encode_command_request(EC, 1, CmdReq) ->
477    megaco_pretty_text_encoder_v1:encode_command_request(EC, CmdReq);
478encode_command_request([{version3,_}|EC], 2, CmdReq) ->
479    megaco_pretty_text_encoder_v2:encode_command_request(EC, CmdReq);
480encode_command_request(EC, 2, CmdReq) ->
481    megaco_pretty_text_encoder_v2:encode_command_request(EC, CmdReq);
482encode_command_request([{version3,v3}|EC], 3, CmdReq) ->
483    megaco_pretty_text_encoder_v3:encode_command_request(EC, CmdReq);
484encode_command_request([{version3,prev3c}|EC], 3, CmdReq) ->
485    megaco_pretty_text_encoder_prev3c:encode_command_request(EC, CmdReq);
486encode_command_request([{version3,prev3b}|EC], 3, CmdReq) ->
487    megaco_pretty_text_encoder_prev3b:encode_command_request(EC, CmdReq);
488encode_command_request([{version3,prev3a}|EC], 3, CmdReq) ->
489    megaco_pretty_text_encoder_prev3a:encode_command_request(EC, CmdReq);
490encode_command_request(EC, 3, CmdReq) ->
491    megaco_pretty_text_encoder_v3:encode_command_request(EC, CmdReq);
492encode_command_request(_EC, V, _CmdReq) ->
493    {error, {bad_version, V}}.
494
495
496%%----------------------------------------------------------------------
497%% Convert a action reply into a deep io list
498%% Return {ok, DeepIoList} | {error, Reason}
499%%----------------------------------------------------------------------
500encode_action_reply(ActRep) ->
501%%     io:format("~p:encode_action_reply -> entry with"
502%% 	      "~n   ActRep: ~p"
503%% 	      "~n", [?MODULE, ActRep]),
504    encode_action_reply([], 1, ActRep).
505
506encode_action_reply([{version3,_}|EC], 1, ActRep) ->
507    megaco_pretty_text_encoder_v1:encode_action_reply(EC, ActRep);
508encode_action_reply(EC, 1, ActRep) ->
509    megaco_pretty_text_encoder_v1:encode_action_reply(EC, ActRep);
510encode_action_reply([{version3,_}|EC], 2, ActRep) ->
511    megaco_pretty_text_encoder_v2:encode_action_reply(EC, ActRep);
512encode_action_reply(EC, 2, ActRep) ->
513    megaco_pretty_text_encoder_v2:encode_action_reply(EC, ActRep);
514encode_action_reply([{version3,v3}|EC], 3, ActRep) ->
515    megaco_pretty_text_encoder_v3:encode_action_reply(EC, ActRep);
516encode_action_reply([{version3,prev3c}|EC], 3, ActRep) ->
517    megaco_pretty_text_encoder_prev3c:encode_action_reply(EC, ActRep);
518encode_action_reply([{version3,prev3b}|EC], 3, ActRep) ->
519    megaco_pretty_text_encoder_prev3b:encode_action_reply(EC, ActRep);
520encode_action_reply([{version3,prev3a}|EC], 3, ActRep) ->
521    megaco_pretty_text_encoder_prev3a:encode_action_reply(EC, ActRep);
522encode_action_reply(EC, 3, ActRep) ->
523    megaco_pretty_text_encoder_v3:encode_action_reply(EC, ActRep);
524encode_action_reply(_EC, V, _ActRep) ->
525    {error, {bad_version, V}}.
526
527
528%%----------------------------------------------------------------------
529term_to_compact_string(Term) ->
530    case catch io_lib:format("~s", [Term]) of
531        {'EXIT', _} -> lists:flatten(io_lib:format("~w", [Term]));
532        GoodString  -> lists:flatten(GoodString)
533    end.
534
535%%----------------------------------------------------------------------
536term_to_pretty_string(Term) ->
537    case catch io_lib:format("~s", [Term]) of
538        {'EXIT', _} -> lists:flatten(io_lib:format("~p", [Term]));
539        GoodString  -> lists:flatten(GoodString)
540    end.
541
542%%----------------------------------------------------------------------
543trim_quoted_string([H | T]) ->
544    case ?classify_char(H) of
545	safe_char   -> [H  | trim_quoted_string(T)];
546	rest_char   -> [H  | trim_quoted_string(T)];
547	white_space -> [H  | trim_quoted_string(T)];
548	_BadChar     -> [$? | trim_quoted_string(T)]
549    end;
550trim_quoted_string([]) ->
551    [].
552
553
554%%----------------------------------------------------------------------
555%% A utility function to pretty print the tags found in a megaco message
556%%----------------------------------------------------------------------
557
558-define(TT2S_BEST_VERSION, v3).
559
560token_tag2string(Tag) ->
561    token_tag2string(Tag, ?TT2S_BEST_VERSION).
562
563token_tag2string(Tag, 1) ->
564    token_tag2string(Tag, v1);
565token_tag2string(Tag, v1) ->
566    megaco_pretty_text_encoder_v1:token_tag2string(Tag);
567token_tag2string(Tag, 2) ->
568    token_tag2string(Tag, v2);
569token_tag2string(Tag, v2) ->
570    megaco_pretty_text_encoder_v2:token_tag2string(Tag);
571token_tag2string(Tag, 3) ->
572    token_tag2string(Tag, v3);
573token_tag2string(Tag, v3) ->
574    megaco_pretty_text_encoder_v3:token_tag2string(Tag);
575token_tag2string(Tag, prev3b) ->
576    megaco_pretty_text_encoder_prev3b:token_tag2string(Tag);
577token_tag2string(Tag, prev3c) ->
578    megaco_pretty_text_encoder_prev3c:token_tag2string(Tag);
579token_tag2string(Tag, _Vsn) ->
580    token_tag2string(Tag, ?TT2S_BEST_VERSION).
581
582
583
584%% d(F) ->
585%%     d(F, []).
586
587%% d(F, A) ->
588%%     %% d(get(dbg), F, A).
589%%     d(true, F, A).
590
591%% d(true, F, A) ->
592%%     io:format("~p:" ++ F ++ "~n", [?MODULE|A]);
593%% d(_, _, _) ->
594%%     ok.
595
596%% p(F, A) ->
597%%     io:format("*** [~s] ***"
598%% 	      "~n   " ++ F ++ "~n", [formated_timestamp() | A]),
599%%     sleep(5000),
600%%     ok.
601
602%% sleep(X) -> receive after X -> ok end.
603
604%% formated_timestamp() ->
605%%     format_timestamp(now()).
606
607%% format_timestamp({_N1, _N2, N3}   = Now) ->
608%%     {Date, Time}   = calendar:now_to_datetime(Now),
609%%     {YYYY,MM,DD}   = Date,
610%%     {Hour,Min,Sec} = Time,
611%%     FormatDate =
612%%         io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
613%%                       [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
614%%     lists:flatten(FormatDate).
615