60 lines
2.3 KiB
Python
60 lines
2.3 KiB
Python
import os
|
|
import re
|
|
|
|
# Directories to scan
|
|
DIRS = ['./app', './Modules', './database']
|
|
|
|
# Patterns to search for
|
|
# 1. MySQL specific functions
|
|
PATTERNS = {
|
|
'MONTHNAME': r'MONTHNAME\(',
|
|
'DATE_FUNCTION': r'DATE\((?!\s*[\'"])', # Avoid matching strings like DATE('2023-01-01')
|
|
'YEAR_FUNCTION': r'YEAR\(',
|
|
'MONTH_FUNCTION': r'MONTH\(',
|
|
'DAY_FUNCTION': r'DAY\(',
|
|
'IFNULL': r'IFNULL\(',
|
|
}
|
|
|
|
# 2. Unquoted camelCase identifiers in raw SQL
|
|
# This is tricky, but we can look for selectRaw, DB::raw, sum(DB::raw), etc.
|
|
RAW_SQL_PATTERN = r'(?:selectRaw|DB::raw|sum\(DB::raw)\(([\'"])(.*?)\1\)'
|
|
|
|
def is_mixed_case(s):
|
|
return any(c.islower() for c in s) and any(c.isupper() for c in s)
|
|
|
|
def audit():
|
|
results = []
|
|
for root_dir in DIRS:
|
|
for root, dirs, files in os.walk(root_dir):
|
|
for file in files:
|
|
if file.endswith('.php'):
|
|
path = os.path.join(root, file)
|
|
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
lines = f.readlines()
|
|
for i, line in enumerate(lines):
|
|
# Check for function patterns
|
|
for name, pattern in PATTERNS.items():
|
|
if re.search(pattern, line):
|
|
results.append(f"{path}:{i+1} - Found {name}: {line.strip()}")
|
|
|
|
# Check for unquoted mixed case in raw SQL
|
|
matches = re.finditer(RAW_SQL_PATTERN, line)
|
|
for match in matches:
|
|
sql = match.group(2)
|
|
# Simple check for mixed case words not in quotes
|
|
words = re.findall(r'\b\w+\b', sql)
|
|
for word in words:
|
|
if is_mixed_case(word):
|
|
# Check if it's already double-quoted
|
|
if f'"{word}"' not in sql:
|
|
results.append(f"{path}:{i+1} - Unquoted mixed-case '{word}' in SQL: {line.strip()}")
|
|
|
|
return results
|
|
|
|
if __name__ == "__main__":
|
|
findings = audit()
|
|
if findings:
|
|
print("\n".join(findings))
|
|
else:
|
|
print("No PostgreSQL incompatibilities found.")
|