From 1f7803c5418a59c4717fc67f245e4c0c876bc873 Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Tue, 7 Apr 2020 11:32:43 -0500 Subject: [PATCH] Catch IPPParseError during config flow (#33769) * Update config_flow.py * Update strings.json * Update config_flow.py * squash. --- homeassistant/components/ipp/config_flow.py | 19 +++++++++-- homeassistant/components/ipp/manifest.json | 2 +- homeassistant/components/ipp/strings.json | 3 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/ipp/test_config_flow.py | 38 +++++++++++++++++++++ 6 files changed, 59 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/ipp/config_flow.py b/homeassistant/components/ipp/config_flow.py index e95267e7803..fe0808414ad 100644 --- a/homeassistant/components/ipp/config_flow.py +++ b/homeassistant/components/ipp/config_flow.py @@ -2,7 +2,13 @@ import logging from typing import Any, Dict, Optional -from pyipp import IPP, IPPConnectionError, IPPConnectionUpgradeRequired +from pyipp import ( + IPP, + IPPConnectionError, + IPPConnectionUpgradeRequired, + IPPParseError, + IPPResponseError, +) import voluptuous as vol from homeassistant.config_entries import CONN_CLASS_LOCAL_POLL, ConfigFlow @@ -63,8 +69,12 @@ class IPPFlowHandler(ConfigFlow, domain=DOMAIN): info = await validate_input(self.hass, user_input) except IPPConnectionUpgradeRequired: return self._show_setup_form({"base": "connection_upgrade"}) - except IPPConnectionError: + except (IPPConnectionError, IPPResponseError): return self._show_setup_form({"base": "connection_error"}) + except IPPParseError: + _LOGGER.exception("IPP Parse Error") + return self.async_abort(reason="parse_error") + user_input[CONF_UUID] = info[CONF_UUID] await self.async_set_unique_id(user_input[CONF_UUID]) @@ -100,8 +110,11 @@ class IPPFlowHandler(ConfigFlow, domain=DOMAIN): info = await validate_input(self.hass, self.discovery_info) except IPPConnectionUpgradeRequired: return self.async_abort(reason="connection_upgrade") - except IPPConnectionError: + except (IPPConnectionError, IPPResponseError): return self.async_abort(reason="connection_error") + except IPPParseError: + _LOGGER.exception("IPP Parse Error") + return self.async_abort(reason="parse_error") self.discovery_info[CONF_UUID] = info[CONF_UUID] diff --git a/homeassistant/components/ipp/manifest.json b/homeassistant/components/ipp/manifest.json index 268787043c5..9e491a54896 100644 --- a/homeassistant/components/ipp/manifest.json +++ b/homeassistant/components/ipp/manifest.json @@ -2,7 +2,7 @@ "domain": "ipp", "name": "Internet Printing Protocol (IPP)", "documentation": "https://www.home-assistant.io/integrations/ipp", - "requirements": ["pyipp==0.8.3"], + "requirements": ["pyipp==0.9.0"], "codeowners": ["@ctalkington"], "config_flow": true, "quality_scale": "platinum", diff --git a/homeassistant/components/ipp/strings.json b/homeassistant/components/ipp/strings.json index afd82d1f454..a80a7f2e0ba 100644 --- a/homeassistant/components/ipp/strings.json +++ b/homeassistant/components/ipp/strings.json @@ -26,7 +26,8 @@ "abort": { "already_configured": "This printer is already configured.", "connection_error": "Failed to connect to printer.", - "connection_upgrade": "Failed to connect to printer due to connection upgrade being required." + "connection_upgrade": "Failed to connect to printer due to connection upgrade being required.", + "parse_error": "Failed to parse response from printer." } } } diff --git a/requirements_all.txt b/requirements_all.txt index 0a01f7d6938..af84a372311 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1341,7 +1341,7 @@ pyintesishome==1.7.1 pyipma==2.0.5 # homeassistant.components.ipp -pyipp==0.8.3 +pyipp==0.9.0 # homeassistant.components.iqvia pyiqvia==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3a4a8cd717a..5bdb3034f93 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -524,7 +524,7 @@ pyicloud==0.9.6.1 pyipma==2.0.5 # homeassistant.components.ipp -pyipp==0.8.3 +pyipp==0.9.0 # homeassistant.components.iqvia pyiqvia==0.2.1 diff --git a/tests/components/ipp/test_config_flow.py b/tests/components/ipp/test_config_flow.py index 0682929b7b8..7e16a9fc6e0 100644 --- a/tests/components/ipp/test_config_flow.py +++ b/tests/components/ipp/test_config_flow.py @@ -134,6 +134,44 @@ async def test_zeroconf_connection_upgrade_required( assert result["reason"] == "connection_upgrade" +async def test_user_parse_error( + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker +) -> None: + """Test we abort user flow on IPP parse error.""" + aioclient_mock.post( + "http://192.168.1.31:631/ipp/print", + content="BAD", + headers={"Content-Type": "application/ipp"}, + ) + + user_input = MOCK_USER_INPUT.copy() + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER}, data=user_input, + ) + + assert result["type"] == RESULT_TYPE_ABORT + assert result["reason"] == "parse_error" + + +async def test_zeroconf_parse_error( + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker +) -> None: + """Test we abort zeroconf flow on IPP parse error.""" + aioclient_mock.post( + "http://192.168.1.31:631/ipp/print", + content="BAD", + headers={"Content-Type": "application/ipp"}, + ) + + discovery_info = MOCK_ZEROCONF_IPP_SERVICE_INFO.copy() + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info, + ) + + assert result["type"] == RESULT_TYPE_ABORT + assert result["reason"] == "parse_error" + + async def test_user_device_exists_abort( hass: HomeAssistant, aioclient_mock: AiohttpClientMocker ) -> None: