aboutsummaryrefslogtreecommitdiff
path: root/src/cerberus/integrations/chrome.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/cerberus/integrations/chrome.py')
-rw-r--r--src/cerberus/integrations/chrome.py135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/cerberus/integrations/chrome.py b/src/cerberus/integrations/chrome.py
new file mode 100644
index 0000000..ddc6acc
--- /dev/null
+++ b/src/cerberus/integrations/chrome.py
@@ -0,0 +1,135 @@
+"""Chrome/Chromium password export integration for Cerberus."""
+
+import csv
+import json
+import sqlite3
+import shutil
+import tempfile
+from pathlib import Path
+from typing import List, Optional, Dict, Any
+
+from ..core.models import PasswordEntry
+from . import BaseIntegration, register_integration, IntegrationError
+
+class ChromeIntegration(BaseIntegration):
+ """Integration with Chrome/Chromium password exports."""
+
+ def __init__(self, export_path: Optional[Path] = None):
+ """Initialize the Chrome integration.
+
+ Args:
+ export_path: Path to Chrome passwords CSV export
+ """
+ super().__init__()
+ self.export_path = export_path
+
+ def connect(self, export_path: Optional[Path] = None, **kwargs) -> bool:
+ """Load the Chrome passwords export file.
+
+ Args:
+ export_path: Path to the Chrome passwords CSV export
+
+ Returns:
+ bool: True if the export file exists and is accessible
+ """
+ if export_path:
+ self.export_path = Path(export_path)
+
+ if not self.export_path or not self.export_path.exists():
+ raise IntegrationError("Chrome passwords export file not found")
+
+ self.connected = True
+ return True
+
+ def list_entries(self) -> List[PasswordEntry]:
+ """List all password entries from the Chrome export.
+
+ Returns:
+ List of PasswordEntry objects
+
+ Raises:
+ IntegrationError: If not connected or error reading the export file
+ """
+ if not self.connected:
+ raise IntegrationError("Not connected to Chrome passwords")
+
+ entries: List[PasswordEntry] = []
+
+ try:
+ with open(self.export_path, 'r', encoding='utf-8') as f:
+ # Chrome CSV format: name,url,username,password
+ reader = csv.reader(f)
+
+ # Skip header if it exists
+ header = next(reader, None)
+ if not header or len(header) < 4:
+ # Try without skipping header
+ f.seek(0)
+
+ for row in reader:
+ if len(row) < 4: # Ensure we have enough columns
+ continue
+
+ name, url, username, password = row[:4]
+
+ # Create a PasswordEntry
+ entry = PasswordEntry(
+ website=name or url or "Unknown",
+ username=username,
+ password=password,
+ url=url
+ )
+
+ entries.append(entry)
+
+ except Exception as e:
+ raise IntegrationError(f"Error reading Chrome passwords export: {e}")
+
+ return entries
+
+ def import_entries(self, input_path: Optional[Path] = None) -> List[PasswordEntry]:
+ """Import entries from a Chrome passwords export.
+
+ Args:
+ input_path: Path to the Chrome passwords export file
+
+ Returns:
+ List of imported PasswordEntry objects
+ """
+ if input_path:
+ self.export_path = Path(input_path)
+
+ if not self.export_path or not self.export_path.exists():
+ raise IntegrationError("Chrome passwords export file not found")
+
+ return self.list_entries()
+
+ def export_entries(self, output_path: Path) -> bool:
+ """Export entries to a Chrome-compatible CSV file.
+
+ Args:
+ output_path: Path to save the exported data
+
+ Returns:
+ bool: True if export was successful
+ """
+ # This would require converting from our format to Chrome's format
+ # For now, we'll just raise a NotImplementedError
+ raise NotImplementedError("Export to Chrome format is not yet implemented")
+
+ @classmethod
+ def export_help(cls) -> str:
+ """Get instructions for exporting from Chrome.
+
+ Returns:
+ str: Instructions for exporting from Chrome
+ """
+ return """To export passwords from Chrome:
+ 1. Open Chrome and go to: chrome://settings/passwords
+ 2. Click the three dots menu next to 'Saved Passwords'
+ 3. Select 'Export passwords...'
+ 4. Follow the prompts to save the passwords to a CSV file
+ """
+
+# Register the integration with the name 'chrome'
+register_integration("chrome")(ChromeIntegration)