示例#1
0
def _parse_uptime_to_seconds(html):
    regex = "Uptime</b></td>(?:.+?)<td width=60%><font size=2>([0-9]+)day:([0-9]+)h:([0-9]+)m:([0-9]+)s</td>"
    regex_uptime = re.compile(regex, re.DOTALL)

    match_object = regex_uptime.search(html)

    if match_object is None:
        raise RouterParseError("Cannot _parse uptime")

    days, hours, minutes, seconds = map(int, match_object.groups())

    return days * 86400 + hours * 3600 + minutes * 60 + seconds
示例#2
0
def _parse_wireless_settings(html_main, html_basic, html_advanced, html_security):
    obj = WirelessSettings()
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WEP64)
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WEP128)
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WPA)
    obj.add_security_support(WirelessSettings.SECURITY_TYPE_WPA2)

    obj.set_auto_channel_support(False)

    # the naming of the radio button is weird!
    is_enabled = '<input type="radio" name="wlanDisabled" value="yes" checked>' in html_main
    obj.set_enabled_status(is_enabled)


    match_object = re.compile('document.wlanSetup.ssid.value="(.+?)";').search(html_basic)
    if match_object is None:
        raise RouterParseError('Cannot determine SSID')
    obj.set_ssid(match_object.group(1))

    match_object = re.compile('var defaultChan = ([0-9]+)[\s\n]').search(html_basic)
    if match_object is None:
        raise RouterParseError('Cannot determine channel')
    obj.set_channel(int(match_object.group(1)))

    is_broadcasting_ssid = '<input type="radio" name="hiddenSSID" value="no" checked>' in html_advanced
    obj.set_ssid_broadcast_status(is_broadcasting_ssid)

    match_object = re.compile('methodVal = ([0-3]);').search(html_security)
    if match_object is None:
        raise RouterParseError('Cannot determine security type')
    security_type = int(match_object.group(1))
    if security_type == 0:
        obj.set_security_type(obj.__class__.SECURITY_TYPE_NONE)
    elif security_type == 1: # WEP of some sort
        match_object = re.compile('var wepTbl =\s+new Array\("([0-9]+)"\);').search(html_security)
        if match_object is None:
            raise RouterParseError('Cannot determine WEP bit length')
        if int(match_object.group(1)) in (0, 1):
            obj.set_security_type(obj.__class__.SECURITY_TYPE_WEP64)
        else:
            obj.set_security_type(obj.__class__.SECURITY_TYPE_WEP128)

        # WEP passwords cannot be extracted! It shows "***" only
    elif security_type == 2: # WPA of some sort
        match_object = re.compile('var wpaCipherTbl =(?:\s+)?new Array\("([0-9]+)"\);').search(html_security)
        if match_object is None:
            raise RouterParseError('Cannot determine WPA type')
        if int(match_object.group(1)) in (0, 1, 3): # 0, 1 = WPA; 3 = mixed
            obj.set_security_type(obj.__class__.SECURITY_TYPE_WPA)
        else: # all other values are WPA2 only
            obj.set_security_type(obj.__class__.SECURITY_TYPE_WPA2)

        match_object = re.compile('var pskValueTbl = new Array\("(.+?)"\);').search(html_security)
        if match_object is None:
            raise RouterParseError('Cannot determine WPA password')
        obj.set_password(match_object.group(1))
    else: # 3 = WPA Radius
        raise NotImplementedError('Security type not supported')

    return obj
示例#3
0
def _parse_dhcp_settings(html):
    settings = DHCPServerSettings()
    settings.set_enabled_status(
        '<option selected value="2">Server</option>' in html)

    match_object = re.compile(
        '<input type="text" name="dhcpRangeStart" size="12" maxlength="15" value="(.+?)">'
    ).search(html)
    if match_object is None:
        raise RouterParseError("Cannot determine DHCP start IP")
    settings.set_ip_start(match_object.group(1))

    match_object = re.compile(
        '<input type="text" name="dhcpRangeEnd" size="12" maxlength="15" value="(.+?)">'
    ).search(html)
    if match_object is None:
        raise RouterParseError("Cannot determine DHCP end IP")
    settings.set_ip_end(match_object.group(1))

    settings.ensure_valid()

    return settings
示例#4
0
def _parse_dhcp_settings(html):
    is_enabled = 'var choice= 2 ;' in html

    regex = re.compile('<input type=text name="dhcpRangeStart" size=16 '
                       'maxlength=15 value="(.+?)"'
                       '(?:.+?)'
                       '<input type=text name="dhcpRangeEnd" size=16 '
                       'maxlength=15 value="(.+?)"', re.DOTALL)
    match_object = regex.search(html)
    if match_object is None:
        raise RouterParseError('Cannot determine DMZ range!')
    for ip in match_object.groups():
        if not validator.is_valid_ip_address(ip):
            raise RouterParseError('Invalid DHCP IP: %s' % ip)

    ip_start, ip_end = match_object.groups()
    obj = DHCPServerSettings()
    obj.set_enabled_status(is_enabled)
    obj.set_ip_start(ip_start)
    obj.set_ip_end(ip_end)
    obj.ensure_valid()
    return obj
示例#5
0
def _parse_uptime_to_seconds(string):
    """Parses an uptime string such as `0 day(s) 10:11:12`
    or `0 days 10:18:45` to seconds.

    These 2 strings both appear in the router interface.
    """
    regex = re.compile('([0-9]+) (?:days|day\(s\)) ([0-9]+):([0-9]+):([0-9]+)')
    match_object = regex.match(string)
    if match_object is None:
        raise RouterParseError('Invalid uptime string `%s`' % str(string))

    days, hours, minutes, seconds = map(int, match_object.groups())
    return days * 86400 + hours * 3600 + minutes * 60 + seconds
示例#6
0
def _parse_dhcp_settings(html):
    regex = re.compile('name="dhcpRange(?:Start|End)" size="15" maxlength="15" value="(.+?)"')
    try:
        ip_start, ip_end = regex.findall(html)
    except ValueError:
        raise RouterParseError('Cannot find DHCP start/end range')
    else:
        settings = DHCPServerSettings()
        settings.set_ip_start(ip_start)
        settings.set_ip_end(ip_end)
        settings.set_enabled_status('<option selected value="2"><script>dw(Enable)</script></option>' in html)
        settings.ensure_valid()

        return settings
示例#7
0
def _parse_addr_reservation_list(html):
    regex = '//\s+nvram = \{(.+?)\};\n\nif '
    match_object = re.compile(regex, re.DOTALL).search(html)
    if match_object is None:
        raise RouterParseError('Cannot parse reservation list')

    array = _parse_data_structure(match_object.group(1))
    try:
        lst = DHCPReservationList()
        lst.set_reboot_requirement_status(False)

        for part in array['dhcpd_static'].split('>'):
            if part == '':
                continue
            mac, ip, name = part.split('<')
            item = DHCPReservationListItem()
            item.set_mac(mac)
            item.set_ip(ip)
            lst.append(item)
    except (KeyError, ValueError):
        raise RouterParseError('Bad nvram for reservation list')

    return lst
示例#8
0
文件: w268r.py 项目: wblyy/roscraco
def _parse_connected_clients_list(html):
    dhcp_list = re.compile('var dhcpList=new Array\((.*)\);').search(html)
    if dhcp_list is None:
        raise RouterParseError('Cannot find DHCP list.')
    dhcp_list = dhcp_list.group(1)

    results = re.compile("'(.+?);(.+?);(.+?);[01];(\d+)'").findall(dhcp_list)
    lst = ConnectedClientsList()
    for client_name, ip, mac, lease_time in results:
        if not validator.is_valid_ip_address(ip):
            raise RouterParseError('Invalid IP address: %s' % ip)
        if not validator.is_valid_mac_address(mac):
            raise RouterParseError('Invalid MAC address: %s' % mac)

        item = ConnectedClientsListItem()
        item.set_client_name(client_name)
        item.set_mac(converter.normalize_mac(mac))
        item.set_ip(ip)
        item.set_lease_time(int(lease_time))

        lst.append(item)

    return lst
示例#9
0
def _parse_pppoe_online_time(status_js):
    # Ensure that we're using PPPoE
    nvram = _parse_js_structure(status_js, 'nvram')
    try:
        if nvram['wan_proto'] != 'pppoe':
            return None
        regex = "stats.wanuptime = '(\d+) days?, (\d+):(\d+):(\d+)';"
        match_object = re.compile(regex).search(status_js)
        if match_object is None:
            return None
        days, hours, minutes, seconds = map(int, match_object.groups())
        return days * 86400 + hours * 3600 + minutes * 60 + seconds
    except (KeyError, ValueError):
        raise RouterParseError('Cannot parse pppoe online time!')
示例#10
0
def _parse_connected_clients_list(html):
    regex_dhcp_list = "<tr class=table2 align=center><td><font size=2>(.+?)</td><td><font size=2>(.+?)</td>"
    lst = ConnectedClientsList()

    for id, (ip, mac) in enumerate(re.findall(regex_dhcp_list, html), start=1):
        if ip == "None":
            # this entry is added when there are no connected clients
            break

        if not validator.is_valid_ip_address(ip):
            raise RouterParseError('Invalid IP address: %s' % ip)

        if not validator.is_valid_mac_address(mac):
            raise RouterParseError('Invalid MAC address: %s' % mac)

        item = ConnectedClientsListItem()
        item.set_client_name('Client %d' % id)
        item.set_mac(converter.normalize_mac(mac))
        item.set_ip(ip)
        item.set_lease_time(0)

        lst.append(item)

    return lst
示例#11
0
def _parse_pppoe_online_time(html):
    # <TD NOWRAP width="50%">23:05:47</td>
    # or
    # <TD NOWRAP width="50%"> 1 day 00:41:36</td>
    # or
    # <TD NOWRAP width="50%"> 10 days 00:41:36</td>

    regex = re.compile('<B>Connection Time</B>(?:.+?)>(?: ([0-9]+) days? )?([0-9]+):([0-9]+):([0-9]+)</td>', re.DOTALL)
    match_object = regex.search(html)
    if match_object is None:
        raise RouterParseError('Cannot parse online time information')

    days, hours, minutes, seconds = map(lambda x: int(x) if x is not None else 0, match_object.groups())

    return days * 86400 + hours * 3600 + minutes * 60 + seconds
示例#12
0
def generate_wireless_settings_link(html):
    """The link with the wireless settings is generated
    dynamically depending on 2 variables find on every page.
    These are the ``es0`` and ``cskm`` variables.
    What ``es0`` controls is not yet known, but ``cskm``
    represents the type of wireless security that's setup now.
    """
    regex = re.compile('es0="([0-9]+)";(?:.+?)cskm="(.+?)";', re.DOTALL)
    match_object = regex.search(html)
    if match_object is None:
        raise RouterParseError('Cannot parse wireless link variables!')
    es0, cskm = match_object.groups()
    link_value, security_type = _resolve_wireless_security_type(cskm)
    from time import time
    return security_type, 'wlan.htm?rc=&rf=%s&_=&_=&_=&_=&_=%s&_=&ZT=%d' % (
        link_value, es0, time())
示例#13
0
文件: w268r.py 项目: wblyy/roscraco
def _parse_addr_reservation_list(html):
    reservations = re.compile('var StaticList = new Array\((.*)\);').search(html)
    if reservations is None:
        raise RouterParseError('Cannot find reservations list.')
    reservations_list = reservations.group(1)

    results = re.compile(';(.+?);(.+?);([12]);(\d+)').findall(reservations_list)
    reservation_list = DHCPReservationList()
    reservation_list.set_reboot_requirement_status(False)
    for ip, mac, mac_bind, _time in results:
        item = DHCPReservationListItem()
        item.set_mac(converter.normalize_mac(mac))
        item.set_ip(ip)
        item.set_enabled_status(mac_bind == '1')
        reservation_list.append(item)
    return reservation_list
示例#14
0
def _parse_traffic_stats(html):
    # The monthly_history array contains one or more other arrays.
    # Each of those arrays contains 3 items (like a 3-tuple), which are:
    #   1. time data, for which 2. and 3. are
    #   2. traffic received in KB
    #   3. traffic sent in KB
    regex = 'monthly_history = \[\n(.+?)\];'
    match_object = re.compile(regex).search(html)
    if match_object is not None:
        try:
            array = ast.literal_eval('[%s]' % match_object.group(1))
            kb_recv, kb_sent = 0, 0
            for time_data, recv, sent in array:
                kb_recv += recv
                kb_sent += sent
            return TrafficStats(kb_recv * 1024, kb_sent * 1024, 0, 0)
        except (KeyError, ValueError):
            raise RouterParseError('Cannot parse traffic stats!')
    return TrafficStats(0, 0, 0, 0)
示例#15
0
def _parse_js_structure(js, name):
    """Extracts a javascript object by its name.

    Here's what it looks like initially:
    //
    object_name = {
        some stuff here
    };

    //

    We're parsing the broken JSON inside, and
    we're returning a dictionary.
    """

    regex = '//\n%s = \{(.+?)\};\n\n//' % name
    match_object = re.compile(regex, re.DOTALL).search(js)
    if match_object is None:
        raise RouterParseError('Cannot parse main structure data')
    return _parse_data_structure(match_object.group(1))
示例#16
0
def _parse_dmz_settings(html):
    regex = "//\s+nvram = \{(.+?)\};\n\nvar lipp = '(.+?)';"
    match_object = re.compile(regex, re.DOTALL).search(html)
    if match_object is None:
        raise RouterParseError('Cannot parse DMZ settings')

    bad_json_settings, lipp = match_object.groups()
    nvram = _parse_data_structure(bad_json_settings)

    ip = nvram['dmz_ipaddr']
    if '.' not in ip:
        # it's the last part only.. it's shortened
        # and the rest is in lipp
        ip = lipp + ip

    obj = DMZSettings()
    obj.set_supported_status(True)
    obj.set_reboot_requirement_status(False)
    obj.set_enabled_status(nvram['dmz_enable'] == '1')
    obj.set_ip(ip)
    obj.ensure_valid()
    return obj
示例#17
0
def _parse_connected_clients_list(html):
    lst = ConnectedClientsList()

    regex = "<tr>(?:.+?)<span class=\"ttext\">(.+?)</span>(?:.+?)<span class=\"ttext\">(.+?)</span>(?:.+?)<span class=\"ttext\">(.+?)</span>(?:.+?)</tr>"

    for ip, name, mac in re.compile(regex, re.DOTALL).findall(html):
        if ip == '--':
            # I've seen such entries on WGR614v7 only.. let's ignore them
            continue

        if not validator.is_valid_ip_address(ip):
            raise RouterParseError('Invalid IP address: %s' % ip)

        item = ConnectedClientsListItem()
        item.set_client_name(name)
        item.set_mac(converter.normalize_mac(mac))
        item.set_ip(ip)
        item.set_lease_time(None)  # no lease time information available

        lst.append(item)

    return lst
示例#18
0
def _parse_connected_clients_list(html):
    # the last 2 elements of the data array are not needed
    result = _extract_js_array_data(html, 'DHCPDynList')[:-2]

    lst = ConnectedClientsList()

    # each 4 subsequent items are related (client_name, mac_address, ip, lease_time)
    for client_name, mac, ip, lease_time in split_in_groups(result, 4):
        if not validator.is_valid_ip_address(ip):
            raise RouterParseError('Invalid IP address: %s' % ip)

        item = ConnectedClientsListItem()
        item.set_client_name(client_name)
        item.set_mac(converter.normalize_mac(mac))
        item.set_ip(ip)

        if lease_time == 'Permanent':
            item.set_lease_time(item.__class__.LEASE_TIME_PERMANENT)
        else:
            item.set_lease_time(_parse_lease_time(lease_time))

        lst.append(item)

    return lst
示例#19
0
def _parse_uptime(status_js):
    data = _parse_js_structure(status_js, 'sysinfo')
    try:
        return int(data['uptime'])
    except (KeyError, ValueError):
        raise RouterParseError('Cannot parse uptime!')
示例#20
0
文件: w268r.py 项目: wblyy/roscraco
def _parse_mac_address(html):
    match_obj = re.compile('wan_mac="(.+?)";').search(html)
    if match_obj is None:
        raise RouterParseError('Cannot determine WAN mac address')
    return converter.normalize_mac(match_obj.group(1))
示例#21
0
文件: w268r.py 项目: wblyy/roscraco
def _parse_pppoe_online_time(html):
    match_obj = re.compile('conntime="(.+?)";').search(html)
    if match_obj is None:
        raise RouterParseError('Cannot determine connection time')
    return int(match_obj.group(1))
示例#22
0
def _parse_wireless_settings(html_basic, html_advanced, html_security,
                             html_wep):
    settings = WirelessSettings()
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WEP64)
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WEP128)
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WPA)
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WPA2)

    match_object = re.compile("var wps_ssid_old='(.+?)';").search(html_basic)
    if match_object is None:
        raise RouterParseError("Cannot find SSID!")
    settings.set_ssid(match_object.group(1))

    match_object = re.compile("var wps_disabled=(0|1);").search(html_basic)
    if match_object is None:
        raise RouterParseError("Cannot determine wireless enabled status!")
    settings.set_enabled_status(match_object.group(1) == "0")

    match_object = re.compile("defaultChan\[wlan_idx\]=(.+?);").search(
        html_basic)
    if match_object is None:
        raise RouterParseError("Cannot determine wireless channel!")
    settings.set_channel(int(match_object.group(1)))

    if "name=\"hiddenSSID\" value=\"no\"checked" not in html_advanced:
        settings.set_ssid_broadcast_status(False)

    # This is the security type (WEP, WPA, WPA2..)
    match_object = re.compile("var wps_encrypt_old=([0-4]);").search(
        html_security)
    if match_object is None:
        raise RouterParseError("Cannot determine security type!")
    security_type = int(match_object.group(1))

    if security_type == 1:  # WEP
        match_object = re.compile("var wps_wep_keylen_old='([1-2])';").search(
            html_wep)
        if match_object is None:
            raise RouterParseError("Cannot determine WEP key length!")

        if int(match_object.group(1)) == 1:  # 64bit
            settings.set_security_type(settings.__class__.SECURITY_TYPE_WEP64)
        else:  # 128bit or something new that we don't handle
            settings.set_security_type(settings.__class__.SECURITY_TYPE_WEP128)
    elif security_type == 2:  # WPA-PSK
        settings.set_security_type(settings.__class__.SECURITY_TYPE_WPA)
    elif security_type == 4:  # WPA2-PSK
        settings.set_security_type(settings.__class__.SECURITY_TYPE_WPA2)
    else:  # Either 0=No security or something else, which we don't handle
        settings.set_security_type(settings.__class__.SECURITY_TYPE_NONE)

    if settings.security_type_is_wpa:
        match_object = re.compile("var wps_psk_old='(.+?)';").search(
            html_security)
        if match_object is None:
            raise RouterParseError('Cannot determine wireless password!')
        settings.set_password(match_object.group(1))
    elif settings.security_type_is_wep:
        # WEP passwords are rendered as '****' on the page
        settings.set_password(None)
    else:  # No security or something else
        settings.set_password("")

    return settings
示例#23
0
def _parse_mac_address(status_js):
    nvram = _parse_js_structure(status_js, 'nvram')
    try:
        return converter.normalize_mac(nvram['wan_hwaddr'])
    except KeyError:
        raise RouterParseError('Cannot parse MAC address!')
示例#24
0
def _parse_dns_servers(data_array):
    try:
        dns_ips = data_array[11].split(' , ')
        return [ip.strip(' ') for ip in dns_ips if validator.is_valid_ip_address(ip)]
    except IndexError, e:
        raise RouterParseError('Cannot access the array index: %s' % repr(e))
示例#25
0
def _parse_mac_address(data_array):
    try:
        return converter.normalize_mac(data_array[1])
    except IndexError, e:
        raise RouterParseError('Cannot access the array index: %s' % repr(e))
示例#26
0
def _parse_uptime(data_array):
    try:
        return int(data_array[4])
    except IndexError, e:
        raise RouterParseError('Cannot access the array index: %s' % repr(e))
示例#27
0
def _parse_http_id(html):
    regex = "src='status-data.jsx\?_http_id=(TID(?:.+?))'>"
    match_object = re.compile(regex).search(html)
    if match_object is None:
        raise RouterParseError('Cannot determine http id!')
    return match_object.group(1)
示例#28
0
文件: w268r.py 项目: wblyy/roscraco
def _parse_uptime(html):
    match_obj = re.compile('uptime=\s"(.+?)";').search(html)
    if match_obj is None:
        raise RouterParseError('Cannot determine uptime')
    return int(match_obj.group(1))
示例#29
0
def _parse_wireless_settings(security_type, html_basic, html_advanced):
    settings = WirelessSettings()
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WEP64)
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WEP128)
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WPA)
    settings.add_security_support(WirelessSettings.SECURITY_TYPE_WPA2)
    settings.set_ascii_wep_password_support_status(False)
    settings.set_reboot_requirement_status(False)

    # Determine the submit token.. some WGR614v9 models have such a token
    # It's either some form of CSRF protection or something else..
    match_object = re.compile(
        '<form method="POST" action="wireless.cgi\?id=([0-9]+)">').search(
            html_basic)
    if match_object is None:
        settings.set_internal_param('submit_token', None)
    else:
        settings.set_internal_param('submit_token', int(match_object.group(1)))

    if security_type == 'WEP':
        if '<option selected value="1">64bit</option>' in html_basic:
            settings.set_security_type(WirelessSettings.SECURITY_TYPE_WEP64)
        elif '<option selected value="2">128bit</option>' in html_basic:
            settings.set_security_type(WirelessSettings.SECURITY_TYPE_WEP128)
        else:
            raise RouterParseError('Cannot determine WEP key length')

        settings.set_password(__parse_wep_password(html_basic))
    elif security_type == 'WPA-PSK':
        settings.set_security_type(WirelessSettings.SECURITY_TYPE_WPA)
        # password extraction is done below
    elif security_type in ('WPA2-PSK', 'WPA-AUTO-PSK'):
        settings.set_security_type(WirelessSettings.SECURITY_TYPE_WPA2)
        # password extraction is done below
    else:  # security_type = `Disable` or something else that we don't handle..
        settings.set_security_type(WirelessSettings.SECURITY_TYPE_NONE)
        settings.set_password('')

    if settings.security_type_is_wpa:
        regex = re.compile(
            '<input type="text" name="passphrase" size=20 maxLength=64 value="(.+?)" onFocus'
        )
        match_object = regex.search(html_basic)
        if match_object is None:
            raise RouterParseError('Cannot determine WPA password')
        password = match_object.group(1)
        if '*****' in password:
            # WGR614v7 doesn't present us with the real password, but substitutes it with * chars
            # that's not the case for v8 and v9 though
            password = None
        settings.set_password(password)

    regex = re.compile('<input type="text" name="ssid" value="(.+?)"')
    match_object = regex.search(html_basic)
    if match_object is None:
        raise RouterParseError('Cannot determine SSID')
    settings.set_ssid(match_object.group(1))

    regex = re.compile(
        '<input type="hidden" name="initChannel" value="([0-9]+)">')
    match_object = regex.search(html_basic)
    if match_object is None:
        raise RouterParseError('Cannot determine channel')
    settings.set_channel(int(match_object.group(1)))

    if '<input type="checkbox"  checked name="enable_ap" value="enable_ap">' in html_advanced:
        is_enabled = True
    else:
        is_enabled = False
    settings.set_enabled_status(is_enabled)

    if '<input type="checkbox"  checked name="ssid_bc" value="ssid_bc">' in html_advanced:
        is_broadcasting = True
    else:
        is_broadcasting = False
    settings.set_ssid_broadcast_status(is_broadcasting)

    if '<input type="checkbox"  checked name="enable_wmm" value="enable_wmm">' in html_advanced:
        is_wmm_enabled = True
    else:
        is_wmm_enabled = False
    settings.set_internal_param('enable_wmm', is_wmm_enabled)

    regex = re.compile(
        "Select Region(?:.+?)<option selected value=\"([0-9]+)\">")
    match_object = regex.search(html_basic)
    if match_object is None:
        raise RouterParseError('Cannot determine Region value')
    settings.set_internal_param('WRegion', int(match_object.group(1)))

    return settings
示例#30
0
文件: wr740n_.py 项目: ovt00/roscraco
def _parse_traffic_stats(data_array):
    data_array = data_array[:4]
    if len(data_array) != 4:
        raise RouterParseError('Unexpected stats size: %d' % len(data_array))
    data_array = map(lambda x: int(x.replace(',', '')), data_array)
    return TrafficStats(*data_array)