Mini Shell
#!/opt/imh-python/bin/python3
__author__ = 'chases'
from glob import glob
from pathlib import Path
import re
import subprocess
import sys
from typing import Union
FIND_NAMES = {
'version.php': 'versionfiles',
'concrete.php': 'concretefiles',
'base.php': 'basefiles',
'Version.php': 'zf_files',
'Kernel.php': 'symfonyfiles',
'DefaultSettings.php': 'mediawikifiles',
'CHANGELOG.txt': 'drupalfiles',
'CHANGELOG': 'magentofiles',
'RELEASE_NOTES.txt': 'oldmagefiles',
'Mage.php': 'oldmagefiles2',
'readme_en.txt': 'prestafiles',
'whatsnew_*html': 'whatsnewfiles',
'joomla.xml': 'joomlafiles',
'CHANGELOG.php': 'oldjoomla',
}
def find_target_files() -> list[Path]:
# fmt: off
cmd = ['find', '/home', '-mindepth', '3']
names = list(FIND_NAMES)
cmd.extend([
'-type', 'f',
'-not', '(', '-path', "*cache*", '-prune', ')',
'(', '-name', names[0]])
for name in names[1:]:
cmd.extend(['-o', '-name', name])
cmd.extend([')', '-print0'])
# fmt: on
ret = subprocess.run(
cmd, stdout=subprocess.PIPE, encoding='utf-8', check=False
)
return [Path(x) for x in ret.stdout.split('\0') if x]
def iterlines_path(path: Path):
try:
with open(path, encoding='utf-8', errors='replace') as infofile:
yield from infofile
except OSError as exc:
print(exc, file=sys.stderr)
def proc_version(path: Path) -> Union[str, None]:
str_path = str(path)
if 'config' in str_path:
for line in iterlines_path(path):
if not line.startswith('$APP_VERSION'):
continue
try:
version = line.split(' ')[2].replace("'", '').replace(';', '')
return f"Concrete5 {version}"
except IndexError:
pass
return None
if 'wp-includes' in str_path:
for line in iterlines_path(path):
if not line.startswith('$wp_version'):
continue
try:
version = line.split("'")[1]
return f'Wordpress {version}'
except IndexError:
pass
return None
if 'libraries' in str_path:
for line in iterlines_path(path):
if not line.lstrip().startswith('const RELEASE'):
continue
try:
version = line.split("'")[1]
return f'Joomla {version}'
except IndexError:
pass
return None
for line in iterlines_path(path):
if not line.startswith('$release'):
continue
try:
version = line.split(' ')[3].replace("'", '')
return f'Moodle {version}'
except IndexError:
pass
return None
def concrete_version(path: Path) -> Union[str, None]:
if 'config' not in str(path):
return None
for line in iterlines_path(path):
if 'version_installed' not in line:
continue
try:
return line.split("'")[3].strip()
except IndexError:
pass
return None
def oldconcrete_version(path: Path) -> Union[str, None]:
if 'config' not in str(path):
return None
for line in iterlines_path(path):
if 'APP_VERSION' not in line:
continue
if match := re.match(r'.*(\d+\.\d+\.\d+)', line):
return match.group(1)
return None
def mediawiki_version(path: Path) -> Union[str, None]:
if 'includes' not in str(path):
return None
for line in iterlines_path(path):
if not line.startswith('$wgVersion'):
continue
try:
return line.split("'")[1]
except IndexError:
pass
return None
def drupal_version(path: Path) -> Union[str, None]:
for line in iterlines_path(path):
if not line.lstrip().startswith('Drupal'):
continue
if match := re.match(r'Drupal (\d+\.\d+)', line):
return match.group(1)
return None
def prestashop_version(path: Path) -> Union[str, None]:
if 'docs' not in str(path):
return None
for line in iterlines_path(path):
if not line.startswith('VERSION'):
continue
try:
return line.split(" ")[1].strip()
except IndexError:
pass
return None
def cur_mage_version(path: Path) -> Union[str, None]:
if 'pdepend' not in str(path):
return None
for line in iterlines_path(path):
if not line.startswith('pdepend'):
continue
try:
return line.split("-")[1].strip().split(' ')[0]
except IndexError:
pass
return None
def old_mage_version(path: Path) -> Union[str, None]:
for line in iterlines_path(path):
if not line.startswith('==='):
continue
try:
return line.split(" ")[1].strip()
except IndexError:
pass
return None
def old_mage_version2(path: Path) -> Union[str, None]:
if 'app' not in str(path):
return None
for line in iterlines_path(path):
line = line.strip()
if not line.startswith('return'):
continue
if match := re.match(r"return '(\d+\.\d+\.\d+)", line):
return match.group(1)
return None
def joomla_version(path: Path) -> Union[str, None]:
str_path = str(path)
if 'administrator' in str_path or 'plugin' in str_path:
return None
for line in iterlines_path(path):
line = line.strip()
if not line.startswith('<version>'):
continue
if match := re.match(r"<version>(\d+\.\d+\.\d+)", line):
return match.group(1)
return None
def old_joomla_version(path: Path) -> Union[str, None]:
prefix = '--------------------'
for line in iterlines_path(path):
line = line.strip()
if not line.startswith(prefix):
continue
if match := re.match(rf"{prefix} (\d+\.\d+\.\d+)", line):
return match.group(1)
return None
def zen_version(zenfolder: Path) -> Union[str, None]:
try:
return '.'.join(
sorted(glob(f'{zenfolder}/whatsnew_*'))[-1]
.split('_')[-1]
.split('.')[0:3]
)
except IndexError:
return None
def zend_version(path: Path) -> Union[str, None]:
if 'Zend' not in str(path):
return None
for line in iterlines_path(path):
if 'const VERSION ' not in line:
continue
try:
return line.split("'")[1]
except IndexError:
pass
return None
def symfony_version(path: Path) -> Union[str, None]:
if not str(path).endswith('Symfony/Component/HttpKernel/Kernel.php'):
return None
for line in iterlines_path(path):
if 'const VERSION ' not in line:
continue
try:
return line.split("'")[1]
except IndexError:
pass
return None
def main():
paths: dict[str, list[Path]] = {x: [] for x in FIND_NAMES.values()}
for path in find_target_files():
if 'whatsnew_' in path.name:
paths['whatsnewfiles'].append(path)
continue
try:
paths[FIND_NAMES[path.name]].append(path)
except KeyError:
print("Unexpected file:", path, file=sys.stderr)
zenfolder = {path.parent for path in paths['whatsnewfiles']}
for folder in zenfolder:
if version := zen_version(folder):
print('ZenCart', version, folder)
for path in paths['joomlafiles']:
if version := joomla_version(path):
print('Joomla', version, path)
for path in paths['oldjoomla']:
if version := old_joomla_version(path):
print('Joomla', version, path)
for path in paths['magentofiles']:
if version := cur_mage_version(path):
print('Magento', version, path)
for path in path['oldmagefiles']:
if version := old_mage_version(path):
print('Magento', version, path)
for path in paths['oldmagefiles2']:
if version := old_mage_version2(path):
print('Magento', version, path)
for path in paths['concretefiles']:
if version := concrete_version(path):
print('Concrete5', version, path)
for path in paths['basefiles']:
if version := oldconcrete_version(path):
print('Concrete5', version, path)
for path in paths['versionfiles']:
if found := proc_version(path):
print(found, path)
for path in paths['mediawikifiles']:
if version := mediawiki_version(path):
print('MediaWiki', version, path)
for path in paths['drupalfiles']:
if version := drupal_version(path):
print('Drupal', version, path)
for path in paths['prestafiles']:
if version := prestashop_version(path):
print('Prestashop', version, path)
for path in paths['zend_files']:
if version := zend_version(path):
print('ZendFramework', version, path)
for path in paths['symfonyfiles']:
if version := symfony_version(path):
print('Symfony', version, path)
if __name__ == "__main__":
main()
Zerion Mini Shell 1.0