Extended tests against shareware

Total of 3081 unique (shareware) Wise installers have been found,
this is good for testing. With these extended test scripts,
written in Python; make it easy to see what installers broke or
fixed after code changes.

SEE the new READMEs for more info.
This commit is contained in:
CYBERDEV 2024-11-01 02:27:37 +01:00
parent 5121c5581d
commit f921650601
16 changed files with 18630 additions and 1 deletions

View file

@ -9,7 +9,7 @@ end_of_line = lf
insert_final_newline = true
# 2 space indentation
[*.{c,h,hexpat}]
[*.{c,h,py,hexpat}]
charset = utf-8
indent_style = space
indent_size = 2

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ src/*.o
# Test cache
tests/cache/
tests/extended/cache/

236
tests/extended/README.md Normal file
View file

@ -0,0 +1,236 @@
# Extended tests
> NOTE: This is for developers
A large number (current 3081) of unique shareware Wise installers have
been found. It is `70.19 GiB` in size, so make sure you have that free space.
These tests won't extract anything to disk, it uses `--list`, `--raw-verify`,
and `--verify` for the dev version of REWise and do a `--verify` test with
REWise v0.2.0 for comparison. Along with that it tries to analyze errors and
comment them.
These scripts require Python 3, so make sure you have that installed.
> TIP: Use `csvlens`, `libreoffice` or whatever to view the .csv files.
## How to
### Initial setup
1. If you don't have a REWise v0.2.0 binary then download and compile
[REWise v0.2.0](https://codeberg.org/CYBERDEV/REWise/archive/v0.2.0.tar.gz).
2. Compile the REWise dev version with `make debug`, it should be
in `../../` (from this README.md file, by default).
3. Copy `config.py.template` to `config.py` and edit `REWISE_02_PATH`
so it points to your REWise v0.2.0 binary. When you already have
downloaded the shareware installers somewhere else then default
you want to edit `DL_PATH`.
4. Download the installers; make sure you have enough free space and take in
mind that this will take a while:
```
python test.py download sources/shareware.csv
```
See the `cache/dl.log` file for download/file errors.
5. Run the initial test; gather info about the installers, run tests against
REWise v0.2.0 and the REWise dev version. The input will be a source .csv
and the output will be a result .csv file that will be our base. Later
tests will skip the REWise v0.2.0 tests because they will be the
same anyway.
```
python test.py init sources/shareware.csv ./results.csv
```
### Testing local changes
So you made some code changes and recompiled REWise with `make debug`
(`rewise` bin should be in `../../`), now it's time to see if it fixed
or broke any installer.
First thing is to re-run the tests against the freshly compiled REWise
bin:
```
python test.py create-diff ./results.csv ./new_results.csv
```
To print the installers that it fixed/broke:
```
python test.py print-diff ./results.csv ./new_results.csv
Fixed (0)
--------------------------------
Broke (2)
--------------------------------
c7aa23ed03082d671a1e2bf776361d685b51f1acfa9525a636f15e25d681084e setup.exe
ff9c38732523f39432479a1f5625a7bf089fab036cc5c7d89f288df1bf56e306 AdminPro_DEMO.exe
```
To print stats of the new results:
```
python test.py print-stats ./new_results.csv
| DATE | OK | ERR | LOK | LERR | ROK | RERR | v02 | v02E | VERSION
| :------------------ | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | :------
| NE | 96 | 6 | 100 | 2 | 101 | 1 | 0 | 102 | Unknown
| 1998-10-02 22:36:51 | 78 | 4 | 78 | 4 | 82 | 0 | 58 | 24 | Unknown
| 1998-10-23 23:23:16 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | Unknown
| 1998-11-09 21:17:09 | 176 | 22 | 179 | 19 | 198 | 0 | 132 | 66 | InstallMaster 7
| 1998-12-03 23:11:32 | 43 | 0 | 43 | 0 | 43 | 0 | 28 | 15 | Unknown
| 1999-02-05 23:07:52 | 214 | 19 | 233 | 0 | 232 | 1 | 132 | 101 | Unknown
| 1999-04-05 18:07:26 | 4 | 0 | 4 | 0 | 4 | 0 | 4 | 0 | Unknown
| 1999-05-21 22:48:48 | 406 | 33 | 420 | 19 | 432 | 7 | 267 | 172 | Unknown
| 1999-08-17 17:25:48 | 238 | 24 | 250 | 12 | 254 | 8 | 143 | 119 | Unknown
| 2000-04-25 16:37:12 | 894 | 49 | 914 | 29 | 937 | 6 | 514 | 429 | InstallMaster 8
| 2001-08-13 19:13:38 | 319 | 8 | 325 | 2 | 323 | 4 | 222 | 105 | Unknown
| 2001-10-25 21:47:11 | 418 | 24 | 433 | 9 | 429 | 13 | 246 | 196 | Installation System 9
| 2031-05-20 22:54:01 | 4 | 0 | 4 | 0 | 4 | 0 | 4 | 0 | Unknown
| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -------
| Total: 3081 | 2892 | 189 | 2985 | 96 | 3041 | 40 | 1752 | 1329 |
PK Total : 438
PK OK : 432
PK ERROR : 6
PK Raw OK : 438
PK Raw ERROR: 0
Comments:
80 Without comment
23 Negative script deflate offset
21 Possible weird stuff at WiseScriptHeader.unknown_22 '9190A09A878B'.
14 Possible weird stuff at WiseScriptHeader.unknown_22 '958A928F8C8B'.
10 Possible weird stuff at WiseScriptHeader.unknown_22 'B890BE889E86'.
6 Possible weird stuff at WiseScriptHeader.unknown_22 'B6BF88BF96BF'.
6 Possible weird stuff at WiseScriptHeader.unknown_22 'A8B0ADB3BBB6'.
5 'Initializing Wise Installation Wizard...' found in the PE b'.data\x00\x00\x00' section.
3 Possible weird stuff at WiseScriptHeader.unknown_22 'BCADA6CEA5CD'.
3 Possible weird stuff at WiseScriptHeader.unknown_22 'C8CACBC8C6CC'.
2 Possible weird stuff at WiseScriptHeader.unknown_22 '99939E9D919E'.
2 0x18 mismatch, 0x18 00 08 ..
2 Possible weird stuff at WiseScriptHeader.unknown_22 'DB8F9E8C8C88'.
2 Possible weird stuff at WiseScriptHeader.unknown_22 'ADBF90BF93BF'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '8588C9C6C88B'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 'AB969C949A8B'.
1 0x18 mismatch, there is OP 0x00 right after 0x18
1 Script deflate offset is absurd high
1 Possible weird stuff at WiseScriptHeader.unknown_22 'CC918B90929D'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 'B4AAACB6B5AC'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '9D8D9E919B96'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '9C909B9A989A'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '8C929E9393D1'.
1 Overlay header unknown2 != 0x8000 but 0x0000.
Verify errors:
75 WS_ERROR_VALUE ERROR: parseWiseScriptHeader failed to read languageTexts.
46 WS_ERROR_INFLATE ERROR: Inflated size is larger then expected
25 WS_ERROR_SEEK ERROR: Failed seek to file offset
9 ERROR_VALUE ERROR: Advertised WiseScript.bin size looks insane.
7 WS_ERROR_INFLATE ERROR: zlib: invalid code lengths set
4 WS_ERROR_INFLATE ERROR: zlib: invalid distance too far back
4 WS_ERROR_INFLATE ERROR: zlib: invalid stored block lengths
3 WS_ERROR_PK_HEADER ERROR: PK signature unknown
3 WS_ERROR_VALUE ERROR: wiseScriptParsePath expected '%' at path start
2 WS_ERROR_VALUE ERROR: parseWiseScript unknown OP: 3A
2 WS_ERROR_INFLATE ERROR: zlib: invalid block type
2 ERROR_VALUE ERROR: Advertised .dib size looks insane.
1 WS_ERROR_BRANCHING ERROR: OP 0x23 LANG but not in LANG branch
1 WS_ERROR_INFLATE ERROR: zlib: invalid literal/length code
1 WS_ERROR_VALUE ERROR: This is a multi language installer but not all languages have their name set
1 WS_ERROR_VALUE ERROR: parseWiseScript unknown OP: 49
1 WS_ERROR_INFLATE ERROR: zlib: invalid distance code
1 WS_ERROR_BRANCHING ERROR: OP 0x23 LANG but currently not in a branch
1 ERROR_INFLATE ERROR: zlib: invalid stored block lengths
```
Further inspection of the results file can be done using something that can
view .csv files.
### Write debug scripts
I've written a lot of small scripts for debugging specific stuff, like printing
a list of all PE build dates and the overlay offset(s) observed. Such things
are very specific and I didn't find it worth including, but here is a example:
```python
import os
from installers import installerStatsCsvIt
found = {}
for installer in installerStatsCsvIt("new_results.csv"):
if installer.isNe:
continue
fdate = installer.formattedDate()
if fdate not in found:
found.update({fdate: []});
hexoverlay = hex(installer.overlay)
if hexoverlay not in found[fdate]:
found[fdate].append(hexoverlay)
for pebuild, offsets in sorted(found.items()):
print(pebuild, offsets)
```
## Files
### test.py
```help
usage: test.py [-h] {download,init,update,create-diff,filter-invalid,update-comments,print-diff,print-stats,result-to-source} ...
options:
-h, --help show this help message and exit
COMMANDS:
Note: use -h after a command to get more help on that command
{download,init,update,create-diff,filter-invalid,update-comments,print-diff,print-stats,result-to-source}
download Download installers from the given SOURCE file when needed
init Run initial test, the output will be written to the given RESULT file. The initial test does include testing against REWise v0.2
update Add new installers from given SOURCE and re-run tests for all installers, excluding the REWise v0.2 tests. To only add new and run tests for new installers give the '--only-new' argument.
create-diff Re-run tests of first given RESULT, ouput to second given RESULT file.
filter-invalid Filter out results that appear to be invalid files / not Wise installers.
update-comments Update comments for given RESULT file.
print-diff Compare two RESULT files and print the installers that it fixed/broke.
print-stats Print some stats for the given RESULT file.
result-to-source Convert RESULT file into SOURCE file.
```
#### `module` analyze.py
Analyze errors and add comments.
#### `module` dl.py
For downloading files.
#### `module` sources.py
Handle reading source .csv files.
The columns:
1. B3 (Blake 3)
2. MD5
3. Filesize in bytes
4. Download URL
#### `module` installers.py
Handle reading/writing result .csv files.
#### `module` rewise.py
This module handles testing and output parsing of REWise current dev and
REWise v0.2.0.

127
tests/extended/analyze.py Normal file
View file

@ -0,0 +1,127 @@
# Analyze errors
import os
import pefile
import zipfile
def addCustomComments(installer):
if installer.md5 == "32aad22244ee0c8e7dcd3f86dea9e347": # NPFG10.EXE
installer.addComment("This one has '../' in one of it's filenames, it is resolved by escaping the '../' with '\\.\\./'")
elif installer.md5 == "a91a9034e99da6917ed6ea4ae1017474": # b65full.exe
installer.addComment("Corrupt, missing data, see "
"c3d819097d06d110f1b01111a89b095c for valid "
"data.")
elif installer.md5 in ["70a6bbf41b7e9de48e711dbc26eac88b", # dap43.exe
"f463a1d47ac919160fc450d322c6c63e", # dap4.exe
"7d093e7e91b17b0b6ca427c91202c839"]: # dap3908.exe
installer.addComment("0x18 mismatch, there is OP 0x00 right after 0x18")
elif installer.md5 in ["5516bfdc0346f475300f83ebc6c76547", # lw3drv.exe
"3be4f8d1fc6ede81d954b6914530dd2b", # lw3w2k.exe
"1588bc310e9a71389f1069af159203ee", # lw3wme.exe
"073c6e77547bcda5ce7b5ebe96f3eb01"]:# SBL51.EXE
installer.addComment("0x18 mismatch")
elif installer.md5 in ["7c763e4af5aca8cc2fabcc846b788692", # DSiegeUpdate1_09_2-1_1_1460.exe
"acccf3d47143f0cf2b6b893765586eb6", # Dsiegeupdate1.0-1.11.1462_english.exe
"3465e2b1eec01cc26b898c4ef3ef090e"]: # dsupdate1.1-1.11.1462_eng.exe
installer.addComment("0x18 mismatch, 0x18 00 08 ..")
#elif installer.md5 in ["2b4e75b6c5b1ae0fd9243d0cf8db45e5" # psp700ev.exe
# "215506a69c9677e9b01bd5c43314ee5f"]: # RD2_onlinedemo_03_10.exe
# installer.addComment("False positive, this is a InstallShield installer")
elif installer.md5 in ["dbbf3189c879ad7673d5971e457effeb", # DPPopUpStopper.exe
"ae59de2259f3a109a6d66eb037da2335", # ICQ2000B.EXE
"60aef2e657c05cfff2bfbc75d6385f3d"]: # DontPanc.exe
installer.addComment("This installer reads the overlay header 3 bytes to early")
#elif installer.md5 in ["a44f7489825a35b8ea49857d2d832ce6", # thmpls450_s.exe
# "cf8e337b9c331cdfbe490a023b184a9f", # icq99b.exe
# "058f7c9124cd32463e8dfebe4eb115c7"]: # icq2000a.exe
# installer.addComment("FIXME Weird extra chars in unknown_22")
elif installer.md5 in ["3379f7b191a5f9ad9dee9d49acf99e23", # upgrade.exe
"3319738353934531293f8b7e1c103a85"]: # upgrade.exe
installer.addComment("Interesting one, this has no 0x00 files, only 0x12, online installer?")
elif installer.md5 == "28b29549010d0980d1cd1d0ad86f8dbe": # battlefield2demo.exe
installer.addComment("False positive, InstallShield Wizard?")
elif installer.md5 in ["32a6454ef70526f8d80be1069749bfde", # sumofree.exe (overlay: 0x00012200)
"3dd7c98df5e6a5e528d446f4ebce46c8", # RD210.EXE (overlay: 0x00012C00)
"3c50c1616008c582c7ea3c34fef90d91"]: # empireearth2_mpdemo_en.exe (overlay: 0x0001F800)
installer.addComment("False positive? Raw files appended at overlay with probably a Wise installer")
elif installer.md5 in ["7c420b5be50635f3a2f73cf8e5c490c5", # spf.exe
"99c37f56b1a030ed4b04e0b2cb611051", # spf.exe
"c087ee0bbd1baf2a6e04151b76fc1216"]: # spf.exe
installer.addComment("False positive")
def addPeComments(installer):
pe = None
try:
pe = pefile.PE(installer.realpath, fast_load=True)
except pefile.PEFormatError as err:
installer.addComment(f"This not a PE file: {err}")
return True
# find the magic string in any PE section and note the offset after read
magicoffset = 0
sectionName = ""
with open(installer.realpath, "rb") as fp:
for section in pe.sections:
if section.Name[:5] == b'.WISE':
installer.addComment("PE .WISE section found.")
# Read each section into mem and search for the magic string
for section in pe.sections:
fp.seek(section.VirtualAddress, 0)
sectiondata = fp.read(section.SizeOfRawData)
if b"Initializing Wise Installation Wizard..." in sectiondata:
magicoffset = fp.tell()
sectionName = section.Name
break
if magicoffset != 0:
installer.addComment(f"'Initializing Wise Installation Wizard...' found in the PE {sectionName} section.")
pe.close()
return True
overlay = pe.get_overlay_data_start_offset()
if overlay:
filesize = os.path.getsize(installer.realpath)
delta = filesize - overlay
if delta < 4096:
installer.addComment(f"Very small overlay size of {delta} bytes")
pe.close()
return True
else:
installer.addComment(f"No overlay data")
pe.close()
return True
with open(installer.realpath, "rb") as fp:
fp.seek(overlay, 0)
if fp.read(13) == b'InstallShield':
installer.addComment("False positive, 'InstallShield' found at overlay.")
pe.close()
return True
pe.close()
return False
def falsePositivePkCheck(installer):
try:
zfp = zipfile.ZipFile(installer.realpath, 'r')
zfp.close()
except zipfile.BadZipFile:
installer.isPk = False
installer.addComment("False positive PK, check the overlay header")
return True
return False

View file

@ -0,0 +1,35 @@
import os
# Do not edit this, it is this script's local directory
BASE_PATH = os.path.abspath(os.path.dirname(__file__))
# You probably don't want to change this but when you do point it to
# where the source .csv files are.
SOURCE_PATH = os.path.abspath(os.path.join(BASE_PATH, "sources/"))
# When you already have the installers downloaded somewhere point it
# there, else it will download them (when not found) to the set location.
#CACHE_PATH = os.path.abspath(os.path.join(BASE_PATH, "../cache/dl/"))
CACHE_PATH = os.path.abspath(os.path.join(BASE_PATH, "cache/"))
# Download path
DL_PATH = os.path.abspath(os.path.join(CACHE_PATH, "dl/"))
# Download error log path
DL_LOG = os.path.join(CACHE_PATH, "dl.log")
# Filepath to the 'rewise' bin
REWISE_DEV_PATH = os.path.abspath(os.path.join(BASE_PATH, "../../rewise"))
# DO SET THIS!
# Filepath to the 'rewise' v0.2 bin
REWISE_02_PATH = os.path.abspath(os.path.join(CACHE_PATH, "rewise_02"))
if __name__ == "__main__":
print("BASE_PATH", BASE_PATH)
print("CACHE_PATH", CACHE_PATH)
print("DL_PATH", DL_PATH)
print("DL_LOG", DL_LOG)
print("SOURCE_PATH", SOURCE_PATH)
print("REWISE_DEV_PATH", REWISE_DEV_PATH)
print("REWISE_02_PATH", REWISE_02_PATH)

30
tests/extended/dl.py Normal file
View file

@ -0,0 +1,30 @@
import os
import urllib
import urllib.error
import urllib.request
from urllib.parse import urlparse, quote, unquote
from http.client import RemoteDisconnected
def encodeUrl(url):
parsed = urlparse(url)
parsed = parsed._replace(path=quote(unquote(parsed.path)),
query=quote(unquote(parsed.query)))
return parsed.geturl()
def downloadFile(url, outputFile):
url = encodeUrl(url)
# Create needed dirs
outputDir = os.path.dirname(outputFile)
if not os.path.isdir(outputDir):
os.makedirs(outputDir)
# Download ..
try:
urllib.request.urlretrieve(url, outputFile)
except (urllib.error.ContentTooShortError, urllib.error.URLError, RemoteDisconnected) as e:
print(e, url)
return str(e)
return None

View file

@ -0,0 +1,238 @@
import os
import csv
import datetime
from config import BASE_PATH, DL_PATH, SOURCE_PATH
import rewise
import sources
import analyze
""" -- InstallerStats
Generate or read build stats
"""
class InstallerStats:
__DATA = {
"title" : "",
"filename" : "",
"b3" : "",
"md5" : "",
"peBuild" : 0,
"scriptBuild" : 0,
"overlay" : 0,
"scriptDeflateOffset": 0,
"isNe" : 0, # bool
"isPk" : 0, # bool
"langCount" : 0,
"devStatus" : rewise.getRewiseStatusString(rewise.REWISE_STATUS_UNSET),
"devError" : "",
"devListStatus": rewise.getRewiseStatusString(rewise.REWISE_STATUS_UNSET),
"devRawStatus": rewise.getRewiseStatusString(rewise.REWISE_STATUS_UNSET),
"devRawError" : "",
"rew02Status" : rewise.getRewiseStatusString(rewise.REWISE_STATUS_UNSET),
"rew02Error" : "",
"comment" : ""
#"dlUrl" : "",
#"filepath" : ""
}
__FANCY_NAMES = [
"Title",
"Filename",
"B3",
"MD5",
"PE Build",
"Script Build",
"Overlay offset",
"Script deflate file offset",
"NE",
"PK",
"Languages",
"Dev status",
"Dev error",
"Dev list status",
"Dev raw status",
"Dev raw error",
"0.2 status",
"0.2 error",
"Comments"
#"Download URL",
#"Local filepath"
]
def __init__(self, source=None, rowData=None):
if not source and not rowData:
raise Exception("InstallerStats: give either source or rowData")
self.__data = dict(InstallerStats.__DATA)
self.__keys = list(self.__data.keys())
self.__keyCount = len(self.__keys)
self.__columns = [col for col in self.__data.keys()]
# Load, rowData should be a list
if rowData:
colIndex = 0
for col in rowData:
key = self.__keys[colIndex]
dtype = type(InstallerStats.__DATA[key])
self.__data[key] = dtype(col)
colIndex += 1
self.filepath = os.path.join(DL_PATH, self.b3)
# Gather stats
else:
self.__data["b3"] = source.b3
self.__data["md5"] = source.md5
self.__data["dlUrl"] = source.dlUrl
self.__data["filename"] = source.getFilename()
self.filepath = source.filepath
# tmp
self.overlayHeaderUnk2 = ""
self.wsHeaderUnk22 = ""
self.realpath = os.path.join(DL_PATH, self.filepath)
def __getattr__(cls, key):
return cls.__data[key]
def __str__(self):
return str(self.__data)
# for sorting on b3
def __lt__(self, other):
return self.b3 < other.b3
def addComment(self, comment):
if self.__data["comment"]:
self.__data["comment"] += "\n---\n"
self.__data["comment"] += comment
def clearComments(self):
self.__data["comment"] = ""
@staticmethod
def columns():
return InstallerStats.__FANCY_NAMES
def asRow(self):
return [self.__data[k] for k in InstallerStats.__DATA.keys()]
def formattedDate(self):
return datetime.datetime.fromtimestamp(int(self.peBuild)).strftime('%Y-%m-%d %H:%M:%S')
def formattedScriptDate(self):
return datetime.datetime.fromtimestamp(int(self.scriptBuild)).strftime('%Y-%m-%d %H:%M:%S')
def gatherInfo(self):
otherStats = rewise.getRewiseDevOtherStats(self.realpath)
self.__data["peBuild"] = otherStats["peBuild"]
self.__data["scriptBuild"] = otherStats["scriptBuild"]
self.__data["isNe"] = 1 if otherStats["isNe"] else 0
self.__data["isPk"] = 1 if otherStats["isPk"] else 0
self.__data["overlay"] = otherStats["overlayOffset"]
self.__data["scriptDeflateOffset"] = otherStats["scriptDeflateOffset"]
self.__data["title"] = otherStats["title"]
self.__data["langCount"] = otherStats["langCount"]
self.overlayHeaderUnk2 = otherStats["overlayUnk2"]
self.wsHeaderUnk22 = otherStats["wsHdrUnk22"]
def testDevVerify(self):
devVerify = rewise.getRewiseDevVerifyStats(self.realpath)
self.__data["devStatus"] = rewise.getRewiseStatusString(devVerify["status"])
self.__data["devError"] = devVerify["error"]
def testDevList(self):
devList = rewise.getRewiseDevListStats(self.realpath)
self.__data["devListStatus"] = rewise.getRewiseStatusString(devList["status"])
#self.__data["devListError"] = devList["error"]
def testDevRaw(self):
devRaw = rewise.getRewiseDevRawVerifyStats(self.realpath)
self.__data["devRawStatus"] = rewise.getRewiseStatusString(devRaw["status"])
self.__data["devRawError"] = devRaw["error"]
def test02Verify(self):
r02Verify = rewise.getRewise02VerifyStats(self.realpath)
self.__data["rew02Status"] = rewise.getRewiseStatusString(r02Verify["status"])
self.__data["rew02Error"] = r02Verify["error"]
def generateComments(self):
self.clearComments()
analyze.addCustomComments(self)
if not self.isNe:
if analyze.addPeComments(self):
return
if self.overlayHeaderUnk2 and self.overlayHeaderUnk2 != "0008":
self.addComment(f"Overlay header unknown2 != 0x8000 but 0x{self.overlayHeaderUnk2}.")
elif self.isPk:
analyze.falsePositivePkCheck(self)
elif self.wsHeaderUnk22 and self.wsHeaderUnk22[-12:] not in ["000000000001", "000000000000"]:
self.addComment(f"Possible weird stuff at WiseScriptHeader.unknown_22 '{self.wsHeaderUnk22[-12:]}'.")
elif self.scriptDeflateOffset != -1:
if self.scriptDeflateOffset < -1:
self.addComment(f"Negative script deflate offset")
elif self.scriptDeflateOffset > 0x100000:
self.addComment(f"Script deflate offset is absurd high")
def fullTest(self):
self.gatherInfo()
self.testDevVerify()
self.testDevList()
self.testDevRaw()
self.test02Verify()
def installerStatsCsvIt(csvFile):
with open(csvFile, newline='') as csvfile:
spamreader = csv.reader(csvfile, delimiter=',', quotechar='"')
for row in list(spamreader)[1:]: # skip the header
yield InstallerStats(rowData=row)
# Filter out installers that appear to be invalid / non Wise.
# - When the installer is a PE file, it has a PE build date, filter
# it out when the PE build date has no working installers.
# - Filter out installer where the exe parsing failed.
# - Filter out CRC32 corrupt installers.
def acceptableInstallerIt(resultFile):
installers = list(installerStatsCsvIt(resultFile))
# Get working PE dates (PE build dates with at least one success
# fully operation for one installer).
workingPeDates = []
for installer in installers:
if installer.peBuild in workingPeDates:
continue
if (installer.devStatus == "OK" or
installer.devRawStatus == "OK" or
installer.devListStatus == "OK" or
installer.rew02Status == "OK"):
workingPeDates.append(installer.peBuild)
for installer in installers:
if installer.devStatus in ["ERROR_INVALID_PENE", "ERROR_NOT_PENE",
"ERROR_NOT_WISE"]:
continue
if installer.peBuild not in workingPeDates:
continue
if installer.devRawStatus == "ERROR_CRC32":
# this installer is corrupt
continue
yield installer
if __name__ == "__main__":
for source in sources.InstallerSourceUniqIt(os.path.join(SOURCE_PATH,
"shareware.csv")):
installer = InstallerStats(source)
installer.gatherInfo()
print(installer.title)

View file

@ -0,0 +1,250 @@
# Results
These are the test results.
## `shareware.csv`
> Use `python ../test.py print-stats shareware.csv` to print stats.
| DATE | OK | ERR | LOK | LERR | ROK | RERR | v02 | v02E | VERSION
| :------------------ | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | :------
| NE | 96 | 6 | 100 | 2 | 101 | 1 | 0 | 102 | Unknown
| 1998-10-02 22:36:51 | 78 | 4 | 78 | 4 | 82 | 0 | 58 | 24 | Unknown
| 1998-10-23 23:23:16 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | Unknown
| 1998-11-09 21:17:09 | 176 | 22 | 179 | 19 | 198 | 0 | 132 | 66 | InstallMaster 7
| 1998-12-03 23:11:32 | 43 | 0 | 43 | 0 | 43 | 0 | 28 | 15 | Unknown
| 1999-02-05 23:07:52 | 214 | 19 | 233 | 0 | 232 | 1 | 132 | 101 | Unknown
| 1999-04-05 18:07:26 | 4 | 0 | 4 | 0 | 4 | 0 | 4 | 0 | Unknown
| 1999-05-21 22:48:48 | 406 | 33 | 420 | 19 | 432 | 7 | 267 | 172 | Unknown
| 1999-08-17 17:25:48 | 238 | 24 | 250 | 12 | 254 | 8 | 143 | 119 | Unknown
| 2000-04-25 16:37:12 | 894 | 49 | 914 | 29 | 937 | 6 | 514 | 429 | InstallMaster 8
| 2001-08-13 19:13:38 | 319 | 8 | 325 | 2 | 323 | 4 | 222 | 105 | Unknown
| 2001-10-25 21:47:11 | 418 | 24 | 433 | 9 | 429 | 13 | 246 | 196 | Installation System 9
| 2031-05-20 22:54:01 | 4 | 0 | 4 | 0 | 4 | 0 | 4 | 0 | Unknown
| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -------
| Total: 3081 | 2892 | 189 | 2985 | 96 | 3041 | 40 | 1752 | 1329 |
```
PK Total : 438
PK OK : 432
PK ERROR : 6
PK Raw OK : 438
PK Raw ERROR: 0
Comments:
80 Without comment
23 Negative script deflate offset
21 Possible weird stuff at WiseScriptHeader.unknown_22 '9190A09A878B'.
14 Possible weird stuff at WiseScriptHeader.unknown_22 '958A928F8C8B'.
10 Possible weird stuff at WiseScriptHeader.unknown_22 'B890BE889E86'.
6 Possible weird stuff at WiseScriptHeader.unknown_22 'B6BF88BF96BF'.
6 Possible weird stuff at WiseScriptHeader.unknown_22 'A8B0ADB3BBB6'.
5 'Initializing Wise Installation Wizard...' found in the PE b'.data\x00\x00\x00' section.
3 Possible weird stuff at WiseScriptHeader.unknown_22 'BCADA6CEA5CD'.
3 Possible weird stuff at WiseScriptHeader.unknown_22 'C8CACBC8C6CC'.
2 Possible weird stuff at WiseScriptHeader.unknown_22 '99939E9D919E'.
2 0x18 mismatch, 0x18 00 08 ..
2 Possible weird stuff at WiseScriptHeader.unknown_22 'DB8F9E8C8C88'.
2 Possible weird stuff at WiseScriptHeader.unknown_22 'ADBF90BF93BF'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '8588C9C6C88B'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 'AB969C949A8B'.
1 0x18 mismatch, there is OP 0x00 right after 0x18
1 Script deflate offset is absurd high
1 Possible weird stuff at WiseScriptHeader.unknown_22 'CC918B90929D'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 'B4AAACB6B5AC'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '9D8D9E919B96'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '9C909B9A989A'.
1 Possible weird stuff at WiseScriptHeader.unknown_22 '8C929E9393D1'.
1 Overlay header unknown2 != 0x8000 but 0x0000.
Verify errors:
75 WS_ERROR_VALUE ERROR: parseWiseScriptHeader failed to read languageTexts.
46 WS_ERROR_INFLATE ERROR: Inflated size is larger then expected
25 WS_ERROR_SEEK ERROR: Failed seek to file offset
9 ERROR_VALUE ERROR: Advertised WiseScript.bin size looks insane.
7 WS_ERROR_INFLATE ERROR: zlib: invalid code lengths set
4 WS_ERROR_INFLATE ERROR: zlib: invalid distance too far back
4 WS_ERROR_INFLATE ERROR: zlib: invalid stored block lengths
3 WS_ERROR_PK_HEADER ERROR: PK signature unknown
3 WS_ERROR_VALUE ERROR: wiseScriptParsePath expected '%' at path start
2 WS_ERROR_VALUE ERROR: parseWiseScript unknown OP: 3A
2 WS_ERROR_INFLATE ERROR: zlib: invalid block type
2 ERROR_VALUE ERROR: Advertised .dib size looks insane.
1 WS_ERROR_BRANCHING ERROR: OP 0x23 LANG but not in LANG branch
1 WS_ERROR_INFLATE ERROR: zlib: invalid literal/length code
1 WS_ERROR_VALUE ERROR: This is a multi language installer but not all languages have their name set
1 WS_ERROR_VALUE ERROR: parseWiseScript unknown OP: 49
1 WS_ERROR_INFLATE ERROR: zlib: invalid distance code
1 WS_ERROR_BRANCHING ERROR: OP 0x23 LANG but currently not in a branch
1 ERROR_INFLATE ERROR: zlib: invalid stored block lengths
```
## `ignored.csv`
> Use `python ../test.py print-stats ignored.csv` to print stats.
| DATE | OK | ERR | LOK | LERR | ROK | RERR | v02 | v02E | VERSION
| :------------------ | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | :------
| NE | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 1992-06-20 00:22:17 | 0 | 9 | 0 | 9 | 0 | 9 | 0 | 9 | Unknown
| 1997-06-16 23:32:11 | 0 | 21 | 0 | 21 | 0 | 21 | 0 | 21 | Unknown
| 1999-02-05 23:07:52 | 0 | 2 | 2 | 0 | 0 | 2 | 0 | 2 | Unknown
| 1999-04-08 22:24:47 | 0 | 285 | 0 | 285 | 0 | 285 | 0 | 285 | Unknown
| 1999-04-17 21:22:36 | 0 | 3 | 0 | 3 | 0 | 3 | 0 | 3 | Unknown
| 1999-05-11 21:42:27 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 1999-05-21 22:48:48 | 0 | 2 | 2 | 0 | 0 | 2 | 0 | 2 | Unknown
| 1999-07-19 20:49:20 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 1999-08-16 11:00:06 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 1999-08-17 17:25:48 | 0 | 3 | 1 | 2 | 0 | 3 | 0 | 3 | Unknown
| 1999-12-03 12:59:21 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2000-03-21 16:49:03 | 0 | 8 | 0 | 8 | 0 | 8 | 0 | 8 | Unknown
| 2000-04-19 20:27:55 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2000-04-25 16:37:12 | 0 | 2 | 1 | 1 | 0 | 2 | 0 | 2 | InstallMaster 8
| 2000-07-05 21:22:55 | 0 | 8 | 0 | 8 | 0 | 8 | 0 | 8 | Unknown
| 2000-08-22 19:05:09 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2000-09-25 22:23:56 | 0 | 11 | 0 | 11 | 0 | 11 | 0 | 11 | Unknown
| 2000-12-08 23:54:42 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2000-12-09 00:33:39 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-01-09 15:08:41 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-01-09 15:09:05 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-01-11 21:55:28 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-03-06 21:15:30 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-05-22 22:13:59 | 0 | 23 | 0 | 23 | 0 | 23 | 0 | 23 | Unknown
| 2001-08-10 01:13:34 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-08-13 19:13:38 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | Unknown
| 2001-09-05 19:02:57 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2001-10-25 21:47:11 | 0 | 2 | 2 | 0 | 0 | 2 | 0 | 2 | Installation System 9
| 2001-10-26 14:34:09 | 0 | 3 | 0 | 3 | 0 | 3 | 0 | 3 | Unknown
| 2001-11-21 15:41:35 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2001-12-19 16:19:42 | 0 | 10 | 0 | 10 | 0 | 10 | 0 | 10 | Unknown
| 2002-01-16 21:20:28 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2002-01-22 21:47:35 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2002-02-12 16:33:09 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2002-03-29 17:59:03 | 0 | 12 | 0 | 12 | 0 | 12 | 0 | 12 | Unknown
| 2002-05-23 22:35:44 | 0 | 12 | 0 | 12 | 0 | 12 | 0 | 12 | Unknown
| 2002-06-24 20:22:31 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2002-08-05 17:25:35 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2002-11-18 16:53:37 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2002-12-02 19:31:43 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2002-12-16 20:16:07 | 0 | 17 | 0 | 17 | 0 | 17 | 0 | 17 | Unknown
| 2003-01-20 15:36:28 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2003-02-03 05:29:30 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2003-03-12 11:26:56 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2003-04-14 17:47:48 | 0 | 6 | 0 | 6 | 0 | 6 | 0 | 6 | Unknown
| 2003-04-22 18:23:04 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2003-04-24 15:10:23 | 0 | 4 | 0 | 4 | 0 | 4 | 0 | 4 | Unknown
| 2003-05-02 22:34:49 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2003-07-07 17:37:27 | 0 | 11 | 0 | 11 | 0 | 11 | 0 | 11 | Unknown
| 2003-10-09 21:05:12 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2003-11-21 19:16:37 | 0 | 23 | 0 | 23 | 0 | 23 | 0 | 23 | Unknown
| 2003-12-09 07:17:05 | 0 | 3 | 0 | 3 | 0 | 3 | 0 | 3 | Unknown
| 2004-01-29 07:13:04 | 0 | 20 | 0 | 20 | 0 | 20 | 0 | 20 | Unknown
| 2004-04-19 06:44:28 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2004-06-10 17:30:49 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2004-07-16 08:08:27 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2004-08-12 15:48:03 | 0 | 9 | 0 | 9 | 0 | 9 | 0 | 9 | Unknown
| 2004-09-10 00:10:25 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2004-09-10 17:38:04 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2004-10-22 09:20:02 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2004-10-28 13:15:26 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2004-12-10 17:05:37 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2005-04-08 16:46:17 | 0 | 7 | 0 | 7 | 0 | 7 | 0 | 7 | Unknown
| 2005-08-16 01:42:29 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2005-12-13 23:12:15 | 0 | 40 | 0 | 40 | 0 | 40 | 0 | 40 | Unknown
| 2006-11-13 19:32:07 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2006-11-27 18:36:03 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2006-12-15 22:21:24 | 0 | 4 | 0 | 4 | 0 | 4 | 0 | 4 | Unknown
| 2007-01-20 06:07:04 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2007-01-29 21:17:00 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2007-03-26 16:49:41 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2007-08-16 20:13:16 | 0 | 8 | 0 | 8 | 0 | 8 | 0 | 8 | Unknown
| 2007-11-20 22:12:45 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2007-11-20 22:52:34 | 0 | 9 | 0 | 9 | 0 | 9 | 0 | 9 | Unknown
| 2008-06-25 11:42:41 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2009-10-27 17:10:03 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2010-03-10 00:20:10 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2011-07-04 12:17:32 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2012-02-17 00:42:19 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2012-03-20 15:00:47 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | Unknown
| 2012-10-29 18:13:37 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2012-12-07 18:34:27 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| 2013-03-28 11:38:55 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | Unknown
| ------------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -------
| Total: 644 | 0 | 644 | 9 | 635 | 0 | 644 | 0 | 644 |
```
PK Total : 152
PK OK : 0
PK ERROR : 152
PK Raw OK : 0
PK Raw ERROR: 152
Comments:
10 Without comment
329 'Initializing Wise Installation Wizard...' found in the PE b'.rsrc\x00\x00\x00' section.
181 'Initializing Wise Installation Wizard...' found in the PE b'.rdata\x00\x00' section.
41 No overlay data
16 Overlay header unknown2 != 0x8000 but 0x0000.
10 'Initializing Wise Installation Wizard...' found in the PE b'.WISE\x00\x00\x00' section.
4 'Initializing Wise Installation Wizard...' found in the PE b'_winzip_' section.
3 Overlay header unknown2 != 0x8000 but 0x3137.
3 Overlay header unknown2 != 0x8000 but 0x496E.
2 Overlay header unknown2 != 0x8000 but 0x481C.
2 Overlay header unknown2 != 0x8000 but 0x5468.
2 Overlay header unknown2 != 0x8000 but 0x6973.
2 Overlay header unknown2 != 0x8000 but 0x003E.
2 Overlay header unknown2 != 0x8000 but 0x8620.
2 Possible weird stuff at WiseScriptHeader.unknown_22 '958A928F8C8B'.
2 Overlay header unknown2 != 0x8000 but 0x312C.
1 This not a PE file: 'DOS Header magic not found.'
1 Overlay header unknown2 != 0x8000 but 0x383E.
1 Overlay header unknown2 != 0x8000 but 0x6233.
1 Overlay header unknown2 != 0x8000 but 0x7376.
1 Overlay header unknown2 != 0x8000 but 0x3335.
1 Overlay header unknown2 != 0x8000 but 0x0205.
1 Overlay header unknown2 != 0x8000 but 0x0355.
1 Overlay header unknown2 != 0x8000 but 0x2E31.
1 Very small overlay size of 3496 bytes
1 Overlay header unknown2 != 0x8000 but 0xE819.
1 Overlay header unknown2 != 0x8000 but 0x0713.
1 Overlay header unknown2 != 0x8000 but 0x4C49.
1 Overlay header unknown2 != 0x8000 but 0x0062.
1 Overlay header unknown2 != 0x8000 but 0xDF64.
1 False positive PK, check the overlay header
1 Overlay header unknown2 != 0x8000 but 0x7072.
1 Overlay header unknown2 != 0x8000 but 0x6974.
1 Overlay header unknown2 != 0x8000 but 0x6520.
1 Overlay header unknown2 != 0x8000 but 0x7365.
1 Overlay header unknown2 != 0x8000 but 0x0700.
1 Overlay header unknown2 != 0x8000 but 0x74CD.
1 Overlay header unknown2 != 0x8000 but 0x0787.
1 Overlay header unknown2 != 0x8000 but 0x1100.
1 Overlay header unknown2 != 0x8000 but 0xB611.
1 Overlay header unknown2 != 0x8000 but 0x7E20.
1 Overlay header unknown2 != 0x8000 but 0x4544.
1 Overlay header unknown2 != 0x8000 but 0xA21E.
1 Overlay header unknown2 != 0x8000 but 0x6173.
1 Overlay header unknown2 != 0x8000 but 0x0AAF.
1 Overlay header unknown2 != 0x8000 but 0x726F.
1 Overlay header unknown2 != 0x8000 but 0xD753.
1 Overlay header unknown2 != 0x8000 but 0xE50A.
1 Overlay header unknown2 != 0x8000 but 0x6F67.
Verify errors:
354 ERROR_VALUE ERROR: Advertised WiseScript.bin size looks insane.
227 ERROR_INVALID_PENE ERROR: analyzeExe overlay size to small.
28 ERROR_VALUE ERROR: Advertised .dib size looks insane.
15 ERROR_INFLATE ERROR: zlib: invalid stored block lengths
4 WS_ERROR_INFLATE ERROR: Inflated size is larger then expected
4 WS_ERROR_CRC32 ERROR: CRC32 mismatch!
2 ERROR_INFLATE ERROR: zlib: invalid distance too far back
2 WS_ERROR_VALUE ERROR: parseWiseScriptHeader failed to read languageTexts.
2 ERROR_INFLATE ERROR: zlib: invalid block type
1 ERROR_INVALID_PENE ERROR: analyzeExe this is not a PE file for sure. The MS-DOS header signature doesn't match (not MZ).
1 ERROR_INVALID_PENE ERROR: analyzeExe overlay offset larger then file size.
1 WS_ERROR_SYSTEM_IO ERROR: Failed to find PK central directory size
1 WS_ERROR_CRC32 ERROR: PK CRC32 mismatch for '(null)'
1 ERROR_INFLATE ERROR: zlib: invalid code lengths set
1 ERROR_INFLATE ERROR: zlib: invalid distance code
```

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

157
tests/extended/rewise.py Normal file
View file

@ -0,0 +1,157 @@
import subprocess
from config import REWISE_DEV_PATH, REWISE_02_PATH
REWISE_STATUS_UNSET = -1
REWISE_STATUS_OK = 0
def getRewiseStatusString(status):
wsError = status & 64
status -= wsError
statusMap = {
-1: "UNSET",
0: "OK",
1: "ERROR_SYSTEM_IO",
2: "ERROR_ARGS",
3: "ERROR_INTERNAL",
4: "ERROR_EOF",
5: "ERROR_SEEK",
6: "ERROR_VALUE",
8: "ERROR_INVALID_PENE",
9: "ERROR_NOT_PENE",
10: "ERROR_NOT_WISE",
16: "ERROR_INFLATE",
17: "ERROR_PK_HEADER",
18: "ERROR_CRC32",
24: "ERROR_BRANCHING"
}
if status in statusMap:
if wsError:
return f"WS_{statusMap[status]}"
return statusMap[status]
else:
return "SEGFAULT"
PARSE_TYPE_INT = 1 # parse first int after text
PARSE_TYPE_STR = 2 # parse text after match
PARSE_TYPE_MATCH = 3 # bool (True when match found)
DEV_STDERR_PARSE = {
#attr name parse type match default
"isNe" : (PARSE_TYPE_MATCH, "DEBUG: NE ", False),
"isPk" : (PARSE_TYPE_MATCH, "DEBUG: IsPkFormat: 1", False),
"overlayOffset": (PARSE_TYPE_INT, "DEBUG: OverlayOffset: ", -1),
"peBuild" : (PARSE_TYPE_INT, "DEBUG: PE Build: ", 0),
"langCount" : (PARSE_TYPE_INT, "DEBUG: LanguageCount: ", -1),
"overlayUnk2" : (PARSE_TYPE_STR, "OverlayHeader.unknown_2 : ", ""),
"scriptDeflateOffset": (PARSE_TYPE_INT, "DEBUG: scriptDeflateOffset: ", -1)
}
DEV_STDOUT_PARSE = {
"wsHdrUnk22" : (PARSE_TYPE_STR, "WiseScriptHeader.unknown_22 : ", ""),
"scriptBuild" : (PARSE_TYPE_INT, "WiseScriptHeader.datetime : ", -1)
}
def getLinesFromBytes(the_bytes):
for line in the_bytes.decode("utf-8", errors="replace").split("\n"):
yield line
def parse(lines, parsedict):
result = {}
for line in lines:
for opt in parsedict:
ptype = parsedict[opt][0]
tomatch = parsedict[opt][1]
if line.startswith(tomatch):
if ptype == PARSE_TYPE_INT:
result.update({opt: int(line[len(tomatch):].split(" ")[0])})
elif ptype == PARSE_TYPE_STR:
result.update({opt: line[len(tomatch):].rstrip()})
elif ptype == PARSE_TYPE_MATCH:
result.update({opt: True})
break
for opt in parsedict:
if opt not in result:
result.update({opt: parsedict[opt][2]})
return result
def genericRewiseStats(file, rewisePath, rewiseOp):
r = subprocess.run([rewisePath, rewiseOp, file],
capture_output=True,
text=True, encoding="utf8")
result = {
"status": REWISE_STATUS_UNSET,
"error": ""
}
if r.returncode == 0:
result["status"] = REWISE_STATUS_OK
elif r.returncode < 127:
result["status"] = r.returncode
error = ""
errCount = 0
for line in reversed(r.stderr.split("\n")):
if line.startswith("ERROR:"):
error += line + "\n"
errCount += 1
if errCount == 5:
break;
result["error"] = error # last lines
else:
result["status"] = r.returncode
return (r, result)
def getRewiseDevVerifyStats(file):
return genericRewiseStats(file, REWISE_DEV_PATH, "-Vd")[1]
def getRewiseDevListStats(file):
return genericRewiseStats(file, REWISE_DEV_PATH, "-l")[1]
def getRewiseDevRawVerifyStats(file):
return genericRewiseStats(file, REWISE_DEV_PATH, "--raw-verify")[1]
def getRewise02VerifyStats(file):
return genericRewiseStats(file, REWISE_02_PATH, "-V")[1]
def getRewiseDevOtherStats(file):
r = subprocess.run([REWISE_DEV_PATH, "-ld", file],
capture_output=True,
text=False)
result = {"title": ""}
result.update(parse(getLinesFromBytes(r.stderr), DEV_STDERR_PARSE))
# This is extra, parse the title (inside WiseScript.bin)
r = subprocess.run([REWISE_DEV_PATH, "-zd", file],
capture_output=True,
text=False)
textsStart = False
for line in getLinesFromBytes(r.stdout):
if textsStart and line.startswith("Text: "):
result.update({"title": line[6:].replace("\"", "")})
break
if line.startswith("WiseScript Texts"):
textsStart = True
result.update(parse(getLinesFromBytes(r.stdout), DEV_STDOUT_PARSE))
return result
# For mass grepping
def debugPrint(file):
subprocess.run([REWISE_DEV_PATH, "-zd", file],
capture_output=False)

53
tests/extended/sources.py Normal file
View file

@ -0,0 +1,53 @@
import csv
import os
from config import SOURCE_PATH, DL_PATH
""" -- InstallerSource
Read sources to Wise installers.
The file format is CSV with the following columns
(b3, md5, filesize, url). It does not have a header.
"""
class InstallerSource:
def __init__(self, data):
self.b3, self.md5, self.filesize, self.dlUrl = data
self.filesize = int(self.filesize)
self.filepath = os.path.join(DL_PATH, self.b3)
def getFilename(self):
return os.path.basename(self.dlUrl)
def InstallerSourceIt(swFile):
with open(swFile, newline='') as fp:
for row in csv.reader(fp):
yield InstallerSource(row)
def InstallerSourceUniqIt(swFile):
sums = []
with open(swFile, newline='') as fp:
for row in csv.reader(fp):
sw = InstallerSource(row)
if sw.b3 in sums:
continue
sums.append(sw.b3)
yield sw
def InstallerSourceAllUniqIt():
for ent in os.listdir(SOURCE_PATH):
abspath = os.path.join(SOURCE_PATH, ent)
if not os.path.isfile(abspath):
continue
if os.path.splitext(ent)[1] != ".csv":
continue
for source in InstallerSourceUniqIt(abspath):
yield source

View file

@ -0,0 +1,27 @@
# sources
`.exe` files from <http://cd.textfiles.com>,
<http://discmaster.textfiles.com> and <https://archive.org> have been
grepped for the `Initializing Wise Installation Wizard...` string. The
files here are the results.
There are duplicates since every URL found is listed.
All the `.csv` files here have the same `b3, md5, filesize, dl-url`
structure, without header.
## `shareware.csv`
- Total size is 70.19 GiB
## `ignored.csv`
- Total size is 17.08 GiB
These have been filtered out, they are assumed false positives.
See the `acceptableInstallerIt()` function in `../installers.py` for the
filter rules.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

669
tests/extended/test.py Normal file

File diff suppressed because it is too large Load diff