#!/usr/bin/env python import sys import os.path import zipfile from lxml import etree from random import randint from binascii import hexlify as _hexlify # source of random data #randdev = '/dev/urandom' randdev = '/dev/random' #randdev = '/dev/hwrng' #randdev = '/var/run/rtl_entropy.fifo' # 3 digit book id #id = '%03d' % randint(0, 999) # 2 digit book id with 1 digit checksum id = '%02d' % randint(0, 99) id += str((10 - int(id[0]) - int(id[1])) % 10) def chartodigit(char): seed = int(_hexlify(char), 16) max = str(256**len(char)-1) count = len(max) for i in range(1, count): div = int(max[:i].ljust(count, '0')) if seed < div: return str(seed).zfill(count-i)[-(count-i):] return '' infile = 'otp-template.odt' outfile = 'otp-in-' + id + '.odt' if os.path.exists(outfile): print >> sys.stderr, outfile, 'already exists' sys.exit(1) # get 4125 digits from 1713 bytes rng = open(randdev, 'rb') digits = '' for i in range(6): digits += chartodigit(rng.read(267)) digits += chartodigit(rng.read(49)) digits += chartodigit(rng.read(49)) digits += chartodigit(rng.read(13)) while len(digits) < 4125: digits += chartodigit(rng.read(5)) rng.close digits = digits[:4125] # add spaces every 5 digits n = 5 temp = '' for i in range(0, len(digits), n): temp += digits[i:i+n] + ' ' digits = temp # split into 275 digit blocks n = 330 # 275 digits + 55 spaces pages = [digits[i:i+n] for i in range(0, len(digits), n)] # sort pages pages.sort() # print #order = [6, 10, 14, 0, 3, 7, 11, 1, 4, 8, 12, 2, 5, 9, 13] #for i in order: # print '\n','\n',pages[i] # open zip files template = zipfile.ZipFile(infile) otp = zipfile.ZipFile(outfile, 'w', zipfile.ZIP_DEFLATED) # parse template content = etree.parse(template.open('content.xml')) # replace text text = content.xpath('//text:p', namespaces={'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'}) for e in text: if e.text != None: # replace pages if e.text[:4] == 'PAGE': e.text = pages[int(e.text[4:])] for c in e: # replace book number if c.tail == '??? ': c.tail = id + ' ' # save new book for item in template.infolist(): buffer = template.read(item.filename) if (item.filename != 'content.xml'): otp.writestr(item, buffer) else: otp.writestr('content.xml', etree.tostring(content, xml_declaration=True, encoding='UTF-8')) # close files template.close() otp.close()