99import time
1010from .lib import dynamically_load_library
1111import mimetypes
12+ import logging
13+
14+ # Force output to stderr immediately
15+ sys .stderr .write ("## c2pa module loading - logging setup starting\n " )
16+ sys .stderr .flush ()
17+
18+ # Configure logging for the c2pa module
19+ logging .basicConfig (
20+ level = logging .DEBUG ,
21+ format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ,
22+ force = True # Force reconfiguration even if already configured
23+ )
24+
25+ # Get the logger for this module
26+ logger = logging .getLogger (__name__ )
27+ logger .setLevel (logging .DEBUG )
28+
29+ # Ensure the logger has a handler
30+ if not logger .handlers :
31+ handler = logging .StreamHandler (sys .stderr ) # Force to stderr
32+ handler .setLevel (logging .DEBUG )
33+ formatter = logging .Formatter ('%(asctime)s - %(name)s - %(levelname)s - %(message)s' )
34+ handler .setFormatter (formatter )
35+ logger .addHandler (handler )
36+
37+ sys .stderr .write ("## c2pa module loading - logging setup complete\n " )
38+ sys .stderr .flush ()
1239
1340# Define required function names
1441_REQUIRED_FUNCTIONS = [
@@ -1308,6 +1335,13 @@ def from_callback(
13081335 C2paError: If there was an error creating the signer
13091336 C2paError.Encoding: If the certificate data or TSA URL contains invalid UTF-8 characters
13101337 """
1338+ import logging
1339+ logger = logging .getLogger (__name__ )
1340+
1341+ sys .stderr .write ("## Signer.from_callback called\n " )
1342+ sys .stderr .flush ()
1343+ logger .info ("Signer.from_callback called" )
1344+
13111345 # Validate inputs before creating
13121346 if not certs :
13131347 raise C2paError (
@@ -1317,17 +1351,74 @@ def from_callback(
13171351 raise C2paError (
13181352 cls ._error_messages ['invalid_tsa' ].format ("Invalid TSA URL format" ))
13191353
1354+ sys .stderr .write ("## Creating wrapped_callback\n " )
1355+ sys .stderr .flush ()
1356+ logger .info ("Creating wrapped_callback" )
1357+
13201358 # Create a wrapper callback that handles errors and memory management
1321- def wrapped_callback (data : bytes ) -> bytes :
1359+ def wrapped_callback (context , data_ptr , data_len , signed_bytes_ptr , signed_len ):
1360+ logger = logging .getLogger (__name__ )
1361+
1362+ sys .stderr .write (f"## create_signer wrapped_callback: context: { context } , data_ptr: { data_ptr } , data_len: { data_len } , signed_bytes_ptr: { signed_bytes_ptr } , signed_len: { signed_len } \n " )
1363+ sys .stderr .flush ()
1364+ logger .debug (f"create_signer wrapped_callback called: context={ context } , data_len={ data_len } , signed_len={ signed_len } " )
1365+
13221366 try :
1367+ if not data_ptr or data_len <= 0 :
1368+ error_msg = f"Invalid input: data_ptr={ data_ptr } , data_len={ data_len } "
1369+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
1370+ sys .stderr .flush ()
1371+ logger .error (error_msg )
1372+ return 0 # Error: invalid input
1373+
1374+ # Convert C pointer to Python bytes
1375+ data = bytes (data_ptr [:data_len ])
1376+ sys .stderr .write (f"## Converted data: { len (data )} bytes\n " )
1377+ sys .stderr .flush ()
1378+ logger .debug (f"Converted data: { len (data )} bytes" )
1379+
13231380 if not data :
1324- raise ValueError ("Empty data provided for signing" )
1325- return callback (data )
1381+ error_msg = "Empty data after conversion"
1382+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
1383+ sys .stderr .flush ()
1384+ logger .error (error_msg )
1385+ return 0 # Error: empty data
1386+
1387+ # Call the user's callback
1388+ sys .stderr .write ("## Calling user callback...\n " )
1389+ sys .stderr .flush ()
1390+ logger .debug ("Calling user callback..." )
1391+ signature = callback (data )
1392+ sys .stderr .write (f"## User callback returned: { len (signature ) if signature else 0 } bytes\n " )
1393+ sys .stderr .flush ()
1394+ logger .debug (f"User callback returned: { len (signature ) if signature else 0 } bytes" )
1395+
1396+ if not signature :
1397+ error_msg = "User callback returned empty signature"
1398+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
1399+ sys .stderr .flush ()
1400+ logger .error (error_msg )
1401+ return 0 # Error: empty signature
1402+
1403+ # Copy the signature back to the C buffer
1404+ actual_len = min (len (signature ), signed_len )
1405+ sys .stderr .write (f"## Copying { actual_len } bytes to buffer (signature_len={ len (signature )} , signed_len={ signed_len } )\n " )
1406+ sys .stderr .flush ()
1407+ logger .debug (f"Copying { actual_len } bytes to buffer" )
1408+
1409+ for i in range (actual_len ):
1410+ signed_bytes_ptr [i ] = signature [i ]
1411+
1412+ sys .stderr .write (f"## Successfully copied signature, returning { actual_len } \n " )
1413+ sys .stderr .flush ()
1414+ logger .debug (f"Successfully copied signature, returning { actual_len } " )
1415+ return actual_len # Return the number of bytes written
13261416 except Exception as e :
1327- print (
1328- cls ._error_messages ['callback_error' ].format (
1329- str (e )), file = sys .stderr )
1330- raise C2paError .Signature (str (e ))
1417+ error_msg = f"Exception in wrapped_callback: { e } "
1418+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
1419+ sys .stderr .flush ()
1420+ logger .error (error_msg )
1421+ return 0 # Return 0 to indicate error
13311422
13321423 # Encode strings with error handling
13331424 try :
@@ -1339,21 +1430,38 @@ def wrapped_callback(data: bytes) -> bytes:
13391430 str (e )))
13401431
13411432 # Create the signer with the wrapped callback
1433+ # Store the callback as an instance attribute to keep it alive
1434+ signer_instance = cls .__new__ (cls )
1435+ signer_instance ._callback_cb = SignerCallback (wrapped_callback )
1436+
1437+ sys .stderr .write ("## About to call c2pa_signer_create from create_signer\n " )
1438+ sys .stderr .flush ()
1439+ logger .info ("About to call c2pa_signer_create from create_signer" )
1440+
13421441 signer_ptr = _lib .c2pa_signer_create (
13431442 None , # context
1344- SignerCallback ( wrapped_callback ) ,
1443+ signer_instance . _callback_cb ,
13451444 alg ,
13461445 certs_bytes ,
13471446 tsa_url_bytes
13481447 )
13491448
1449+ sys .stderr .write (f"## c2pa_signer_create returned: { signer_ptr } \n " )
1450+ sys .stderr .flush ()
1451+ logger .info (f"c2pa_signer_create returned: { signer_ptr } " )
1452+
13501453 if not signer_ptr :
13511454 error = _parse_operation_result_for_error (_lib .c2pa_error ())
13521455 if error :
13531456 raise C2paError (error )
13541457 raise C2paError ("Failed to create signer" )
13551458
1356- return cls (signer_ptr )
1459+ # Initialize the signer instance
1460+ signer_instance ._signer = signer_ptr
1461+ signer_instance ._closed = False
1462+ signer_instance ._error_messages = cls ._error_messages
1463+
1464+ return signer_instance
13571465
13581466 def __enter__ (self ):
13591467 """Context manager entry."""
@@ -1895,25 +2003,116 @@ def create_signer(
18952003 C2paError: If there was an error creating the signer
18962004 C2paError.Encoding: If the certificate data or TSA URL contains invalid UTF-8 characters
18972005 """
2006+ import logging
2007+ logger = logging .getLogger (__name__ )
2008+
2009+ sys .stderr .write ("## create_signer called\n " )
2010+ sys .stderr .flush ()
2011+ logger .info ("create_signer called" )
2012+
18982013 try :
18992014 certs_bytes = certs .encode ('utf-8' )
19002015 tsa_url_bytes = tsa_url .encode ('utf-8' ) if tsa_url else None
19012016 except UnicodeError as e :
19022017 raise C2paError .Encoding (
19032018 f"Invalid UTF-8 characters in certificate data or TSA URL: { str (e )} " )
19042019
2020+ sys .stderr .write ("## About to call c2pa_signer_create from create_signer\n " )
2021+ sys .stderr .flush ()
2022+ logger .info ("About to call c2pa_signer_create from create_signer" )
2023+
2024+ # Create a wrapper callback that handles errors and memory management
2025+ def wrapped_callback (context , data_ptr , data_len , signed_bytes_ptr , signed_len ):
2026+ logger = logging .getLogger (__name__ )
2027+
2028+ sys .stderr .write (f"## create_signer wrapped_callback: context: { context } , data_ptr: { data_ptr } , data_len: { data_len } , signed_bytes_ptr: { signed_bytes_ptr } , signed_len: { signed_len } \n " )
2029+ sys .stderr .flush ()
2030+ logger .debug (f"create_signer wrapped_callback called: context={ context } , data_len={ data_len } , signed_len={ signed_len } " )
2031+
2032+ # Add immediate return for debugging
2033+ sys .stderr .write ("## wrapped_callback entered - about to process\n " )
2034+ sys .stderr .flush ()
2035+
2036+ try :
2037+ if not data_ptr or data_len <= 0 :
2038+ error_msg = f"Invalid input: data_ptr={ data_ptr } , data_len={ data_len } "
2039+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
2040+ sys .stderr .flush ()
2041+ logger .error (error_msg )
2042+ return 0 # Error: invalid input
2043+
2044+ # Convert C pointer to Python bytes
2045+ data = bytes (data_ptr [:data_len ])
2046+ sys .stderr .write (f"## Converted data: { len (data )} bytes\n " )
2047+ sys .stderr .flush ()
2048+ logger .debug (f"Converted data: { len (data )} bytes" )
2049+
2050+ if not data :
2051+ error_msg = "Empty data after conversion"
2052+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
2053+ sys .stderr .flush ()
2054+ logger .error (error_msg )
2055+ return 0 # Error: empty data
2056+
2057+ # Call the user's callback
2058+ sys .stderr .write ("## Calling user callback...\n " )
2059+ sys .stderr .flush ()
2060+ logger .debug ("Calling user callback..." )
2061+ signature = callback (data )
2062+ sys .stderr .write (f"## User callback returned: { len (signature ) if signature else 0 } bytes\n " )
2063+ sys .stderr .flush ()
2064+ logger .debug (f"User callback returned: { len (signature ) if signature else 0 } bytes" )
2065+
2066+ if not signature :
2067+ error_msg = "User callback returned empty signature"
2068+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
2069+ sys .stderr .flush ()
2070+ logger .error (error_msg )
2071+ return 0 # Error: empty signature
2072+
2073+ # Copy the signature back to the C buffer
2074+ actual_len = min (len (signature ), signed_len )
2075+ sys .stderr .write (f"## Copying { actual_len } bytes to buffer (signature_len={ len (signature )} , signed_len={ signed_len } )\n " )
2076+ sys .stderr .flush ()
2077+ logger .debug (f"Copying { actual_len } bytes to buffer" )
2078+
2079+ for i in range (actual_len ):
2080+ signed_bytes_ptr [i ] = signature [i ]
2081+
2082+ sys .stderr .write (f"## Successfully copied signature, returning { actual_len } \n " )
2083+ sys .stderr .flush ()
2084+ logger .debug (f"Successfully copied signature, returning { actual_len } " )
2085+ return actual_len # Return the number of bytes written
2086+ except Exception as e :
2087+ error_msg = f"Exception in wrapped_callback: { e } "
2088+ sys .stderr .write (f"## ERROR: { error_msg } \n " )
2089+ sys .stderr .flush ()
2090+ logger .error (error_msg )
2091+ return 0 # Return 0 to indicate error
2092+
2093+ # Store the callback to keep it alive
2094+ if not hasattr (create_signer , '_callbacks' ):
2095+ create_signer ._callbacks = []
2096+
2097+ # Create the C callback and store it
2098+ c_callback = SignerCallback (wrapped_callback )
2099+ create_signer ._callbacks .append (c_callback ) # Keep it alive
2100+
19052101 signer_ptr = _lib .c2pa_signer_create (
19062102 None , # context
1907- SignerCallback ( callback ),
2103+ c_callback , # Use the stored callback
19082104 alg ,
19092105 certs_bytes ,
19102106 tsa_url_bytes
19112107 )
19122108
2109+ sys .stderr .write (f"## c2pa_signer_create returned: { signer_ptr } \n " )
2110+ sys .stderr .flush ()
2111+ logger .info (f"c2pa_signer_create returned: { signer_ptr } " )
2112+
19132113 if not signer_ptr :
19142114 error = _parse_operation_result_for_error (_lib .c2pa_error ())
19152115 if error :
1916- # More detailed error message when possible
19172116 raise C2paError (error )
19182117 raise C2paError ("Failed to create signer" )
19192118
0 commit comments