anycoder-a08b208a / utils.py
moddux's picture
Upload utils.py with huggingface_hub
0da308d verified
"""
Utility functions for DFIR iOS Enhancement Application
"""
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any, Optional
import hashlib
import sqlite3
# Apple epoch (January 1, 2001)
APPLE_EPOCH = datetime(2001, 1, 1, tzinfo=timezone.utc)
def apple_time_to_datetime(ts: Any) -> Optional[datetime]:
"""
Convert Apple timestamp to Python datetime.
Apple uses a custom epoch starting from January 1, 2001.
Args:
ts: Apple timestamp (can be seconds or nanoseconds)
Returns:
datetime object or None if conversion fails
"""
if ts is None:
return None
try:
ts = float(ts)
# Handle nanoseconds
if ts > 1e12:
ts = ts / 1e9
return APPLE_EPOCH + timedelta(seconds=ts)
except Exception:
return None
def normalize_phone(phone: Optional[str]) -> Optional[str]:
"""
Normalize phone number by removing common formatting characters.
Args:
phone: Raw phone number string
Returns:
Normalized phone number or None
"""
if not phone:
return phone
value = str(phone).replace("+1", "").replace(" ", "").replace("-", "")
value = value.replace("(", "").replace(")", "")
return value.strip() or None
def sha256_file(path: Path, chunk_size: int = 1024 * 1024) -> str:
"""
Calculate SHA256 hash of a file.
Args:
path: Path to the file
chunk_size: Size of chunks to read (default 1MB)
Returns:
Hexadecimal SHA256 hash string
"""
h = hashlib.sha256()
with path.open("rb") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()
def get_manifest_files(manifest_db: Path) -> list:
"""
Query Manifest.db for file entries.
Args:
manifest_db: Path to Manifest.db
Returns:
List of file entries from manifest
"""
if not manifest_db.exists():
return []
conn = sqlite3.connect(str(manifest_db))
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
try:
cursor.execute("""
SELECT fileID, domain, relativePath, flags, file
FROM Files
WHERE relativePath IS NOT NULL
""")
return [dict(row) for row in cursor.fetchall()]
except Exception:
return []
finally:
conn.close()
def find_artifact_in_manifest(manifest_files: list, artifact_name: str) -> Optional[dict]:
"""
Find a specific artifact in manifest files.
Args:
manifest_files: List of manifest file entries
artifact_name: Name of artifact to find
Returns:
File entry dict or None
"""
for file_entry in manifest_files:
if artifact_name in (file_entry.get('relativePath') or ''):
return file_entry
return None