123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- #!/usr/bin/env python
- from io import BytesIO, open
- import struct
- import hashlib
- from dbparse import DBParser
- import sys
- MAGIC = 0x52474442
- VERSION = 19
- if len(sys.argv) < 3:
- print('Usage: %s output-file input-file [key-file]' % sys.argv[0])
- sys.exit(2)
- def create_rules(countries):
- result = {}
- for c in countries.values():
- for rule in c.permissions:
- result[rule] = 1
- return list(result)
- def create_collections(countries):
- result = {}
- for c in countries.values():
- result[c.permissions] = 1
- return list(result)
- def be32(output, val):
- output.write(struct.pack('>I', val))
- class PTR(object):
- def __init__(self, output):
- self._output = output
- self._pos = output.tell()
- be32(output, 0xFFFFFFFF)
- def set(self, val=None):
- if val is None:
- val = self._output.tell()
- self._offset = val
- pos = self._output.tell()
- self._output.seek(self._pos)
- be32(self._output, val)
- self._output.seek(pos)
- def get(self):
- return self._offset
- p = DBParser()
- countries = p.parse(open(sys.argv[2], 'r', encoding='utf-8'))
- countrynames = list(countries)
- countrynames.sort()
- power = []
- bands = []
- for alpha2 in countrynames:
- for perm in countries[alpha2].permissions:
- if not perm.freqband in bands:
- bands.append(perm.freqband)
- if not perm.power in power:
- power.append(perm.power)
- rules = create_rules(countries)
- rules.sort()
- collections = create_collections(countries)
- collections.sort()
- output = BytesIO()
- # struct regdb_file_header
- be32(output, MAGIC)
- be32(output, VERSION)
- reg_country_ptr = PTR(output)
- # add number of countries
- be32(output, len(countries))
- siglen = PTR(output)
- power_rules = {}
- for pr in power:
- power_rules[pr] = output.tell()
- pr = [int(v * 100.0) for v in (pr.max_ant_gain, pr.max_eirp)]
- # struct regdb_file_power_rule
- output.write(struct.pack('>II', *pr))
- freq_ranges = {}
- for fr in bands:
- freq_ranges[fr] = output.tell()
- fr = [int(f * 1000.0) for f in (fr.start, fr.end, fr.maxbw)]
- # struct regdb_file_freq_range
- output.write(struct.pack('>III', *fr))
- reg_rules = {}
- for reg_rule in rules:
- freq_range, power_rule = reg_rule.freqband, reg_rule.power
- reg_rules[reg_rule] = output.tell()
- # struct regdb_file_reg_rule
- output.write(struct.pack('>III', freq_ranges[freq_range], power_rules[power_rule],
- reg_rule.flags))
- reg_rules_collections = {}
- for coll in collections:
- reg_rules_collections[coll] = output.tell()
- # struct regdb_file_reg_rules_collection
- coll = list(coll)
- be32(output, len(coll))
- coll.sort()
- for regrule in coll:
- be32(output, reg_rules[regrule])
- # update country pointer now!
- reg_country_ptr.set()
- for alpha2 in countrynames:
- coll = countries[alpha2]
- # struct regdb_file_reg_country
- output.write(struct.pack('>BBxBI', alpha2[0], alpha2[1], coll.dfs_region, reg_rules_collections[coll.permissions]))
- if len(sys.argv) > 3:
- # Load RSA only now so people can use this script
- # without having those libraries installed to verify
- # their SQL changes
- from M2Crypto import RSA
- # determine signature length
- key = RSA.load_key(sys.argv[3])
- hash = hashlib.sha1()
- hash.update(output.getvalue())
- sig = key.sign(hash.digest())
- # write it to file
- siglen.set(len(sig))
- # sign again
- hash = hashlib.sha1()
- hash.update(output.getvalue())
- sig = key.sign(hash.digest())
- output.write(sig)
- else:
- siglen.set(0)
- outfile = open(sys.argv[1], 'wb')
- outfile.write(output.getvalue())
|