53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
import olefile, struct, sys
|
|||
|
|
|
||
|
|
def extract_doc_text(filepath):
|
||
|
|
ole = olefile.OleFileIO(filepath)
|
||
|
|
word = ole.openstream('WordDocument').read()
|
||
|
|
flags = struct.unpack('<H', word[0x0A:0x0C])[0]
|
||
|
|
table_name = '1Table' if (flags & 0x0200) else '0Table'
|
||
|
|
fcClx = struct.unpack('<I', word[0x01A2:0x01A6])[0]
|
||
|
|
lcbClx = struct.unpack('<I', word[0x01A6:0x01AA])[0]
|
||
|
|
table = ole.openstream(table_name).read()
|
||
|
|
clx = table[fcClx:fcClx+lcbClx]
|
||
|
|
pos = 0
|
||
|
|
plc_pcd = None
|
||
|
|
while pos < len(clx):
|
||
|
|
clxt = clx[pos]
|
||
|
|
if clxt == 1:
|
||
|
|
cb = struct.unpack('<H', clx[pos+1:pos+3])[0]
|
||
|
|
pos += 3 + cb
|
||
|
|
elif clxt == 2:
|
||
|
|
lcb = struct.unpack('<I', clx[pos+1:pos+5])[0]
|
||
|
|
plc_pcd = clx[pos+5:pos+5+lcb]
|
||
|
|
break
|
||
|
|
else:
|
||
|
|
break
|
||
|
|
if plc_pcd is None:
|
||
|
|
return "NO_PCDT"
|
||
|
|
n = (len(plc_pcd) - 4) // 12
|
||
|
|
cps = [struct.unpack('<I', plc_pcd[i*4:i*4+4])[0] for i in range(n+1)]
|
||
|
|
out = []
|
||
|
|
for i in range(n):
|
||
|
|
cnt = cps[i+1] - cps[i]
|
||
|
|
pcd = plc_pcd[4 + i*12: 4 + i*12 + 12]
|
||
|
|
fc = struct.unpack('<I', pcd[0:4])[0]
|
||
|
|
compressed = (fc & 0x40000000) != 0
|
||
|
|
fcoff = fc & 0x3FFFFFFF
|
||
|
|
if compressed:
|
||
|
|
raw = word[fcoff:fcoff+cnt]
|
||
|
|
txt = raw.decode('gb18030', errors='replace')
|
||
|
|
else:
|
||
|
|
raw = word[fcoff:fcoff+cnt*2]
|
||
|
|
txt = raw.decode('utf-16-le', errors='replace')
|
||
|
|
out.append(txt)
|
||
|
|
return "".join(out)
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
import io
|
||
|
|
for p in sys.argv[1:]:
|
||
|
|
t = extract_doc_text(p)
|
||
|
|
sys.stdout.buffer.write(("="*60 + "\n").encode('utf-8'))
|
||
|
|
sys.stdout.buffer.write(("FILE: " + p + "\n").encode('utf-8'))
|
||
|
|
sys.stdout.buffer.write(t.encode('utf-8'))
|
||
|
|
sys.stdout.buffer.write(("\n" + "="*60 + "\n").encode('utf-8'))
|