aboutsummaryrefslogtreecommitdiff
path: root/src/xmlrpc_decode.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmlrpc_decode.erl')
-rw-r--r--src/xmlrpc_decode.erl237
1 files changed, 130 insertions, 107 deletions
diff --git a/src/xmlrpc_decode.erl b/src/xmlrpc_decode.erl
index af0d72c68..72c78cf4a 100644
--- a/src/xmlrpc_decode.erl
+++ b/src/xmlrpc_decode.erl
@@ -3,10 +3,10 @@
%%
%% Redistribution and use in source and binary forms, with or without
%% modification, are permitted provided that the following conditions
-%% are met:
+%% are met:
%%
%% 1. Redistributions of source code must retain the above copyright
-%% notice, this list of conditions and the following disclaimer.
+%% notice, this list of conditions and the following disclaimer.
%% 2. Redistributions in binary form must reproduce the above
%% copyright notice, this list of conditions and the following
%% disclaimer in the documentation and/or other materials provided
@@ -25,130 +25,156 @@
%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-module(xmlrpc_decode).
+
-author('jocke@gleipnir.com').
+
-export([payload/1]).
-include("log.hrl").
+
-include_lib("xmerl/include/xmerl.hrl").
payload(Payload) ->
?DEBUG_LOG({scanning_payload, Payload}),
case xmerl_scan:string(Payload) of
- {error, Reason} ->
- ?DEBUG_LOG({error_scanning, Payload, Reason}),
- {error, Reason};
- {E, _} ->
- ?DEBUG_LOG({decoding_element, E}),
- case catch decode_element(E) of
- {'EXIT', Reason} ->
- ?DEBUG_LOG({error_deconding, E, Reason}),
- exit(Reason);
- Result ->
- ?DEBUG_LOG({result_deconding, E, Result}),
- Result
- end
+ {error, Reason} ->
+ ?DEBUG_LOG({error_scanning, Payload, Reason}),
+ {error, Reason};
+ {E, _} ->
+ ?DEBUG_LOG({decoding_element, E}),
+ case catch decode_element(E) of
+ {'EXIT', Reason} ->
+ ?DEBUG_LOG({error_deconding, E, Reason}), exit(Reason);
+ Result ->
+ ?DEBUG_LOG({result_deconding, E, Result}), Result
+ end
end.
-decode_element(#xmlElement{name = methodCall} = MethodCall)
- when record(MethodCall, xmlElement) ->
- {MethodName, Rest} =
- match_element([methodName], MethodCall#xmlElement.content),
- TextValue = get_text_value(MethodName#xmlElement.content),
+decode_element(#xmlElement{name = methodCall} =
+ MethodCall)
+ when is_record(MethodCall, xmlElement) ->
+ {MethodName, Rest} = match_element([methodName],
+ MethodCall#xmlElement.content),
+ TextValue =
+ get_text_value(MethodName#xmlElement.content),
case match_element(normal, [params], Rest) of
- {error, {missing_element, _}} ->
- {ok, {call, list_to_atom(TextValue), []}};
- {Params, _} ->
- DecodedParams = decode_params(Params#xmlElement.content),
- {ok, {call, list_to_atom(TextValue), DecodedParams}}
+ {error, {missing_element, _}} ->
+ {ok, {call, jlib:binary_to_atom(TextValue), []}};
+ {Params, _} ->
+ DecodedParams =
+ decode_params(Params#xmlElement.content),
+ {ok,
+ {call, jlib:binary_to_atom(TextValue), DecodedParams}}
end;
-decode_element(#xmlElement{name = methodResponse} = MethodResponse)
- when record(MethodResponse, xmlElement) ->
- case match_element([fault, params], MethodResponse#xmlElement.content) of
- {Fault, _} when Fault#xmlElement.name == fault ->
- {Value, _} = match_element([value], Fault#xmlElement.content),
- case decode(Value#xmlElement.content) of
- {struct, [{faultCode, Code},
- {faultString, String}]} when integer(Code) ->
- case xmlrpc_util:is_string(String) of
- yes -> {ok, {response, {fault, Code, String}}};
- no -> {error, {bad_string, String}}
- end;
- _ ->
- {error, {bad_element, MethodResponse}}
- end;
- {Params, _} ->
- case decode_params(Params#xmlElement.content) of
- [DecodedParam] -> {ok, {response, [DecodedParam]}};
- DecodedParams -> {error, {to_many_params, DecodedParams}}
- end
+decode_element(#xmlElement{name = methodResponse} =
+ MethodResponse)
+ when is_record(MethodResponse, xmlElement) ->
+ case match_element([fault, params],
+ MethodResponse#xmlElement.content)
+ of
+ {Fault, _} when Fault#xmlElement.name == fault ->
+ {Value, _} = match_element([value],
+ Fault#xmlElement.content),
+ case decode(Value#xmlElement.content) of
+ {struct, [{faultCode, Code}, {faultString, String}]}
+ when is_integer(Code) ->
+ case xmlrpc_util:is_string(String) of
+ yes -> {ok, {response, {fault, Code, String}}};
+ no -> {error, {bad_string, String}}
+ end;
+ _ -> {error, {bad_element, MethodResponse}}
+ end;
+ {Params, _} ->
+ case decode_params(Params#xmlElement.content) of
+ [DecodedParam] -> {ok, {response, [DecodedParam]}};
+ DecodedParams ->
+ {error, {to_many_params, DecodedParams}}
+ end
end;
decode_element(E) -> {error, {bad_element, E}}.
-match_element(NameList, Content) -> match_element(throw, NameList, Content).
+match_element(NameList, Content) ->
+ match_element(throw, NameList, Content).
match_element(Type, NameList, []) ->
return(Type, {error, {missing_element, NameList}});
-match_element(Type, NameList, [E|Rest]) when record(E, xmlElement) ->
+match_element(Type, NameList, [E | Rest])
+ when is_record(E, xmlElement) ->
case lists:member(E#xmlElement.name, NameList) of
- true -> {E, Rest};
- false -> return(Type, {error, {unexpected_element, E#xmlElement.name}})
+ true -> {E, Rest};
+ false ->
+ return(Type,
+ {error, {unexpected_element, E#xmlElement.name}})
end;
-match_element(Type, NameList, [T|Rest]) when record(T, xmlText) ->
+match_element(Type, NameList, [T | Rest])
+ when is_record(T, xmlText) ->
case only_whitespace(T#xmlText.value) of
- yes -> match_element(Type, NameList, Rest);
- no ->
- return(Type, {error, {unexpected_text, T#xmlText.value, NameList}})
+ yes -> match_element(Type, NameList, Rest);
+ no ->
+ return(Type,
+ {error, {unexpected_text, T#xmlText.value, NameList}})
end.
return(throw, Result) -> throw(Result);
return(normal, Result) -> Result.
-only_whitespace([]) -> yes;
-only_whitespace([$ |Rest]) -> only_whitespace(Rest);
-only_whitespace([$\n|Rest]) -> only_whitespace(Rest);
-only_whitespace([$\t|Rest]) -> only_whitespace(Rest);
+only_whitespace(<<>>) -> yes;
+only_whitespace(<<$\s, Rest/binary>>) ->
+ only_whitespace(Rest);
+only_whitespace(<<$\n, Rest/binary>>) ->
+ only_whitespace(Rest);
+only_whitespace(<<$\t, Rest/binary>>) ->
+ only_whitespace(Rest);
only_whitespace(_) -> no.
-get_text_value([]) -> [];
-get_text_value([T|Rest]) when record(T, xmlText) ->
- T#xmlText.value++get_text_value(Rest);
+get_text_value([]) -> <<>>;
+get_text_value([T | Rest]) when is_record(T, xmlText) ->
+ <<(list_to_binary(T#xmlText.value))/binary, (get_text_value(Rest))/binary>>;
get_text_value(_) -> throw({error, missing_text}).
decode_params([]) -> [];
decode_params(Content) ->
case match_element(normal, [param], Content) of
- {error, {missing_element, _}} -> [];
- {Param, Rest} ->
- {Value, _} = match_element([value], Param#xmlElement.content),
- [decode(Value#xmlElement.content)|decode_params(Rest)]
+ {error, {missing_element, _}} -> [];
+ {Param, Rest} ->
+ {Value, _} = match_element([value],
+ Param#xmlElement.content),
+ [decode(Value#xmlElement.content) | decode_params(Rest)]
end.
-decode(Content) when list(Content) ->
+decode(Content) when is_list(Content) ->
case get_value(Content) of
- {text_value, TextValue} -> TextValue;
- E -> decode(E)
+ {text_value, TextValue} -> TextValue;
+ E -> decode(E)
end;
-decode(String) when record(String, xmlText) -> String#xmlText.value;
+decode(String) when is_record(String, xmlText) ->
+ String#xmlText.value;
decode(Struct) when Struct#xmlElement.name == struct ->
{struct, decode_members(Struct#xmlElement.content)};
decode(Array) when Array#xmlElement.name == array ->
- {Data, _} = match_element([data], Array#xmlElement.content),
+ {Data, _} = match_element([data],
+ Array#xmlElement.content),
{array, decode_values(Data#xmlElement.content)};
-decode(Int) when Int#xmlElement.name == int; Int#xmlElement.name == i4 ->
+decode(Int)
+ when Int#xmlElement.name == int;
+ Int#xmlElement.name == i4 ->
TextValue = get_text_value(Int#xmlElement.content),
make_integer(TextValue);
-decode(Boolean) when Boolean#xmlElement.name == boolean ->
+decode(Boolean)
+ when Boolean#xmlElement.name == boolean ->
case get_text_value(Boolean#xmlElement.content) of
- "1" -> true;
- "0" -> false;
- TextValue -> throw({error, {invalid_boolean, TextValue}})
+ <<"1">> -> true;
+ <<"0">> -> false;
+ TextValue ->
+ throw({error, {invalid_boolean, TextValue}})
end;
decode(String) when String#xmlElement.name == string ->
get_text_value(String#xmlElement.content);
decode(Double) when Double#xmlElement.name == double ->
TextValue = get_text_value(Double#xmlElement.content),
make_double(TextValue);
-decode(Date) when Date#xmlElement.name == 'dateTime.iso8601' ->
+decode(Date)
+ when Date#xmlElement.name == 'dateTime.iso8601' ->
TextValue = get_text_value(Date#xmlElement.content),
{date, ensure_iso8601_date(TextValue)};
decode(Base64) when Base64#xmlElement.name == base64 ->
@@ -158,61 +184,58 @@ decode(Value) -> throw({error, {bad_value, Value}}).
get_value(Content) ->
case any_element(Content) of
- false -> {text_value, get_text_value(Content)};
- true -> get_element(Content)
+ false -> {text_value, get_text_value(Content)};
+ true -> get_element(Content)
end.
any_element([]) -> false;
-any_element([E|_]) when record(E, xmlElement) -> true;
-any_element([_|Rest]) -> any_element(Rest).
+any_element([E | _]) when is_record(E, xmlElement) -> true;
+any_element([_ | Rest]) -> any_element(Rest).
get_element([]) -> throw({error, missing_element});
-get_element([E|_]) when record(E, xmlElement) -> E;
-get_element([T|Rest]) when record(T, xmlText) ->
+get_element([E | _]) when is_record(E, xmlElement) -> E;
+get_element([T | Rest]) when is_record(T, xmlText) ->
case only_whitespace(T#xmlText.value) of
- yes -> get_element(Rest);
- no -> throw({error, {unexpected_text, T#xmlText.value}})
+ yes -> get_element(Rest);
+ no -> throw({error, {unexpected_text, T#xmlText.value}})
end.
decode_members(Content) ->
case match_element(normal, [member], Content) of
- {error, {missing_element, _}} -> [];
- {Member, Rest} ->
- {Name, Rest2} = match_element([name], Member#xmlElement.content),
- TextValue = get_text_value(Name#xmlElement.content),
- {Value, _} = match_element([value], Rest2),
- [{list_to_atom(TextValue),
- decode(Value#xmlElement.content)}|decode_members(Rest)]
+ {error, {missing_element, _}} -> [];
+ {Member, Rest} ->
+ {Name, Rest2} = match_element([name],
+ Member#xmlElement.content),
+ TextValue = get_text_value(Name#xmlElement.content),
+ {Value, _} = match_element([value], Rest2),
+ [{jlib:binary_to_atom(TextValue),
+ decode(Value#xmlElement.content)}
+ | decode_members(Rest)]
end.
decode_values([]) -> [];
decode_values(Content) ->
case match_element(normal, [value], Content) of
- {error, {missing_element, _}} -> [];
- {Value, Rest} ->
- [decode(Value#xmlElement.content)|decode_values(Rest)]
+ {error, {missing_element, _}} -> [];
+ {Value, Rest} ->
+ [decode(Value#xmlElement.content) | decode_values(Rest)]
end.
make_integer(Integer) ->
- case catch list_to_integer(Integer) of
- {'EXIT', Reason} -> throw({error, {not_integer, Integer}});
- Value -> Value
+ case catch jlib:binary_to_integer(Integer) of
+ {'EXIT', _Reason} ->
+ throw({error, {not_integer, Integer}});
+ Value -> Value
end.
make_double(Double) ->
- case catch list_to_float(Double) of
- {'EXIT', _} -> throw({error, {not_double, Double}});
- Value -> Value
+ case catch list_to_float(binary_to_list(Double)) of
+ {'EXIT', _} -> throw({error, {not_double, Double}});
+ Value -> Value
end.
ensure_iso8601_date(Date) ->
- case xmlrpc_util:is_iso8601_date(Date) of
- no -> throw({error, {not_iso8601_date, Date}});
- yes -> Date
- end.
+ xmlrpc_util:is_iso8601_date(Date).
ensure_base64(Base64) ->
- case xmlrpc_util:is_base64(Base64) of
- no -> throw({error, {not_base64, Base64}});
- yes -> Base64
- end.
+ xmlrpc_util:is_base64(Base64).