James F. O'Brien

132 papers A* 9A 1B 6C 3Journal 69Unranked 44
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Nam Hee Kim, Jingjing May Liu, Jaakko Lehtinen, Perttu Hämäläinen, James F. O'Brien, Xue Bin Peng
2025 C conf
WoWMoM
Vivek Nair, Mark Roman Miller, Rui Wang, Brandon Huang, Christian Rack, Marc Erich Latoschik, James F. O'Brien
2025 C conf
WoWMoM
Mark Roman Miller, Vivek Nair, Eugy Han, Cyan DeVeaux, Christian Rack, Rui Wang, Brandon Huang, Marc Erich Latoschik, James F. O'Brien, Jeremy N. Bailenson
2024 J jnl
IEEE Trans. Vis. Comput. Graph.
Vivek Nair, Wenbo Guo, Rui Wang, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2024 conf
VR Workshops
Vivek Nair, Wenbo Guo, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2024 J jnl
CoRR
Vivek Nair, Mark Roman Miller, Rui Wang, Brandon Huang, Christian Rack, Marc Erich Latoschik, James F. O'Brien
2024 J jnl
CoRR
Mark Roman Miller, Vivek Nair, Eugy Han, Cyan DeVeaux, Christian Rack, Rui Wang, Brandon Huang, Marc Erich Latoschik, James F. O'Brien, Jeremy N. Bailenson
2024 conf
VR Workshops
Vivek Nair, Christian Rack, Wenbo Guo, Rui Wang, Shuixian Li, Brandon Huang, Atticus Cull, James F. O'Brien, Marc Erich Latoschik, Louis B. Rosenberg, Dawn Song
2024 J jnl
IEEE Secur. Priv.
Vivek Nair, Louis B. Rosenberg, James F. O'Brien, Dawn Song
2023 J jnl
CoRR
Gary D. Yngve, James F. O'Brien, Jessica K. Hodgins
2023 J jnl
CoRR
James F. O'Brien, Jessica K. Hodgins
2023 J jnl
CoRR
Jessica K. Hodgins, Wayne L. Wooten, David C. Brogan, James F. O'Brien
2023 J jnl
CoRR
Robert W. Sumner, James F. O'Brien, Jessica K. Hodgins
2023 J jnl
CoRR
James F. O'Brien, Robert E. Bodenheimer, Gabriel J. Brostow, Jessica K. Hodgins
2023 J jnl
CoRR
Vivek Nair, Wenbo Guo, Rui Wang, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2023 J jnl
CoRR
James F. O'Brien, Victor B. Zordan, Jessica K. Hodgins
2023 J jnl
CoRR
Vivek Nair, Wenbo Guo, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2023 J jnl
CoRR
James F. O'Brien, Jessica K. Hodgins
2023 J jnl
Proc. Priv. Enhancing Technol.
Vivek Nair, Gonzalo Munilla Garrido, Dawn Song, James F. O'Brien
2023 J jnl
CoRR
James F. O'Brien, Jessica K. Hodgins
2023 J jnl
CoRR
Vivek Nair, Christian Rack, Wenbo Guo, Rui Wang, Shuixian Li, Brandon Huang, Atticus Cull, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2023 conf
CVPR Workshops
Nikolaos Zioulis, James F. O'Brien
2023 conf
CVPR Workshops
Nikolaos Zioulis, James F. O'Brien
2023 J jnl
CoRR
Nikolaos Zioulis, James F. O'Brien
2023 J jnl
CoRR
Jessica K. Hodgins, James F. O'Brien, Jack Tumblin
2023 J jnl
CoRR
Vivek Nair, Viktor Radulov, James F. O'Brien
2023 J jnl
CoRR
Greg Turk, James F. O'Brien
2023 J jnl
CoRR
Vivek Nair, Louis B. Rosenberg, James F. O'Brien, Dawn Song
2023 A* conf
USENIX Security Symposium
Vivek Nair, Wenbo Guo, Justus Mattern, Rui Wang, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2023 J jnl
CoRR
Vivek Nair, Wenbo Guo, Justus Mattern, Rui Wang, James F. O'Brien, Louis B. Rosenberg, Dawn Song
2022 J jnl
Comput. Graph. Forum
Stephen W. Bailey, Jérémy Riviere, Morten Mikkelsen, James F. O'Brien
2021 J jnl
CoRR
Cuihua Shen, Mona Kasra, James F. O'Brien
2020 conf
SIGGRAPH Posters
Dorian Yao Chan, James F. O'Brien
2020 J jnl
ACM Trans. Graph.
Stephen W. Bailey, Dalton Omens, Paul C. DiLorenzo, James F. O'Brien
2019 J jnl
New Media Soc.
Cuihua Shen, Mona Kasra, Wenjing Pan, Grace A. Bassett, Yining Malloch, James F. O'Brien
2018 conf
EGSR (EI&I)
Rachel A. Albert, Dorian Yao Chan, Dan B. Goldman, James F. O'Brien
2018 J jnl
ACM Trans. Graph.
Stephen W. Bailey, Dave Otte, Paul C. DiLorenzo, James F. O'Brien
2018 conf
CHI Extended Abstracts
Mona Kasra, Cuihua Shen, James F. O'Brien
2016 conf
Symposium on Computer Animation
Stephen W. Bailey, Martin Watt, James F. O'Brien
2015 C conf
MIG
Pierre-Luc Manteaux, Wei-Lun Sun, François Faure, Marie-Paule Cani, James F. O'Brien
2015 J jnl
ACM Trans. Graph.
Rahul Narain, Rachel A. Albert, Abdullah Bulbul, Gregory J. Ward, Martin S. Banks, James F. O'Brien
2015 conf
Symposium on Computer Animation
George E. Brown, Armin Samii, James F. O'Brien, Rahul Narain
2015 J jnl
IEEE Trans. Vis. Comput. Graph.
Woojong Koh, Rahul Narain, James F. O'Brien
2014 J jnl
ACM Trans. Graph.
Tobias Pfaff, Rahul Narain, Juan Miguel de Joya, James F. O'Brien
2014 J jnl
ACM Trans. Graph.
Eric Kee, James F. O'Brien, Hany Farid
2014 J jnl
ACM Trans. Graph.
Matt Stanton, Ben Humberston, Brandon Kase, James F. O'Brien, Kayvon Fatahalian, Adrien Treuille
2014 conf
Symposium on Computer Animation
Woojong Koh, Rahul Narain, James F. O'Brien
2013 J jnl
ACM Trans. Graph.
Eric Kee, James F. O'Brien, Hany Farid
2013 J jnl
ACM Trans. Graph.
Tiantian Liu, Adam W. Bargteil, James F. O'Brien, Ladislav Kavan
2013 J jnl
ACM Trans. Graph.
Rahul Narain, Tobias Pfaff, James F. O'Brien
2013 J jnl
ACM Trans. Graph.
Doyub Kim, Woojong Koh, Rahul Narain, Kayvon Fatahalian, Adrien Treuille, James F. O'Brien
2013 J jnl
ACM Trans. Graph.
Pascal Clausen, Martin Wicke, Jonathan Richard Shewchuk, James F. O'Brien
2012 J jnl
ACM Trans. Graph.
Rahul Narain, Armin Samii, James F. O'Brien
2012 J jnl
IEEE Trans. Inf. Forensics Secur.
Valentina Conotter, James F. O'Brien, Hany Farid
2012 J jnl
ACM Trans. Graph.
James F. O'Brien, Hany Farid
2012 J jnl
ACM Trans. Graph.
Florian Hecht, Yeon Jin Lee, Jonathan Richard Shewchuk, James F. O'Brien
2011 A* conf
ICRA
Marco F. Cusumano-Towner, Arjun Singh, Stephen Miller, James F. O'Brien, Pieter Abbeel
2011 J jnl
ACM Trans. Graph.
Huamin Wang, James F. O'Brien, Ravi Ramamoorthi
2011 A* conf
ICRA
Shervin Javdani, Sameep Tandon, Jie Tang, James F. O'Brien, Pieter Abbeel
2011 J jnl
ACM Trans. Graph.
Adam G. Kirk, James F. O'Brien
2010 J jnl
ACM Trans. Graph.
Martin Wicke, Daniel Ritchie, Bryan Matthew Klingner, Sebastian Burke, Jonathan Richard Shewchuk, James F. O'Brien
2010 J jnl
ACM Trans. Graph.
Huamin Wang, Florian Hecht, Ravi Ramamoorthi, James F. O'Brien
2010 J jnl
ACM Trans. Graph.
Huamin Wang, James F. O'Brien, Ravi Ramamoorthi
2010 J jnl
ACM Trans. Graph.
Robert T. Held, Emily A. Cooper, James F. O'Brien, Martin S. Banks
2009 J jnl
Graph. Model.
Hayley N. Iben, James F. O'Brien
2009 J jnl
ACM Trans. Graph.
Nuttapong Chentanez, Ron Alterovitz, Daniel Ritchie, Lita Cho, Kris K. Hauser, Kenneth Y. Goldberg, Jonathan Richard Shewchuk, James F. O'Brien
2009 conf
Symposium on Computer Animation
Eric G. Parker, James F. O'Brien
2009 J jnl
Discret. Comput. Geom.
Hayley N. Iben, James F. O'Brien, Erik D. Demaine
2009 J jnl
Graph. Model.
Marie-Paule Cani, Frédéric H. Pighin, James F. O'Brien, Carol O'Sullivan
2007 B conf
Graphics Interface
Ashley M. Eden, Adam W. Bargteil, Tolga Göktekin, Sarah Beth Eisinger, James F. O'Brien
2007 conf
Symposium on Computer Animation
Nuttapong Chentanez, Bryan E. Feldman, François Labelle, James F. O'Brien, Jonathan Richard Shewchuk
2006 J jnl
ACM Trans. Graph.
Adam W. Bargteil, Tolga Göktekin, James F. O'Brien, John A. Strain
2006 conf
Symposium on Computer Animation
Adam W. Bargteil, Funshing Sin, Jonathan E. Michaels, Tolga Göktekin, James F. O'Brien
2006 conf
SIGGRAPH Sketches
Adam W. Bargteil, Funshing Sin, Jonathan E. Michaels, Tolga G. Göktekin, James F. O'Brien
2006 J jnl
ACM Trans. Graph.
Bryan Matthew Klingner, Bryan E. Feldman, Nuttapong Chentanez, James F. O'Brien
2006 conf
Symposium on Computer Animation
Hayley N. Iben, James F. O'Brien
2006 conf
SCG
Hayley N. Iben, James F. O'Brien, Erik D. Demaine
2006 conf
Symposium on Computer Animation
Nuttapong Chentanez, Tolga Göktekin, Bryan E. Feldman, James F. O'Brien
2006 conf
SIGGRAPH Sketches
Nuttapong Chentanez, Tolga G. Göktekin, Bryan E. Feldman, James F. O'Brien
2006 J jnl
Graph. Model.
Leif Kobbelt, Vadim Shapiro, Mario Botsch, Frédéric Cazals, Daniel Cohen-Or, Hugues Hoppe, Shi-Min Hu, Bert Jüttler, Myung-Soo Kim, James F. O'Brien
2005 conf
SIGGRAPH Sketches
Adam W. Bargteil, Tolga G. Göktekin, James F. O'Brien, John A. Strain
2005 J jnl
ACM Trans. Graph.
Bryan E. Feldman, James F. O'Brien, Bryan Matthew Klingner
2005 J jnl
Found. Trends Comput. Graph. Vis.
David A. Forsyth, Okan Arikan, Leslie Ikemoto, James F. O'Brien, Deva Ramanan
2005 J jnl
ACM Trans. Graph.
Okan Arikan, David A. Forsyth, James F. O'Brien
2005 conf
Symposium on Computer Animation
Bryan E. Feldman, James F. O'Brien, Bryan Matthew Klingner, Tolga G. Göktekin
2005 conf
SIGGRAPH Courses
Chen Shen, James F. O'Brien, Jonathan Richard Shewchuk
2005 conf
SIGGRAPH Courses
Chen Shen, James F. O'Brien, Jonathan Richard Shewchuk
2005 conf
Symposium on Solid and Physical Modeling
James F. O'Brien
2005 conf
SIGGRAPH Courses
Greg Turk, James F. O'Brien
2005 conf
SIGGRAPH Courses
James F. O'Brien, Terry S. Yoo
2005 conf
Symposium on Computer Animation
Okan Arikan, David A. Forsyth, James F. O'Brien
2005 conf
SIGGRAPH Courses
Greg Turk, James F. O'Brien
2005 conf
CVPR (2)
Adam G. Kirk, James F. O'Brien, David A. Forsyth
2005 conf
CVPR (2)
Adam G. Kirk, James F. O'Brien, David A. Forsyth
2004 J jnl
ACM Trans. Graph.
Tolga Göktekin, Adam W. Bargteil, James F. O'Brien
2004 conf
SCG
Jason H. Cantarella, Erik D. Demaine, Hayley N. Iben, James F. O'Brien
2004 conf
SIGGRAPH Computer Animation Festival
James F. O'Brien
2004 J jnl
ACM Trans. Graph.
Chen Shen, James F. O'Brien, Jonathan Richard Shewchuk
2004 conf
SIGGRAPH Sketches
Okan Arikan, David A. Forsyth, James F. O'Brien
2004 conf
SIGGRAPH Sketches
Hayley N. Iben, James F. O'Brien, Erik D. Demaine
2004 conf
SIGGRAPH Sketches
Adam G. Kirk, James F. O'Brien, David A. Forsyth
2004 B conf
Symposium on Geometry Processing
Ravi Krishna Kolluri, Jonathan Richard Shewchuk, James F. O'Brien
2003 J jnl
ACM Trans. Graph.
Bryan E. Feldman, James F. O'Brien, Okan Arikan
2003 B conf
Graphics Interface
Kris K. Hauser, Chen Shen, James F. O'Brien
2003 J jnl
ACM Trans. Graph.
Okan Arikan, David A. Forsyth, James F. O'Brien
2003 A* conf
SIGGRAPH
Ravi Krishna Kolluri, Jonathan Richard Shewchuk, James F. O'Brien
2002 A conf
IEEE Visualization
Josh Grant, Gordon Erlebacher, James F. O'Brien
2002 conf
SIGGRAPH Electronic Art and Animation Catalog
James F. O'Brien
2002 J jnl
ACM Trans. Graph.
James F. O'Brien, Adam W. Bargteil, Jessica K. Hodgins
2002 conf
SIGGRAPH Abstracts and Applications
Chen Shen, Kris K. Hauser, Christine M. Gatchalian, James F. O'Brien
2002 conf
SIGGRAPH Abstracts and Applications
Bryan E. Feldman, James F. O'Brien
2002 J jnl
ACM Trans. Graph.
Greg Turk, James F. O'Brien
2002 conf
Symposium on Computer Animation
James F. O'Brien, Chen Shen, Christine M. Gatchalian
2001 conf
Shape Modeling International
Greg Turk, Huong Quynh Dinh, James F. O'Brien, Gary D. Yngve
2001 conf
SIGGRAPH Video Review on Animation Theater Program
James F. O'Brien
2001 A* conf
SIGGRAPH
James F. O'Brien, Perry R. Cook, Georg Essl
2000 A* conf
SIGGRAPH
Gary D. Yngve, James F. O'Brien, Jessica K. Hodgins
2000 J jnl
Commun. ACM
James F. O'Brien, Jessica K. Hodgins
2000 B conf
Graphics Interface
James F. O'Brien, Robert E. Bodenheimer, Gabriel J. Brostow, Jessica K. Hodgins
2000 J jnl
IEEE Computer Graphics and Applications
James F. O'Brien, Victor B. Zordan, Jessica K. Hodgins
1999 J jnl
Comput. Graph. Forum
Robert W. Sumner, James F. O'Brien, Jessica K. Hodgins
1999 conf
SIGGRAPH Electronic Art and Animation Catalog
James F. O'Brien
1999 A* conf
SIGGRAPH
James F. O'Brien, Jessica K. Hodgins
1999 A* conf
SIGGRAPH
Greg Turk, James F. O'Brien
1998 B conf
Graphics Interface
Robert W. Sumner, James F. O'Brien, Jessica K. Hodgins
1998 J jnl
IEEE Trans. Vis. Comput. Graph.
Jessica K. Hodgins, James F. O'Brien, Jack Tumblin
1997 conf
SIGGRAPH Visual Proceedings
Jessica K. Hodgins, James F. O'Brien, Victor B. Zordan
1997 B conf
Graphics Interface
Jessica K. Hodgins, James F. O'Brien, Jack Tumblin
1995 A* conf
SIGGRAPH
Jessica K. Hodgins, Wayne L. Wooten, David C. Brogan, James F. O'Brien
1995 conf
CA
James F. O'Brien, Jessica K. Hodgins
1994 conf
VBC
James F. O'Brien, Norberto F. Ezquerra
1993 J jnl
IEEE Computer Graphics and Applications
Steven A. Cover, Norberto F. Ezquerra, James F. O'Brien, Richard Rowe, Thomas Gadacz, Ellen Palm
redb/extractors/capa.py
← Index redb/extractors/capa.py python
from dataclasses import asdict
import inspect
import json
import subprocess
import magic
from magika import Magika
from typing import Any, Dict, List, Tuple
from datetime import datetime, timezone

from redb.extractors.enum import Tag
from redb.models.dataclasses import CAPA
from redb.extractors.extractor import Extractor
from dotenv import load_dotenv
import os

load_dotenv(override=True)

class CAPAExtractor(Extractor):

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
    ):
        super().__init__(
            filepath, 
            log, 
            exporters,
            index_prefix, 
            elastic_index, 
            known_benign, 
            known_malicious
        )
        self.capa = None
        self.elastic_index = self.index_prefix + "-capa"

    def _replace_empty_keys(self, dictionary, replacement="default_empty_key"):
        """
        Replace empty keys in a dictionary with a specified replacement.

        Args:
        dictionary (dict): The input dictionary
        replacement (str): The replacement for empty keys (default: 'empty_key')

        Returns:
        dict: A new dictionary with empty keys replaced
        """
        # tmp_dict = {}
        # for k, v in dictionary.items():
        #     if k == '':
        #         tmp_dict[replacement] = dictionary[k]
        #     else:
        #         tmp_dict[k] = dictionary[k]
        # return tmp_dict
        return {(replacement if k == "" else k): v for k, v in dictionary.items()}

    def _extract_capa(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        TIMEOUT = int(os.getenv("CAPA_TIMEOUT")) # 5 minutes in seconds
        capa_command = [os.getenv("CAPA_PATH"), "-j", self.filepath] # COMMENT FOR TESTING ON MAC

        import signal

        # try:
        #     result = subprocess.run(
        #         capa_command, capture_output=True, text=True, check=True, timeout=TIMEOUT
        #     )
        # except subprocess.TimeoutExpired:
        #     self.log.error(f"The capa command timed out after {TIMEOUT} seconds")
        #     return {}
        # except subprocess.CalledProcessError as e:
        #     self.log.error(f"Error running capa: {e}")
        #     return {}

        # try:
        #     capa_output = json.loads(result.stdout)
        # except json.JSONDecodeError as e:
        #     self.log.error("Error parsing capa output: {e}")
        #     return {}

        # Create a process group for easier termination of all child processes
        try:
            # Start the process in a new process group
            process = subprocess.Popen(
                capa_command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                preexec_fn=os.setsid  # Use os.setsid() to create a new process group
            )
            
            # Implement timeout handling manually
            try:
                stdout, stderr = process.communicate(timeout=TIMEOUT)
                # Process completed within timeout
                if process.returncode != 0:
                    self.log.error(f"Error running capa, return code: {process.returncode}, stderr: {stderr}")
                    return {}
            except subprocess.TimeoutExpired:
                # Kill the entire process group on timeout
                self.log.warning(f"The capa command timed out after {TIMEOUT} seconds, terminating process group")
                
                try:
                    # Send SIGTERM to the entire process group
                    os.killpg(process.pid, signal.SIGTERM)
                    
                    # Give it a moment to terminate gracefully
                    try:
                        process.wait(timeout=3)
                    except subprocess.TimeoutExpired:
                        # If it's still running after 3 seconds, send SIGKILL
                        self.log.warning("Process didn't terminate with SIGTERM, sending SIGKILL")
                        os.killpg(process.pid, signal.SIGKILL)
                        
                    process.wait()  # Make sure process resources are fully cleaned up
                except (ProcessLookupError, OSError) as e:
                    self.log.warning(f"Error while killing process: {e}")
                    
                return {}
                
            try:
                capa_output = json.loads(stdout)
            except json.JSONDecodeError as e:
                self.log.error(f"Error parsing capa output: {e}")
                return {}

            capa_dump = {}  # dictionalry of capabilities
            capabilities = set()  # list of capabilities
            namespaces = set()  # list of namespaces
            attack_dump = {}  # dictionary of tuples [tactic](technique, technique_id)
            tactics = set()  # list of tactics
            techniques = set()  # list of techniques
            techniques_id = set()  # list of techniques_id
            mbc_dump = {}  # dictionary of tuples [objective](behavior, behavior_id)
            mbc_objectives = set()  # list of objectives
            mbc_behaviors = set()  # list of behaviors
            mbc_behaviors_id = set()  # list of behaviors_id

            if isinstance(capa_output, dict) and "rules" in capa_output:
                rules = capa_output["rules"]
                if isinstance(rules, dict):
                    for rule_name, rule_data in rules.items():
                        if isinstance(rule_data, dict) and "meta" in rule_data:
                            meta = rule_data["meta"]
                            if isinstance(meta, dict):
                                # Process capabilities
                                namespace = meta.get("namespace", "").lower()
                                # if namespace != 'lib':
                                if namespace not in capa_dump:
                                    capa_dump[namespace] = []
                                    namespaces.add(namespace)
                                capa_dump[namespace].append(rule_name)
                                capabilities.add(rule_name)

                                # Process ATTACK information
                                if "attack" in meta:
                                    for attack_entry in meta["attack"]:
                                        tactic = attack_entry.get("tactic", "")
                                        technique = attack_entry.get("technique", "")
                                        id = attack_entry.get("id", "")
                                        if tactic and technique:
                                            if tactic in attack_dump:
                                                attack_dump[tactic].append((technique, id))
                                            else:
                                                attack_dump[tactic] = [(technique, id)]
                                            tactics.add(tactic)
                                            techniques.add(technique)
                                            techniques_id.add(id)

                                # Process MBC information
                                if "mbc" in meta:
                                    for mbc_entry in meta["mbc"]:
                                        objective = mbc_entry.get("objective", "")
                                        behavior = mbc_entry.get("behavior", "")
                                        id = mbc_entry.get("id", "")
                                        if objective and behavior:
                                            if objective in mbc_dump:
                                                mbc_dump[objective].append((behavior, id))
                                            else:
                                                mbc_dump[objective] = [(behavior, id)]
                                            mbc_objectives.add(objective)
                                            mbc_behaviors.add(behavior)
                                            mbc_behaviors_id.add(id)

            # return {
            #     'capabilities_all': json.dumps(capabilities_all, indent=2),
            #     'capabilities': list(capabilities),
            #     'namespaces': list(namespaces),
            #     'attack': json.dumps(attack, indent=2),
            #     'tactics': list(tactics),
            #     'techniques': list(techniques),
            #     'techniques_id': list(techniques_id),
            #     'mbc': json.dumps(mbc, indent=2),
            #     'mbc_objectives': list(mbc_objectives),
            #     'mbc_behaviors': list(mbc_behaviors),
            #     'mbc_behaviors_id': list(mbc_behaviors_id)
            # }

            capa_dump = self._replace_empty_keys(capa_dump)
            attack_dump = self._replace_empty_keys(attack_dump)
            mbc_dump = self._replace_empty_keys(mbc_dump)
            self.capa = CAPA(
                json.dumps(capa_dump, indent=2),
                list(capabilities),
                list(namespaces),
                json.dumps(attack_dump, indent=2),
                list(tactics),
                list(techniques),
                list(techniques_id),
                json.dumps(mbc_dump, indent=2),
                list(mbc_objectives),
                list(mbc_behaviors),
                list(mbc_behaviors_id),
            )
            self.log.debug(f"CAPA dump: {self.capa})")
            
        except Exception as e:
            self.log.error(f"Unexpected error in CAPA extraction: {str(e)}")
            # Try to clean up any process if possible
            if 'process' in locals() and process.poll() is None:
                try:
                    os.killpg(process.pid, signal.SIGKILL)
                    process.wait()
                except:
                    pass
            return {}

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ElasticsearchExporter":
            return self.capa
        elif exporter_type == "ClickHouseExporter":
            current_time = datetime.now(timezone.utc)
            
            # Prepare data for multiple tables
            tables_data = {
                'multi_table': True,  # Flag for multi-table export
                
                # Raw data table
                'raw': {
                    'table': 'redb_capa',
                    'data': [[
                        self.sha256,
                        self.md5,
                        self.sha1,
                        current_time,
                        self.capa.capa_dump,  # capa_dump
                        self.capa.attack_dump,            # attack_dump
                        self.capa.mbc_dump                # mbc_dump
                    ]],
                    'column_names': [
                        'sha256', 'md5', 'sha1', 'analysis_date',
                        'capa_dump', 'attack_dump', 'mbc_dump'
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                        'DateTime64(3, \'UTC\')',
                        'JSON', 'JSON', 'JSON'
                    ]
                },
                
                # Capabilities table
                'capabilities': {
                    'table': 'redb_capa_capabilities',
                    'data': [
                        [self.sha256, self.md5, self.sha1, current_time, namespace, capability]
                        for namespace, capabilities in json.loads(self.capa.capa_dump).items()
                        for capability in capabilities
                    ],
                    'column_names': [
                        'sha256', 'md5', 'sha1', 'analysis_date',
                        'namespace', 'capability'
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                        'DateTime64(3, \'UTC\')',
                        'LowCardinality(String)', 'LowCardinality(String)'
                    ]
                },
                
                # MITRE ATT&CK table
                'attack': {
                    'table': 'redb_capa_attack',
                    'data': [
                        [self.sha256, self.md5, self.sha1, current_time, 
                         tactic, technique[0], technique[1]]  # technique[0] is the name, technique[1] is the ID
                        for tactic, techniques in json.loads(self.capa.attack_dump).items()
                        for technique in techniques
                    ],
                    'column_names': [
                        'sha256', 'md5', 'sha1', 'analysis_date',
                        'tactic', 'technique', 'technique_id'
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                        'DateTime64(3, \'UTC\')',
                        'LowCardinality(String)', 'LowCardinality(String)', 
                        'LowCardinality(String)'
                    ]
                },
                
                # MBC table
                'mbc': {
                    'table': 'redb_capa_mbc',
                    'data': [
                        [self.sha256, self.md5, self.sha1, current_time,
                         objective, behavior[0], behavior[1]]  # behavior[0] is the name, behavior[1] is the ID
                        for objective, behaviors in json.loads(self.capa.mbc_dump).items()
                        for behavior in behaviors
                    ],
                    'column_names': [
                        'sha256', 'md5', 'sha1', 'analysis_date',
                        'objective', 'behavior', 'behavior_id'
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                        'DateTime64(3, \'UTC\')',
                        'LowCardinality(String)', 'LowCardinality(String)',
                        'LowCardinality(String)'
                    ]
                }
            }
            
            return tables_data

    def get_clickhouse_table(self) -> str:
        return "redb_capa"  # Return the main table name

    def extract(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        try:
            self._extract_capa()
            return self.capa  # Return the extracted data instead of exporting directly
        except Exception as e:
            self.log.error(f"Error extracting CAPA: {e}")
            return None

    def tag(self):
        return Tag.CAPA.value