@@ -1725,33 +1725,29 @@ def to_archive(self, stream: Any):
17251725 raise C2paError (
17261726 self ._error_messages ['archive_error' ].format ("Unknown error" ))
17271727
1728- def sign (
1728+ def _sign_internal (
17291729 self ,
17301730 signer : Signer ,
17311731 format : str ,
1732- source : Any ,
1733- dest : Any = None ) -> Optional [bytes ]:
1734- """Sign the builder's content and write to a destination stream .
1735-
1732+ source_stream : Stream ,
1733+ dest_stream : Stream ) -> tuple [ int , Optional [bytes ] ]:
1734+ """Core signing logic shared between sign() and sign_file() methods .
1735+
17361736 Args:
1737- format: The MIME type or extension of the content
1738- source: The source stream (any Python stream-like object)
1739- dest: The destination stream (any Python stream-like object)
17401737 signer: The signer to use
1741-
1738+ format: The MIME type or extension of the content
1739+ source_stream: The source stream
1740+ dest_stream: The destination stream
1741+
17421742 Returns:
17431743 A tuple of (size of C2PA data, optional manifest bytes)
1744-
1744+
17451745 Raises:
17461746 C2paError: If there was an error during signing
17471747 """
17481748 if not self ._builder :
17491749 raise C2paError (self ._error_messages ['closed_error' ])
17501750
1751- # Convert Python streams to Stream objects
1752- source_stream = Stream (source )
1753- dest_stream = Stream (dest )
1754-
17551751 try :
17561752 format_str = format .encode ('utf-8' )
17571753 manifest_bytes_ptr = ctypes .POINTER (ctypes .c_ubyte )()
@@ -1777,12 +1773,40 @@ def sign(
17771773 manifest_bytes = bytes (manifest_bytes_ptr [:size ])
17781774 _lib .c2pa_manifest_bytes_free (manifest_bytes_ptr )
17791775
1780- return manifest_bytes
1776+ return result , manifest_bytes
17811777 finally :
17821778 # Ensure both streams are cleaned up
17831779 source_stream .close ()
17841780 dest_stream .close ()
17851781
1782+ def sign (
1783+ self ,
1784+ signer : Signer ,
1785+ format : str ,
1786+ source : Any ,
1787+ dest : Any = None ) -> Optional [bytes ]:
1788+ """Sign the builder's content and write to a destination stream.
1789+
1790+ Args:
1791+ format: The MIME type or extension of the content
1792+ source: The source stream (any Python stream-like object)
1793+ dest: The destination stream (any Python stream-like object)
1794+ signer: The signer to use
1795+
1796+ Returns:
1797+ The manifest bytes if available, None otherwise
1798+
1799+ Raises:
1800+ C2paError: If there was an error during signing
1801+ """
1802+ # Convert Python streams to Stream objects
1803+ source_stream = Stream (source )
1804+ dest_stream = Stream (dest )
1805+
1806+ # Use the core signing logic
1807+ _ , manifest_bytes = self ._sign_internal (signer , format , source_stream , dest_stream )
1808+ return manifest_bytes
1809+
17861810 def sign_file (self ,
17871811 source_path : Union [str ,
17881812 Path ],
@@ -1795,41 +1819,27 @@ def sign_file(self,
17951819 Args:
17961820 source_path: Path to the source file
17971821 dest_path: Path to write the signed file to
1822+ signer: The signer to use
17981823
17991824 Returns:
18001825 A tuple of (size of C2PA data, optional manifest bytes)
18011826
18021827 Raises:
18031828 C2paError: If there was an error during signing
18041829 """
1805- if not self ._builder :
1806- raise C2paError (self ._error_messages ['closed_error' ])
1807-
1808- source_path_str = str (source_path ).encode ('utf-8' )
1809- dest_path_str = str (dest_path ).encode ('utf-8' )
1810- manifest_bytes_ptr = ctypes .POINTER (ctypes .c_ubyte )()
1811-
1812- result = _lib .c2pa_builder_sign_file (
1813- self ._builder ,
1814- source_path_str ,
1815- dest_path_str ,
1816- signer ._signer ,
1817- ctypes .byref (manifest_bytes_ptr )
1818- )
1830+ # Get the MIME type from the file extension
1831+ mime_type = mimetypes .guess_type (str (source_path ))[0 ]
1832+ if not mime_type :
1833+ raise C2paError .NotSupported (f"Could not determine MIME type for file: { source_path } " )
18191834
1820- if result < 0 :
1821- error = _parse_operation_result_for_error (_lib .c2pa_error ())
1822- if error :
1823- raise C2paError (error )
1824-
1825- manifest_bytes = None
1826- if manifest_bytes_ptr :
1827- # Convert the manifest bytes to a Python bytes object
1828- size = result
1829- manifest_bytes = bytes (manifest_bytes_ptr [:size ])
1830- _lib .c2pa_manifest_bytes_free (manifest_bytes_ptr )
1835+ # Open source and destination files
1836+ with open (source_path , 'rb' ) as source_file , open (dest_path , 'wb' ) as dest_file :
1837+ # Convert Python streams to Stream objects
1838+ source_stream = Stream (source_file )
1839+ dest_stream = Stream (dest_file )
18311840
1832- return result , manifest_bytes
1841+ # Use the core signing logic
1842+ return self ._sign_internal (signer , mime_type , source_stream , dest_stream )
18331843
18341844
18351845def format_embeddable (format : str , manifest_bytes : bytes ) -> tuple [int , bytes ]:
0 commit comments