mirror of
https://github.com/Tafkas/fritzbox-munin.git
synced 2023-10-10 13:36:55 +02:00
use lxml for parsing and better error handling
This commit is contained in:
parent
a2fb8f7dc7
commit
bfdeb190f3
@ -14,80 +14,94 @@
|
|||||||
This plugin supports the following munin configuration parameters:
|
This plugin supports the following munin configuration parameters:
|
||||||
#%# family=auto contrib
|
#%# family=auto contrib
|
||||||
#%# capabilities=autoconf
|
#%# capabilities=autoconf
|
||||||
|
|
||||||
|
The initial script was inspired by
|
||||||
|
https://www.linux-tips-and-tricks.de/en/programming/389-read-data-from-a-fritzbox-7390-with-python-and-bash
|
||||||
|
framp at linux-tips-and-tricks dot de
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import httplib
|
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
from xml.dom import minidom
|
|
||||||
|
|
||||||
USER_AGENT = "Mozilla/5.0 (U; Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0"
|
import requests
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0"
|
||||||
|
|
||||||
|
|
||||||
def get_sid(server, password, port=80):
|
def get_session_id(server, password, port=80):
|
||||||
"""Obtains the sid after login into the fritzbox"""
|
"""Obtains the session id after login into the Fritzbox.
|
||||||
conn = httplib.HTTPConnection(server + ':' + str(port))
|
See https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID.pdf
|
||||||
|
for deteils (in German).
|
||||||
|
|
||||||
|
:param server: the ip address of the Fritzbox
|
||||||
|
:param password: the password to log into the Fritzbox webinterface
|
||||||
|
:param port: the port the Fritzbox webserver runs on
|
||||||
|
:return: the session id
|
||||||
|
"""
|
||||||
|
|
||||||
headers = {"Accept": "application/xml",
|
headers = {"Accept": "application/xml",
|
||||||
"Content-Type": "text/plain",
|
"Content-Type": "text/plain",
|
||||||
"User-Agent": USER_AGENT}
|
"User-Agent": USER_AGENT}
|
||||||
|
|
||||||
initial_page = '/login_sid.lua'
|
url = 'http://{}:{}/login_sid.lua'.format(server, port)
|
||||||
conn.request("GET", initial_page, '', headers)
|
try:
|
||||||
response = conn.getresponse()
|
r = requests.get(url, headers=headers)
|
||||||
data = response.read()
|
r.raise_for_status()
|
||||||
if response.status != 200:
|
except requests.exceptions.HTTPError as err:
|
||||||
print "%s %s" % (response.status, response.reason)
|
print(err)
|
||||||
sys.exit(0)
|
sys.exit(1)
|
||||||
else:
|
|
||||||
xml_data = minidom.parseString(data)
|
root = etree.fromstring(r.content)
|
||||||
sid_info = xml_data.getElementsByTagName('SID')
|
session_id = root.xpath('//SessionInfo/SID/text()')[0]
|
||||||
sid = sid_info[0].firstChild.data
|
if session_id == "0000000000000000":
|
||||||
if sid == "0000000000000000":
|
challenge = root.xpath('//SessionInfo/Challenge/text()')[0]
|
||||||
challenge_info = xml_data.getElementsByTagName('Challenge')
|
challenge_bf = ('{}-{}'.format(challenge, password)).decode('iso-8859-1').encode('utf-16le')
|
||||||
challenge = challenge_info[0].firstChild.data
|
|
||||||
challenge_bf = (challenge + '-' + password).decode('iso-8859-1').encode('utf-16le')
|
|
||||||
m = hashlib.md5()
|
m = hashlib.md5()
|
||||||
m.update(challenge_bf)
|
m.update(challenge_bf)
|
||||||
response_bf = challenge + '-' + m.hexdigest().lower()
|
response_bf = '{}-{}'.format(challenge, m.hexdigest().lower())
|
||||||
else:
|
else:
|
||||||
return sid
|
return session_id
|
||||||
|
|
||||||
headers = {"Accept": "text/html,application/xhtml+xml,application/xml",
|
headers = {"Accept": "text/html,application/xhtml+xml,application/xml",
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
"User-Agent": USER_AGENT}
|
"User-Agent": USER_AGENT}
|
||||||
|
|
||||||
login_page = "/login_sid.lua?&response=" + response_bf
|
url = 'http://{}:{}/login_sid.lua?&response={}'.format(server, port, response_bf)
|
||||||
conn.request("GET", login_page, '', headers)
|
try:
|
||||||
response = conn.getresponse()
|
r = requests.get(url, headers=headers)
|
||||||
data = response.read()
|
r.raise_for_status()
|
||||||
if response.status != 200:
|
except requests.exceptions.HTTPError as err:
|
||||||
print "%s %s" % (response.status, response.reason)
|
print(err)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
root = etree.fromstring(r.content)
|
||||||
|
session_id = root.xpath('//SessionInfo/SID/text()')[0]
|
||||||
|
if session_id == "0000000000000000":
|
||||||
|
print("ERROR - No SID received because of invalid password")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
return session_id
|
||||||
sid = re.search("<SID>(.*?)</SID>", data).group(1)
|
|
||||||
if sid == "0000000000000000":
|
|
||||||
print "ERROR - No SID received because of invalid password"
|
|
||||||
sys.exit(0)
|
|
||||||
return sid
|
|
||||||
|
|
||||||
|
|
||||||
def get_page(server, sid, page, port=80):
|
def get_page_content(server, session_id, page, port=80):
|
||||||
"""Fetches a page from the Fritzbox and returns its content"""
|
"""Fetches a page from the Fritzbox and returns its content
|
||||||
conn = httplib.HTTPConnection(server + ':' + str(port))
|
|
||||||
|
:param server: the ip address of the Fritzbox
|
||||||
|
:param session_id: a valid session id
|
||||||
|
:param page: the page you are regquesting
|
||||||
|
:param port: the port the Fritzbox webserver runs on
|
||||||
|
:return: the content of the page
|
||||||
|
"""
|
||||||
|
|
||||||
headers = {"Accept": "application/xml",
|
headers = {"Accept": "application/xml",
|
||||||
"Content-Type": "text/plain",
|
"Content-Type": "text/plain",
|
||||||
"User-Agent": USER_AGENT}
|
"User-Agent": USER_AGENT}
|
||||||
|
|
||||||
page_with_sid = page + "?sid=" + sid
|
url = 'http://{}:{}/{}?sid={}'.format(server, port, page, session_id)
|
||||||
conn.request("GET", page_with_sid, '', headers)
|
try:
|
||||||
response = conn.getresponse()
|
r = requests.get(url, headers=headers)
|
||||||
data = response.read()
|
r.raise_for_status()
|
||||||
if response.status != 200:
|
except requests.exceptions.HTTPError as err:
|
||||||
print "%s %s" % (response.status, response.reason)
|
print(err)
|
||||||
print data
|
sys.exit(1)
|
||||||
sys.exit(0)
|
return r.content
|
||||||
else:
|
|
||||||
return data
|
|
||||||
|
Loading…
Reference in New Issue
Block a user