Hello community,
here is the log from the commit of package python-msoffcrypto-tool for
openSUSE:Factory checked in at 2019-09-13 14:58:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-msoffcrypto-tool (Old)
and /work/SRC/openSUSE:Factory/.python-msoffcrypto-tool.new.7948 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-msoffcrypto-tool"
Fri Sep 13 14:58:21 2019 rev:2 rq:730104 version:4.10.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-msoffcrypto-tool/python-msoffcrypto-tool.changes
2019-08-05 10:38:57.599315894 +0200
+++
/work/SRC/openSUSE:Factory/.python-msoffcrypto-tool.new.7948/python-msoffcrypto-tool.changes
2019-09-13 14:58:27.273277582 +0200
@@ -1,0 +2,6 @@
+Wed Sep 11 11:10:17 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 4.10.1:
+ * ship license file
+
+-------------------------------------------------------------------
Old:
----
LICENSE.txt
msoffcrypto-tool-4.10.0.tar.gz
New:
----
msoffcrypto-tool-4.10.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-msoffcrypto-tool.spec ++++++
--- /var/tmp/diff_new_pack.LtwLzT/_old 2019-09-13 14:58:29.033277656 +0200
+++ /var/tmp/diff_new_pack.LtwLzT/_new 2019-09-13 14:58:29.033277656 +0200
@@ -18,14 +18,13 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-msoffcrypto-tool
-Version: 4.10.0
+Version: 4.10.1
Release: 0
Summary: Library for decrypting MS Office files
License: MIT
Group: Development/Languages/Python
URL: https://github.com/nolze/msoffcrypto-tool
Source:
https://files.pythonhosted.org/packages/source/m/msoffcrypto-tool/msoffcrypto-tool-%{version}.tar.gz
-Source1:
https://raw.githubusercontent.com/nolze/msoffcrypto-tool/master/LICENSE.txt
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -48,7 +47,6 @@
%setup -q -n msoffcrypto-tool-%{version}
# Delete empty file as of v4.10.0
wc -c msoffcrypto/method/xor_obfuscation.py | sed -n '/^0/{s/^0\s//;p}' |
xargs rm
-cp %{SOURCE1} .
%build
%python_build
++++++ msoffcrypto-tool-4.10.0.tar.gz -> msoffcrypto-tool-4.10.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/LICENSE.txt
new/msoffcrypto-tool-4.10.1/LICENSE.txt
--- old/msoffcrypto-tool-4.10.0/LICENSE.txt 1970-01-01 01:00:00.000000000
+0100
+++ new/msoffcrypto-tool-4.10.1/LICENSE.txt 2019-08-02 04:38:36.000000000
+0200
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2015 nolze
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/MANIFEST.in
new/msoffcrypto-tool-4.10.1/MANIFEST.in
--- old/msoffcrypto-tool-4.10.0/MANIFEST.in 2019-04-14 05:38:42.000000000
+0200
+++ new/msoffcrypto-tool-4.10.1/MANIFEST.in 2019-08-02 04:38:36.000000000
+0200
@@ -1,4 +1,5 @@
include README.md
+include LICENSE.txt
include .noserc
# include test source and data files
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/PKG-INFO
new/msoffcrypto-tool-4.10.1/PKG-INFO
--- old/msoffcrypto-tool-4.10.0/PKG-INFO 2019-04-14 05:39:19.000000000
+0200
+++ new/msoffcrypto-tool-4.10.1/PKG-INFO 2019-08-02 04:39:13.000000000
+0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: msoffcrypto-tool
-Version: 4.10.0
+Version: 4.10.1
Summary: A Python tool and library for decrypting MS Office files with
passwords or other keys
Home-page: https://github.com/nolze/msoffcrypto-tool
Author: nolze
@@ -38,13 +38,20 @@
### As CLI tool (with password)
```
- msoffcrypto-tool -p Passw0rd encrypted.docx decrypted.docx
+ msoffcrypto-tool encrypted.docx decrypted.docx -p Passw0rd
+ ```
+
+ Password is prompted if you omit the password argument value:
+
+ ```bash
+ $ msoffcrypto-tool encrypted.docx decrypted.docx -p
+ Password:
```
Test if the file is encrypted or not (exit code 0 or 1 is returned):
```
- msoffcrypto-tool --test -v document.doc
+ msoffcrypto-tool document.doc --test -v
```
### As library
@@ -91,7 +98,7 @@
* [ ] Excel 95 Encryption (Excel 95 and prior)
* [ ] PowerPoint 95 Encryption (PowerPoint 95 and prior)
- PRs welcome!
+ PRs are welcome!
## Tests
@@ -118,7 +125,7 @@
* [x] Add the password prompt mode for CLI
* [ ] Redesign APIs (v5.0.0)
* [ ] Improve error types (v5.0.0)
- * [ ] Use `ctypes.Structure`
+ * [ ] Use a kind of `ctypes.Structure`
* [ ] Support encryption
## See also
@@ -136,6 +143,7 @@
* herumi/msoffice <https://github.com/herumi/msoffice>
* DocRecrypt
<https://blogs.technet.microsoft.com/office_resource_kit/2013/01/23/now-you-can-reset-or-remove-a-password-from-a-word-excel-or-powerpoint-filewith-office-2013/>
+ * Apache POI - the Java API for Microsoft Documents
<https://poi.apache.org/>
## Use cases and mentions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/README.md
new/msoffcrypto-tool-4.10.1/README.md
--- old/msoffcrypto-tool-4.10.0/README.md 2019-04-14 05:38:42.000000000
+0200
+++ new/msoffcrypto-tool-4.10.1/README.md 2019-08-02 04:38:36.000000000
+0200
@@ -30,13 +30,20 @@
### As CLI tool (with password)
```
-msoffcrypto-tool -p Passw0rd encrypted.docx decrypted.docx
+msoffcrypto-tool encrypted.docx decrypted.docx -p Passw0rd
+```
+
+Password is prompted if you omit the password argument value:
+
+```bash
+$ msoffcrypto-tool encrypted.docx decrypted.docx -p
+Password:
```
Test if the file is encrypted or not (exit code 0 or 1 is returned):
```
-msoffcrypto-tool --test -v document.doc
+msoffcrypto-tool document.doc --test -v
```
### As library
@@ -83,7 +90,7 @@
* [ ] Excel 95 Encryption (Excel 95 and prior)
* [ ] PowerPoint 95 Encryption (PowerPoint 95 and prior)
-PRs welcome!
+PRs are welcome!
## Tests
@@ -110,7 +117,7 @@
* [x] Add the password prompt mode for CLI
* [ ] Redesign APIs (v5.0.0)
* [ ] Improve error types (v5.0.0)
-* [ ] Use `ctypes.Structure`
+* [ ] Use a kind of `ctypes.Structure`
* [ ] Support encryption
## See also
@@ -128,6 +135,7 @@
* herumi/msoffice <https://github.com/herumi/msoffice>
* DocRecrypt
<https://blogs.technet.microsoft.com/office_resource_kit/2013/01/23/now-you-can-reset-or-remove-a-password-from-a-word-excel-or-powerpoint-filewith-office-2013/>
+* Apache POI - the Java API for Microsoft Documents <https://poi.apache.org/>
## Use cases and mentions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/msoffcrypto/__init__.py
new/msoffcrypto-tool-4.10.1/msoffcrypto/__init__.py
--- old/msoffcrypto-tool-4.10.0/msoffcrypto/__init__.py 2019-04-14
05:38:42.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto/__init__.py 2019-08-02
04:38:36.000000000 +0200
@@ -2,7 +2,7 @@
import zipfile
-__version__ = "4.10.0"
+__version__ = "4.10.1"
def OfficeFile(file):
@@ -15,11 +15,15 @@
BaseOfficeFile object.
Examples:
- >>> f = open("tests/inputs/example_password.docx", "rb")
- >>> officefile = OfficeFile(f)
- >>> officefile.keyTypes
+ >>> with open("tests/inputs/example_password.docx", "rb") as f:
+ ... officefile = OfficeFile(f)
+ ... officefile.keyTypes
('password', 'private_key', 'secret_key')
+
+ Given file handle will not be closed, the file position will most certainly
+ change.
'''
+ file.seek(0) # required by isOleFile
if olefile.isOleFile(file):
ole = olefile.OleFileIO(file)
elif zipfile.is_zipfile(file): # Heuristic
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/msoffcrypto/format/doc97.py
new/msoffcrypto-tool-4.10.1/msoffcrypto/format/doc97.py
--- old/msoffcrypto-tool-4.10.0/msoffcrypto/format/doc97.py 2019-04-14
05:38:42.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto/format/doc97.py 2019-08-02
04:38:36.000000000 +0200
@@ -275,7 +275,7 @@
class Doc97File(base.BaseOfficeFile):
def __init__(self, file):
self.file = file
- ole = olefile.OleFileIO(file)
+ ole = olefile.OleFileIO(file) # do not close this, would close file
self.ole = ole
self.format = "doc97"
self.keyTypes = ['password']
@@ -283,7 +283,8 @@
self.salt = None
# https://msdn.microsoft.com/en-us/library/dd944620(v=office.12).aspx
- fib = _parseFib(ole.openstream('wordDocument'))
+ with ole.openstream('wordDocument') as stream:
+ fib = _parseFib(stream)
# https://msdn.microsoft.com/en-us/library/dd923367(v=office.12).aspx
tablename = '1Table' if fib.base.fWhichTblStm == 1 else '0Table'
@@ -305,31 +306,31 @@
else: # elif fib.base.fObfuscation == 0:
encryptionHeader_size = fib.base.IKey
logger.debug("encryptionHeader_size:
{}".format(hex(encryptionHeader_size)))
- table = self.ole.openstream(self.info.tablename)
- encryptionHeader = table
- encryptionVersionInfo = table.read(4)
- vMajor, vMinor = unpack("<HH", encryptionVersionInfo)
- logger.debug("Version: {} {}".format(vMajor, vMinor))
- if vMajor == 0x0001 and vMinor == 0x0001: # RC4
- info = _parse_header_RC4(encryptionHeader)
- if DocumentRC4.verifypw(password, info['salt'],
info['encryptedVerifier'], info['encryptedVerifierHash']):
- self.type = 'rc4'
- self.key = password
- self.salt = info['salt']
+ with self.ole.openstream(self.info.tablename) as table:
+ encryptionHeader = table # TODO why create a 2nd
reference to same stream?
+ encryptionVersionInfo = table.read(4)
+ vMajor, vMinor = unpack("<HH", encryptionVersionInfo)
+ logger.debug("Version: {} {}".format(vMajor, vMinor))
+ if vMajor == 0x0001 and vMinor == 0x0001: # RC4
+ info = _parse_header_RC4(encryptionHeader)
+ if DocumentRC4.verifypw(password, info['salt'],
info['encryptedVerifier'], info['encryptedVerifierHash']):
+ self.type = 'rc4'
+ self.key = password
+ self.salt = info['salt']
+ else:
+ raise Exception("Failed to verify password")
+ elif vMajor in [0x0002, 0x0003, 0x0004] and vMinor ==
0x0002: # RC4 CryptoAPI
+ info = _parse_header_RC4CryptoAPI(encryptionHeader)
+ if DocumentRC4CryptoAPI.verifypw(password,
info['salt'], info['keySize'],
+
info['encryptedVerifier'], info['encryptedVerifierHash']):
+ self.type = 'rc4_cryptoapi'
+ self.key = password
+ self.salt = info['salt']
+ self.keySize = info['keySize']
+ else:
+ raise Exception("Failed to verify password")
else:
- raise Exception("Failed to verify password")
- elif vMajor in [0x0002, 0x0003, 0x0004] and vMinor == 0x0002:
# RC4 CryptoAPI
- info = _parse_header_RC4CryptoAPI(encryptionHeader)
- if DocumentRC4CryptoAPI.verifypw(password, info['salt'],
info['keySize'],
-
info['encryptedVerifier'], info['encryptedVerifierHash']):
- self.type = 'rc4_cryptoapi'
- self.key = password
- self.salt = info['salt']
- self.keySize = info['keySize']
- else:
- raise Exception("Failed to verify password")
- else:
- raise Exception("Unsupported encryption method")
+ raise Exception("Unsupported encryption method")
def decrypt(self, ofile):
# fd, _ofile_path = tempfile.mkstemp()
@@ -337,11 +338,6 @@
# shutil.copyfile(os.path.realpath(self.file.name), _ofile_path)
# outole = olefile.OleFileIO(_ofile_path, write_mode=True)
- _ofile = tempfile.TemporaryFile()
- self.file.seek(0)
- shutil.copyfileobj(self.file, _ofile)
- outole = olefile.OleFileIO(_ofile, write_mode=True)
-
obuf1 = io.BytesIO()
fibbase = FibBase(
wIdent=self.info.fib.base.wIdent,
@@ -383,27 +379,29 @@
obuf1.seek(0)
obuf1.write(header)
- worddocument = self.ole.openstream('wordDocument')
- worddocument.seek(len(header))
- header = worddocument.read(FIB_LENGTH - len(header))
- worddocument.seek(0)
- logger.debug(len(header))
- obuf1.write(header)
+ with self.ole.openstream('wordDocument') as worddocument:
+ worddocument.seek(len(header))
+ header = worddocument.read(FIB_LENGTH - len(header))
+ worddocument.seek(0)
+ logger.debug(len(header))
+ obuf1.write(header)
- if self.type == "rc4":
- dec1 = DocumentRC4.decrypt(self.key, self.salt, worddocument)
- elif self.type == "rc4_cryptoapi":
- dec1 = DocumentRC4CryptoAPI.decrypt(self.key, self.salt,
self.keySize, worddocument)
- dec1.seek(FIB_LENGTH)
- obuf1.write(dec1.read())
- obuf1.seek(0)
+ if self.type == "rc4":
+ dec1 = DocumentRC4.decrypt(self.key, self.salt, worddocument)
+ elif self.type == "rc4_cryptoapi":
+ dec1 = DocumentRC4CryptoAPI.decrypt(self.key, self.salt,
self.keySize, worddocument)
+ dec1.seek(FIB_LENGTH)
+ obuf1.write(dec1.read())
+ obuf1.seek(0)
# TODO: Preserve header
obuf2 = io.BytesIO()
if self.type == "rc4":
- dec2 = DocumentRC4.decrypt(self.key, self.salt,
self.ole.openstream(self.info.tablename))
+ with self.ole.openstream(self.info.tablename) as stream:
+ dec2 = DocumentRC4.decrypt(self.key, self.salt, stream)
elif self.type == "rc4_cryptoapi":
- dec2 = DocumentRC4CryptoAPI.decrypt(self.key, self.salt,
self.keySize, self.ole.openstream(self.info.tablename))
+ with self.ole.openstream(self.info.tablename) as stream:
+ dec2 = DocumentRC4CryptoAPI.decrypt(self.key, self.salt,
self.keySize, stream)
obuf2.write(dec2.read())
obuf2.seek(0)
@@ -411,22 +409,29 @@
if self.ole.exists('Data'):
obuf3 = io.BytesIO()
if self.type == "rc4":
- dec3 = DocumentRC4.decrypt(self.key, self.salt,
self.ole.openstream('Data'))
+ with self.ole.openstream('Data') as data_stream:
+ dec3 = DocumentRC4.decrypt(self.key, self.salt,
data_stream)
elif self.type == "rc4_cryptoapi":
- dec3 = DocumentRC4CryptoAPI.decrypt(self.key, self.salt,
self.keySize, self.ole.openstream('Data'))
+ with self.ole.openstream('Data') as data_stream:
+ dec3 = DocumentRC4CryptoAPI.decrypt(self.key, self.salt,
self.keySize, data_stream)
obuf3.write(dec3.read())
obuf3.seek(0)
- outole.write_stream('wordDocument', obuf1.read())
- outole.write_stream(self.info.tablename, obuf2.read())
- if obuf3:
- outole.write_stream('Data', obuf3.read())
+ with tempfile.TemporaryFile() as _ofile:
+ self.file.seek(0)
+ shutil.copyfileobj(self.file, _ofile)
+ outole = olefile.OleFileIO(_ofile, write_mode=True)
+
+ outole.write_stream('wordDocument', obuf1.read())
+ outole.write_stream(self.info.tablename, obuf2.read())
+ if obuf3:
+ outole.write_stream('Data', obuf3.read())
- # _ofile = open(_ofile_path, 'rb')
+ # _ofile = open(_ofile_path, 'rb')
- _ofile.seek(0)
+ _ofile.seek(0)
- shutil.copyfileobj(_ofile, ofile)
+ shutil.copyfileobj(_ofile, ofile)
def is_encrypted(self):
return self.info.fib.base.fEncrypted
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/msoffcrypto/format/ooxml.py
new/msoffcrypto-tool-4.10.1/msoffcrypto/format/ooxml.py
--- old/msoffcrypto-tool-4.10.0/msoffcrypto/format/ooxml.py 2019-04-14
05:38:42.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto/format/ooxml.py 2019-08-02
04:38:36.000000000 +0200
@@ -74,10 +74,12 @@
self.format = "ooxml"
file.seek(0) # TODO: Investigate the effect (required for
olefile.isOleFile)
# olefile cannot process non password protected ooxml files.
+ # TODO: this code is duplicate of OfficeFile(). Merge?
if olefile.isOleFile(file):
ole = olefile.OleFileIO(file)
self.file = ole
- self.type, self.info =
_parseinfo(self.file.openstream('EncryptionInfo'))
+ with self.file.openstream('EncryptionInfo') as stream:
+ self.type, self.info = _parseinfo(stream)
logger.debug("OOXMLFile.type: {}".format(self.type))
self.secret_key = None
if self.type == 'agile':
@@ -134,14 +136,16 @@
def decrypt(self, ofile):
if self.type == 'agile':
- obuf = ECMA376Agile.decrypt(
- self.secret_key, self.info['keyDataSalt'],
- self.info['keyDataHashAlgorithm'],
- self.file.openstream('EncryptedPackage')
- )
+ with self.file.openstream('EncryptedPackage') as stream:
+ obuf = ECMA376Agile.decrypt(
+ self.secret_key, self.info['keyDataSalt'],
+ self.info['keyDataHashAlgorithm'],
+ stream
+ )
ofile.write(obuf)
elif self.type == 'standard':
- obuf = ECMA376Standard.decrypt(self.secret_key,
self.file.openstream('EncryptedPackage'))
+ with self.file.openstream('EncryptedPackage') as stream:
+ obuf = ECMA376Standard.decrypt(self.secret_key, stream)
ofile.write(obuf)
# If the file is successfully decrypted, there must be a valid OOXML
file, i.e. a valid zip file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/msoffcrypto/format/ppt97.py
new/msoffcrypto-tool-4.10.1/msoffcrypto/format/ppt97.py
--- old/msoffcrypto-tool-4.10.0/msoffcrypto/format/ppt97.py 2019-04-14
05:38:42.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto/format/ppt97.py 2019-08-02
04:38:36.000000000 +0200
@@ -492,13 +492,14 @@
class Ppt97File(base.BaseOfficeFile):
def __init__(self, file):
self.file = file
- ole = olefile.OleFileIO(file)
+ ole = olefile.OleFileIO(file) # do not close this, would close file
self.ole = ole
self.format = "ppt97"
self.keyTypes = ['password']
self.key = None
self.salt = None
+ # streams closed in destructor:
currentuser = ole.openstream('Current User')
powerpointdocument = ole.openstream('PowerPoint Document')
@@ -508,6 +509,14 @@
powerpointdocument=powerpointdocument,
)
+ def __del__(self):
+ """Destructor, closes opened streams."""
+ if hasattr(self, 'data') and self.data:
+ if self.data.currentuser:
+ self.data.currentuser.close()
+ if self.data.powerpointdocument:
+ self.data.powerpointdocument.close()
+
def load_key(self, password=None):
persistobjectdirectory = construct_persistobjectdirectory(self.data)
logger.debug("[*] persistobjectdirectory:
{}".format(persistobjectdirectory))
@@ -547,11 +556,6 @@
raise Exception("Failed to verify password")
def decrypt(self, ofile):
- _ofile = tempfile.TemporaryFile()
- self.file.seek(0)
- shutil.copyfileobj(self.file, _ofile)
- outole = olefile.OleFileIO(_ofile, write_mode=True)
-
# Current User Stream
self.data.currentuser.seek(0)
currentuser = _parseCurrentUser(self.data.currentuser)
@@ -580,7 +584,7 @@
buf = _packCurrentUser(currentuser_new)
buf.seek(0)
- outole.write_stream('Current User', buf.read())
+ currentuser_buf = buf
# List of encrypted parts:
https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ppt/b0963334-4408-4621-879a-ef9c54551fd8
@@ -712,14 +716,22 @@
logger.debug("[*] powerpointdocument_size={},
len(dec_buf.read())={}".format(powerpointdocument_size, len(dec_buf.read())))
dec_buf.seek(0)
- outole.write_stream('PowerPoint Document', dec_buf.read())
+ powerpointdocument_dec_buf = dec_buf
# TODO: Pictures Stream
# TODO: Encrypted Summary Info Stream
- # Finalize
- _ofile.seek(0)
- shutil.copyfileobj(_ofile, ofile)
+ with tempfile.TemporaryFile() as _ofile:
+ self.file.seek(0)
+ shutil.copyfileobj(self.file, _ofile)
+ outole = olefile.OleFileIO(_ofile, write_mode=True)
+
+ outole.write_stream('Current User', currentuser_buf.read())
+ outole.write_stream('PowerPoint Document',
powerpointdocument_dec_buf.read())
+
+ # Finalize
+ _ofile.seek(0)
+ shutil.copyfileobj(_ofile, ofile)
return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/msoffcrypto/format/xls97.py
new/msoffcrypto-tool-4.10.1/msoffcrypto/format/xls97.py
--- old/msoffcrypto-tool-4.10.0/msoffcrypto/format/xls97.py 2019-04-14
05:38:42.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto/format/xls97.py 2019-08-02
04:38:36.000000000 +0200
@@ -445,20 +445,25 @@
class Xls97File(base.BaseOfficeFile):
def __init__(self, file):
self.file = file
- ole = olefile.OleFileIO(file)
+ ole = olefile.OleFileIO(file) # do not close this, would close file
self.ole = ole
self.format = "xls97"
self.keyTypes = ['password']
self.key = None
self.salt = None
- workbook = ole.openstream('Workbook')
+ workbook = ole.openstream('Workbook') # closed in destructor
Data = namedtuple('Data', ['workbook'])
self.data = Data(
workbook=workbook,
)
+ def __del__(self):
+ """Destructor, closes opened stream."""
+ if hasattr(self, 'data') and self.data and self.data.workbook:
+ self.data.workbook.close()
+
def load_key(self, password=None):
self.data.workbook.seek(0)
workbook = _BIFFStream(self.data.workbook)
@@ -519,11 +524,6 @@
# shutil.copyfile(os.path.realpath(self.file.name), _ofile_path)
# outole = olefile.OleFileIO(_ofile_path, write_mode=True)
- _ofile = tempfile.TemporaryFile()
- self.file.seek(0)
- shutil.copyfileobj(self.file, _ofile)
- outole = olefile.OleFileIO(_ofile, write_mode=True)
-
# List of encrypted parts:
https://msdn.microsoft.com/en-us/library/dd905723(v=office.12).aspx
# Workbook stream
@@ -576,13 +576,20 @@
# f.write(dec.read())
# dec.seek(0)
- outole.write_stream('Workbook', dec.read())
+ workbook_dec = dec
+
+ with tempfile.TemporaryFile() as _ofile:
+ self.file.seek(0)
+ shutil.copyfileobj(self.file, _ofile)
+ outole = olefile.OleFileIO(_ofile, write_mode=True)
+
+ outole.write_stream('Workbook', workbook_dec.read())
- # _ofile = open(_ofile_path, 'rb')
+ # _ofile = open(_ofile_path, 'rb')
- _ofile.seek(0)
+ _ofile.seek(0)
- shutil.copyfileobj(_ofile, ofile)
+ shutil.copyfileobj(_ofile, ofile)
return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/msoffcrypto-tool-4.10.0/msoffcrypto_tool.egg-info/PKG-INFO
new/msoffcrypto-tool-4.10.1/msoffcrypto_tool.egg-info/PKG-INFO
--- old/msoffcrypto-tool-4.10.0/msoffcrypto_tool.egg-info/PKG-INFO
2019-04-14 05:39:19.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto_tool.egg-info/PKG-INFO
2019-08-02 04:39:13.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: msoffcrypto-tool
-Version: 4.10.0
+Version: 4.10.1
Summary: A Python tool and library for decrypting MS Office files with
passwords or other keys
Home-page: https://github.com/nolze/msoffcrypto-tool
Author: nolze
@@ -38,13 +38,20 @@
### As CLI tool (with password)
```
- msoffcrypto-tool -p Passw0rd encrypted.docx decrypted.docx
+ msoffcrypto-tool encrypted.docx decrypted.docx -p Passw0rd
+ ```
+
+ Password is prompted if you omit the password argument value:
+
+ ```bash
+ $ msoffcrypto-tool encrypted.docx decrypted.docx -p
+ Password:
```
Test if the file is encrypted or not (exit code 0 or 1 is returned):
```
- msoffcrypto-tool --test -v document.doc
+ msoffcrypto-tool document.doc --test -v
```
### As library
@@ -91,7 +98,7 @@
* [ ] Excel 95 Encryption (Excel 95 and prior)
* [ ] PowerPoint 95 Encryption (PowerPoint 95 and prior)
- PRs welcome!
+ PRs are welcome!
## Tests
@@ -118,7 +125,7 @@
* [x] Add the password prompt mode for CLI
* [ ] Redesign APIs (v5.0.0)
* [ ] Improve error types (v5.0.0)
- * [ ] Use `ctypes.Structure`
+ * [ ] Use a kind of `ctypes.Structure`
* [ ] Support encryption
## See also
@@ -136,6 +143,7 @@
* herumi/msoffice <https://github.com/herumi/msoffice>
* DocRecrypt
<https://blogs.technet.microsoft.com/office_resource_kit/2013/01/23/now-you-can-reset-or-remove-a-password-from-a-word-excel-or-powerpoint-filewith-office-2013/>
+ * Apache POI - the Java API for Microsoft Documents
<https://poi.apache.org/>
## Use cases and mentions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/msoffcrypto-tool-4.10.0/msoffcrypto_tool.egg-info/SOURCES.txt
new/msoffcrypto-tool-4.10.1/msoffcrypto_tool.egg-info/SOURCES.txt
--- old/msoffcrypto-tool-4.10.0/msoffcrypto_tool.egg-info/SOURCES.txt
2019-04-14 05:39:19.000000000 +0200
+++ new/msoffcrypto-tool-4.10.1/msoffcrypto_tool.egg-info/SOURCES.txt
2019-08-02 04:39:13.000000000 +0200
@@ -1,4 +1,5 @@
.noserc
+LICENSE.txt
MANIFEST.in
README.md
setup.py
@@ -27,6 +28,7 @@
tests/__init__.py
tests/test_cli.sh
tests/test_compare_known_output.py
+tests/test_file_handle.py
tests/inputs/ecma376standard_password.docx
tests/inputs/example_password.docx
tests/inputs/example_password.xlsx
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/msoffcrypto-tool-4.10.0/tests/test_file_handle.py
new/msoffcrypto-tool-4.10.1/tests/test_file_handle.py
--- old/msoffcrypto-tool-4.10.0/tests/test_file_handle.py 1970-01-01
01:00:00.000000000 +0100
+++ new/msoffcrypto-tool-4.10.1/tests/test_file_handle.py 2019-08-02
04:38:36.000000000 +0200
@@ -0,0 +1,44 @@
+"""Check that given file handles are not closed."""
+
+
+import unittest
+from os.path import join, dirname
+
+from msoffcrypto import OfficeFile
+
+
+#: directory with input
+DATA_DIR = join(dirname(__file__), 'inputs')
+
+
+class FileHandleTest(unittest.TestCase):
+ """See module doc."""
+
+ def test_file_handle_open(self):
+ """Check that file handles are open after is_encrypted()."""
+ for suffix in 'doc', 'ppt', 'xls':
+ path = join(DATA_DIR, 'plain.' + suffix)
+
+ with open(path, 'rb') as file_handle:
+ ofile = OfficeFile(file_handle)
+
+ # do something with ofile
+ self.assertEqual(ofile.is_encrypted(), False)
+
+ # check that file handle is still open
+ self.assertFalse(file_handle.closed)
+
+ # destroy OfficeFile, calls destructor
+ del ofile
+
+ # check that file handle is still open
+ self.assertFalse(file_handle.closed)
+
+ # just for completeness:
+ # check that file handle is now closed
+ self.assertTrue(file_handle.closed)
+
+
+# if someone calls this as script, run unittests
+if __name__ == '__main__':
+ unittest.main()