diff --git a/homeassistant/components/notify/twilio_call.py b/homeassistant/components/notify/twilio_call.py index 8bc9185e789..37068d6e220 100644 --- a/homeassistant/components/notify/twilio_call.py +++ b/homeassistant/components/notify/twilio_call.py @@ -7,6 +7,7 @@ https://home-assistant.io/components/notify.twilio_call/ import logging import urllib + import voluptuous as vol import homeassistant.helpers.config_validation as cv @@ -41,6 +42,57 @@ def get_service(hass, config, discovery_info=None): config[CONF_FROM_NUMBER]) +def is_validurl(url): + """Check if the passed url is valid using dperini regex.""" + import re + + ip_middle_oct = u"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5]))" + ip_last_oct = u"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))" + + regex = re.compile( + u"^" + # protocol identifier + u"(?:(?:https?|ftp)://)" + # user:pass authentication + u"(?:\S+(?::\S*)?@)?" + u"(?:" + u"(?P" + # IP address exclusion + # private & local networks + u"(?:(?:10|127)" + ip_middle_oct + u"{2}" + ip_last_oct + u")|" + u"(?:(?:169\.254|192\.168)" + ip_middle_oct + ip_last_oct + u")|" + u"(?:172\.(?:1[6-9]|2\d|3[0-1])" + ip_middle_oct + ip_last_oct + u"))" + u"|" + # IP address dotted notation octets + # excludes loopback network 0.0.0.0 + # excludes reserved space >= 224.0.0.0 + # excludes network & broadcast addresses + # (first & last IP address of each class) + u"(?P" + u"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])" + u"" + ip_middle_oct + u"{2}" + u"" + ip_last_oct + u")" + u"|" + # host name + u"(?:(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)" + # domain name + u"(?:\.(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)*" + # TLD identifier + u"(?:\.(?:[a-z\u00a1-\uffff]{2,}))" + u")" + # port number + u"(?::\d{2,5})?" + # resource path + u"(?:/\S*)?" + # query string + u"(?:\?\S*)?" + u"$", + re.UNICODE | re.IGNORECASE + ) + + return regex.match(url) + + class TwilioCallNotificationService(BaseNotificationService): """Implement the notification service for the Twilio Call service.""" @@ -57,9 +109,13 @@ class TwilioCallNotificationService(BaseNotificationService): _LOGGER.info("At least 1 target is required") return - for target in targets: - twimlet_url = 'http://twimlets.com/message?Me=' + if is_validurl(message): + twimlet_url = message + else: + twimlet_url = 'http://twimlets.com/message?Message=' twimlet_url += urllib.parse.quote(message, safe='') + + for target in targets: self.client.calls.create(to=target, url=twimlet_url, from_=self.from_number)