From a36dcc9535d701cf2d98848e5692cbc9a53c23bf Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 11 Apr 2022 16:25:08 -0400 Subject: [PATCH] Handle errors when parsing XML --- lib/parser/atom.ex | 19 +++++++++++++------ lib/parser/rss2.ex | 19 +++++++++++++------ lib/xml.ex | 12 ++++++++---- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/lib/parser/atom.ex b/lib/parser/atom.ex index 16d61d3..a95d5ae 100644 --- a/lib/parser/atom.ex +++ b/lib/parser/atom.ex @@ -12,15 +12,22 @@ defmodule FeedParser.Parser.Atom do def accepts(data, content_type) do case content_type do "application/atom+xml" -> - {true, XML.parse(data)} + case XML.parse(data) do + {:error, _} -> false + {:ok, doc} -> {true, doc} + end _ when content_type in ["text/xml", "application/xml"] -> - doc = XML.parse(data) + case XML.parse(data) do + {:error, _} -> + false - if XML.xmlElement(doc, :name) == :feed do - {true, doc} - else - false + {:ok, doc} -> + if XML.xmlElement(doc, :name) == :feed do + {true, doc} + else + false + end end _ -> diff --git a/lib/parser/rss2.ex b/lib/parser/rss2.ex index 8f3cbc6..5650682 100644 --- a/lib/parser/rss2.ex +++ b/lib/parser/rss2.ex @@ -12,15 +12,22 @@ defmodule FeedParser.Parser.RSS2 do def accepts(data, content_type) do cond do content_type in ["application/rss+xml", "text/rss+xml"] -> - {true, XML.parse(data)} + case XML.parse(data) do + {:error, _} -> false + {:ok, doc} -> {true, doc} + end content_type in ["text/xml", "application/xml"] -> - doc = XML.parse(data) + case XML.parse(data) do + {:error, _} -> + false - if XML.xmlElement(doc, :name) == :rss do - {true, doc} - else - false + {:ok, doc} -> + if XML.xmlElement(doc, :name) == :rss do + {true, doc} + else + false + end end true -> diff --git a/lib/xml.ex b/lib/xml.ex index de8d397..c61fc71 100644 --- a/lib/xml.ex +++ b/lib/xml.ex @@ -9,12 +9,16 @@ defmodule FeedParser.XML do defrecord :xmlAttribute, extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl") defrecord :xmlText, extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl") - @spec parse(data :: String.t()) :: tuple() + @spec parse(data :: String.t()) :: {:ok, tuple()} | {:error, String.t()} def parse(data) do {doc, _} = - data - |> :binary.bin_to_list() - |> :xmerl_scan.string() + try do + data + |> :binary.bin_to_list() + |> :xmerl_scan.string() + catch + :exit, reason -> {:error, "parsing XML failed: #{inspect(reason)}"} + end doc end