/* $Id: diFirmaSat2.h $ */

/* Copyright (C) 2006-22 DI Management Services Pty Limited. 
   All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net>

   Last updated:
   $Date: 2022-03-12 12:51 $
   $Revision: 10.50.0 $
*/

/* This source file has markup for Doxygen documentation <http://www.doxygen.org/> */
/** 
@file
	@brief The C/C++ interface to the <b>diFirmaSat2.dll</b> library.
	@par Note re output to szOut buffer
Functions that provide output in `szOut` require the buffer to be pre-dimensioned 
(i.e. allocated) to at least the specified length `nOutChars`
PLUS one extra for the null-terminating byte.
These functions always return the total length in bytes of the string they tried to create.
To find the required length, pass a NULL `szOut` or zero `nOutChars` argument,
then add one to the result for the required buffer size.
For example:
@code
char *xmlfile = "test.xml";
long nchars;
char *lpszOut;
// Find out how many bytes we need
nchars = SAT_MakePipeStringFromXml(NULL, 0, xmlfile, 0);
if (nchars <= 0) error();
// Pre-dimension, i.e allocate memory for string buffer
lpszOut = malloc(nchars+1);  // NB +1
if (!lpszOut) error();
nchars = SAT_MakePipeStringFromXml(lpszOut, nchars, xmlfile, 0);
// ...
// do something with lpszOut...
// ...
free(lpszOut);
@endcode
*/

#ifndef DIFIRMASAT2_H_
#define DIFIRMASAT2_H_ 1

/** @cond */
/* __stdcall convention required for Win32 DLL only */
#if __APPLE__
#define __stdcall __attribute__ ((visibility ("default")))
#elif (!( defined(_WIN32) || defined(WIN32) ))
#define __stdcall
#endif	
/** @endcond */

/* OPTION FLAGS */
/** Use default hash algorithm */
#define SAT_HASH_DEFAULT   0

/** @cond */
/* Use MD5 hash algorithm [REMOVED] (not relevant after 2010-12-31) */
//#define SAT_HASH_MD5       0x10
/** Force the SHA-1 hash algorithm */
#define SAT_HASH_SHA1      0x20
/** Force the SHA-256 hash algorithm */
#define SAT_HASH_SHA256    0x30
/** Return start date instead of expiry when using SAT_GetCertExpiry() [_deprecated_]
@deprecated Use SAT_QueryCert() with `notBefore` instead  */
#define SAT_DATE_NOTBEFORE 0x1000
/** Use strict XML type checking with SAT_ValidateXml() (default in v5.0 and above)  */
#define SAT_XML_STRICT     0
/** @endcond */

/** Use loose XML type checking with SAT_ValidateXml() */
#define SAT_XML_LOOSE      0x4000
/** Override strict checks for required nodes when signing (advanced users) */
#define SAT_XML_OVERRIDE_REQD	0x4000
/** Operate on Timbre Fiscal Digital (TFD) instead of Combrobante */
#define SAT_TFD            0x8000
/** Encode output in UTF-8 (default) */
#define SAT_ENCODE_UTF8    0
/** Encode output in Latin-1 (ISO-8859-1) */
#define SAT_ENCODE_LATIN1  1
/** Create output XML file _without_ UTF-8 byte-order mark (BOM) */
#define SAT_FILE_NO_BOM    0x2000
/** Get private key as PEM-style encrypted private key with SAT_GetKeyAsString() */
#define SAT_KEY_ENCRYPTED  0x10000
/** Output XML elements with no content in empty-element tag form */
#define SAT_XML_EMPTYELEMTAG  0x20000
/** Speed up the processing of large files (not TFD) */
#define SAT_FILE_BIGFILE      0x8000000
/** Output key or PFX file in PEM textual form with SAT_NewKeyFile() and SAT_WritePfxFile(). */
#define SAT_FORMAT_PEM    0x10000
/** Output PFX file in binary DER form with SAT_WritePfxFile() */
#define SAT_FORMAT_BINARY    0x40000
/** Flag to retrieve platform type with SAT_ModuleName() */
#define SAT_GEN_PLATFORM   0x40
/** Flag to return default digest algorithm with SAT_XmlReceiptVersion() */
#define SAT_GEN_DIGALG     0x2000
/* CONSTANTS */
/** Maximum number of characters in hex-encoded hash digest value */
#define SAT_MAX_HASH_CHARS 64
/** Maximum number of characters in an error message */
#define SAT_MAX_ERROR_CHARS 4073

#ifdef __cplusplus
extern "C" {
#endif

/********************************/
/* GENERAL DIAGNOSTIC FUNCTIONS */
/********************************/

/** Get version number of the core DLL 
	@return Version number as an integer in the form `Major*10000+Minor*100+Revision`.
	For example, version 9.2.15 would return 90215. */
long __stdcall SAT_Version(void);


/** Get date and time the core DLL module was last compiled 
	@param [out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@return Number of characters in or required for output string;
	or a @link SAT_ErrorLookup() negative error code @endlink. */ 
long __stdcall SAT_CompileTime(char *szOut, long nOutChars);


/** Get full path name of core DLL module 
	@param [out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink */
long __stdcall SAT_ModuleName(char *szOut, long nOutChars, long nOptions);


/** Get the licence type. 
	@return The ASCII value of the licence type, either 'D' (ASCII 68, 0x44) for the Developer Edition 
	or 'T' (ASCII 84, 0x54) for the Trial Edition. */
long __stdcall SAT_LicenceType(void);


/** Get additional information about the core DLL module 
@param [out] szOut Buffer to receive output string
@param [in] nOutChars Maximum length of output string in bytes
@param [in] nOptions Not used. Set as zero (0).
@return Number of characters in or required for output string;
or a @link SAT_ErrorLookup() negative error code @endlink */
long __stdcall SAT_Comments(char *szOut, long nOutChars, long nOptions);


/** Get platform for which the core DLL was compiled ("Win32" or "Win64").
@param [out] szOut Buffer to receive output string.
@param [in] nOutChars Maximum number of character bytes to be received (excluding the null terminating byte).
@return Number of characters in or required for output string.
*/
long __stdcall SAT_Platform(char *szOut, long nOutChars);


/***************************/
/* ERROR-RELATED FUNCTIONS */
/***************************/

/** Retrieve the last error message (if available).
	@param [out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark Call this function to find out more information about the last error.
	Not all functions set this.
*/
long __stdcall SAT_LastError(char *szOut, long nOutChars);


/** Look up error code.
	@param [out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] nErrCode Value of error code to lookup (positive or negative)
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink. */
long __stdcall SAT_ErrorLookup(char *szOut, long nOutChars, long nErrCode);


/*********************/
/* SAT XML FUNCTIONS */
/*********************/

/** Create the "pipe" string (cadena original) from an XML file.
	@param [out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] nOptions Use #SAT_ENCODE_LATIN1 to encode in Latin1.
	The default (0) is #SAT_ENCODE_UTF8 for UTF-8.
		Add #SAT_TFD to create the cadena original del Timbre Fiscal Digital instead.
		Add #SAT_XML_OVERRIDE_REQD to override strict checks for required nodes (advanced users).
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark Final string length may be shorter after extra spaces are removed.
	@see Note re output to szOut buffer. 
	*/
long __stdcall SAT_MakePipeStringFromXml(char *szOut, long nOutChars, const char *szXmlFile, long nOptions);


/** Create the signature as a base64 string ready for insertion as `Sello` node
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] szKeyFile Encrypted key file
	@param [in] szPassword Password for encrypted key file
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark This will use the default hash algorithm. 
	For advanced options use SAT_MakeSignatureFromXmlEx().
	*/
long __stdcall SAT_MakeSignatureFromXml(char *szOut, long nOutChars, const char *szXmlFile,
	const char *szKeyFile, const char *szPassword);


/** Create the signature as a base64 string ready for insertion as `Sello` node
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] szKeyFile Encrypted key file
	@param [in] szPassword Password for encrypted key file
	@param [in] nOptions Use 0 for default or #SAT_TFD to make `SelloSAT` for Timbre Fiscal Digital instead.
	Add #SAT_XML_OVERRIDE_REQD to override strict checks for required nodes (advanced users).
	@return Number of characters in or required for output string;
	or a @link SAT_ErrorLookup() negative error code @endlink. 
	*/
long __stdcall SAT_MakeSignatureFromXmlEx(char *szOut, long nOutChars, const char *szXmlFile,
	const char *szKeyFile, const char *szPassword, long nOptions);


/** Validate an XML file against SAT specification.
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] nOptions Use #SAT_XML_LOOSE to loosen strict checks on XML restrictions.
	Default (0) is `SAT_XML_STRICT`.
	@return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink. 
	@remark This only does a check that the XML elements are well-formed and in the correct order.
	It does not check the signature and may not catch all XML facet restriction errors that a strict XML parser may find.
	This function is meant as a quick check for structural problems in the XML file, not as a replacement
	for a full XSD checker.
*/
long __stdcall SAT_ValidateXml(const char *szXmlFile, long nOptions);


/** Verify the signature (`Sello`) in an XML file.
	@param [in] szXmlFile Name of XML file to be processed.
	@param [in] szCertFile (optional) certificate file
	@param [in] nOptions Use #SAT_TFD to verify `SelloSAT` in Timbre Fiscal Digital instead.
	@return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink. 
	@remark If no certificate file is specified, then the `Certificado` node in the XML file will be used.
		 If a separate certificate file is specified, it will be used instead.
	@note A separate certificate file is always required for the `SAT_TFD` option.
*/
long __stdcall SAT_VerifySignature(const char *szXmlFile, const char *szCertFile, long nOptions);


/** Sign an XML file.
	@param [in] szOutputFile Name of new output file to be created with 
		`Sello` and (optionally) `Certificado` and `NoCertificado` nodes completed.
	@param [in] szXmlFile Name of input XML file to be processed.
	@param [in] szKeyFile Encrypted private key file
	@param [in] szPassword Password for encrypted key file
	@param [in] szCertFile (optional) X.509 certificate file
	@param [in] nOptions Add any of the following options (use the `|` operator). 
	    Default (0) is to add BOM, empty elements in form `<foo></foo>`.  
	    - #SAT_XML_EMPTYELEMTAG to write all empty elements in the empty-element tag form `<foo />`.
	      The default is the start-end tag pair form `<foo></foo>`.
	    - #SAT_FILE_NO_BOM do not add byte-order mark (BOM) to output file. Default = add BOM.
		- #SAT_FILE_BIGFILE to speed up the processing of large files.
		- #SAT_XML_OVERRIDE_REQD to override strict checks for required nodes (advanced users).
		@return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark This will create an output XML document copied from the input 
	with the `Comprobante/@Sello` node overwritten by a new signature value.
	Any existing file with same name as the `szOutputFile` argument will be overwritten without warning.
	The input and output files can be the same. 
	If a certificate file `szCertFile` is specified then the `Certificado` and `NoCertificado` nodes
	will be overwritten in the output file with the values in the certificate file.

	@remark If a certficate file is not specified then the `Certificado` value in the XML will be used.
	@note For CFD v4.0/3.3 the `NoCertificado` attribute in the input _must_ be set to the correct certificate serial number 
	before signing or computing the digest. 
	It is an error (`CERT_NUM_ERROR`) if this value does not match the serial number of the certificate.
@code
<Comprobante Version="4.0" ...
NoCertificado="40001000000300000337"
Certificado=""
Sello=""
...>
@endcode

@note In a Retenciones document you _must_ set the `CertNum` attribute before signing.
In a ControlesVolumetricos document you must set _both_ the `noCertificado` and `certificado`
attributes before signing.
@note It is an error (`NO_MATCH_ERROR`) if the private key and certificate do not match.
@note _Alternative mode:_ Set `nOptions` to #SAT_TFD to create and insert a `tfd:TimbreFiscalDigital` 
element signed by the "PAC" with the given key/certificate pair. 
In this case the input file must be a properly signed v4.0/3.3 CFDI document without a TFD element, and 
the certificate _must_ be provided. 
This option may be useful for testing purposes.

@see SAT_InsertCert() and SAT_InsertCertToString().
*/
long __stdcall SAT_SignXml(const char *szOutputFile, const char *szXmlFile,
	const char *szKeyFile, const char *szPassword, const char *szCertFile, long nOptions);


/** Form the hex-encoded hash digest of piped string (cadena original) from an XML file.
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes (expect 64 by default)
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] nOptions Use #SAT_TFD to make digest of the cadena original del Timbre Fiscal Digital instead; otherwise use 0.
	Add #SAT_XML_OVERRIDE_REQD to override strict checks for required nodes (advanced users).
	@return Number of characters in or required for output string;
	or a @link SAT_ErrorLookup() negative error code @endlink. 
	*/
long __stdcall SAT_MakeDigestFromXml(char *szOut, long nOutChars, const char *szXmlFile, long nOptions);


/** Extract the hex-encoded message digest from the signature (Sello) in an XML file.
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes (expect 64 by default)
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] szCertFile (optional) certificate file
	@param [in] nOptions Use #SAT_TFD to extract digest instead from `SelloSAT` of Timbre Fiscal Digital; otherwise use 0.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark If the XML file contains a `Certificado` node, then that certificate will be used for the public key;
		otherwise the user must specify a separate certificate file.
	@note A separate certificate file _must_ be specified to use the `SAT_TFD` option.
*/
long __stdcall SAT_ExtractDigestFromSignature(char *szOut, long nOutChars, const char *szXmlFile, 
	const char *szCertFile, long nOptions);


/** Get the serial number of the X.509 certificate in special SAT format (20 ASCII digits) [_deprecated_].
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes (expect 20 characters)
	@param [in] szFileName X.509 certificate file or XML file with a `certificado` node
	@param [in] nOptions None. Use 0.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark This only works with a certificate issed by SAT with their special serial number format.
		 If input is an XML file, this extracts the number indirectly from the `certificado` node,
		 not the `noCertificado` node.
	@see Use instead @link SAT_QueryCert() @endlink with query `serialNumber`.
*/
long __stdcall SAT_GetCertNumber(char *szOut, long nOutChars, const char *szFileName, long nOptions);


/** Get the expiry date of the X.509 certificate in ISO time format 'yyyy-mm-ddThh:nn:ssZ' [_deprecated_].
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes (expect 20 characters)
	@param [in] szFileName X.509 certificate file or XML file with a `certificado` node
	@param [in] nOptions Use `SAT_DATE_NOTBEFORE` to get start date instead of expiry date; otherwise use 0.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark The time is GMT (UTC, Zulu time), not local.
	@deprecated Use instead @link SAT_QueryCert() @endlink with query `notAfter` or `notBefore`.
*/
long __stdcall SAT_GetCertExpiry(char *szOut, long nOutChars, const char *szFileName, long nOptions);


/** Get the certificate data as a base64 string.
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes.
	@param [in] szFileName X.509 certificate file or XML file with a `certificado` node
	@param [in] nOptions None. Use 0.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark Use to obtain the base64 value for the `certificado` node from a .CER file.
	It is an error if szOut is too small.
	If the input is an XML file, this function is equivalent to 
	@code SAT_GetXmlAttribute(szFileName, "certificado", "Comprobante"); @endcode         
*/
long __stdcall SAT_GetCertAsString(char *szOut, long nOutChars, const char *szFileName, long nOptions);


/** Extract attribute data for a given element in an XML file
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] szAttribute Name of attribute to find
	@param [in] szElement Name of element to find or xpath expression (see remarks)
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink. 
	In particular it will return `-NO_MATCH_ERROR` if the element/attribute combination cannot be found.
	@remark Attribute and element names are case-sensitive. 
	For a simple element name, the default behaviour is to get the attribute from the _first_ element found with the given name.
	Specify the element name in the form `"element[N]"`
	to extract the attribute for the N'th element found in the XML document, where `N` is a positive decimal integer (`N=1,2,3,...`).
	Setting `szElement=""` will output the value of the specified attribute from the root element of the XML document.
	Setting both `szElement=""` and `szAttribute=""` will output the name of the root element itself.
@par XPath Expression
Alternatively, specify an path expression in elementName using the `"/"` and `"//"` operators and optional predicate `[N]` where `N` is a positive integer. 
For example `"/Comprobante/Emisor"` or `"//Concepto[2]//Retencion[3]"`. 
This is a simplified form of XPath that selects the first occurrence of the element matching the path expression 
(whereas XPath would select all matching elements). Path expressions _must_ start with a `"/"` or `"//"` and must _not_ end with a `"/"`. 
No other XPath function or operator is accepted. Do not use namespace prefixes (e.g. `"cfdi:"`) in the path expression.
@par Simplified Xpath syntax:
- `/e1` -- selects the first `&lt;e1&gt;` document element (child element of the document node).
- `/e1/e2` -- selects the first &lt;e2&gt; child element of the first &lt;e1&gt; document element.
- `/e1[2]/e2[3]` -- selects the third &lt;e2&gt; child element of the second &lt;e1&gt; document element.
- `/e1[1]/e2[1]` -- same as `/e1/e2`.
- `//e2` -- the first &lt;e2&gt; element found anywhere (same as simple `e2`).
- `//e2[3]` -- the third &lt;e2&gt; element found anywhere (same as simple `e2[3]`).
- `/e1//e2` -- the first `&lt;e2&gt;` element found anywhere inside the `&lt;e1&gt;` element.
.

To test for the existence of an element, set `szAttribute=""`. This will return a positive value if it exists,
or return `-NO_MATCH_ERROR` if not found.
*/
long __stdcall SAT_GetXmlAttribute(char *szOut, long nOutChars, const char *szXmlFile,
	const char *szAttribute, const char *szElement);


/** Extract attribute data for a given element in an XML file with option to encode output.
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] szAttribute Name of attribute to find
	@param [in] szElement Name of element to find or xpath expression
	@param [in] nOptions Use #SAT_ENCODE_LATIN1 to encode output in Latin-1; otherwise use 0 for default UTF-8.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink. 
	@remark See remarks in SAT_GetXmlAttribute() for more details.
*/
long __stdcall SAT_GetXmlAttributeEx(char *szOut, long nOutChars, const char *szXmlFile,
	const char *szAttribute, const char *szElement, long nOptions);


/** Verify that the public key in an X.509 certificate matches the private key.
	@param [in] szKeyFile PKCS#8 encrypted key file
	@param [in] szPassword Password for encrypted key file
	@param [in] szCertFile X.509 certificate file or XML file with a `certificado` node
	@param [in] nOptions None. Use 0.
	@return Zero (0) if keys match or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark This will also verify that the password is correct for the key file.
*/
long __stdcall SAT_CheckKeyAndCert(const char *szKeyFile, const char *szPassword, const char *szCertFile, long nOptions);


/** Find version number of `Comprobante` element or ID number for other document types.
	@param [in] szXmlFile Name of XML file to be processed
	@param [in] nOptions Use #SAT_GEN_DIGALG to retrieve default digest algorithm for the document.
	@return Version number or ID number for XML document,  
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark Possible return values:
	- 40 =  Comprobante document with Version="4.0"
	- 33 =  Comprobante document with Version="3.3" (legacy)
	- 32 = Comprobante document with version="3.2" (legacy)
	- 1010/1020 = Retenciones document with Version="1.0"/"2.0"
	- 2011/2013 = CatalogoCuentas document with Version="1.1"/"1.3"
	- 2111/2113 = BalanzaComprobacion document with Version="1.1"/"1.3"
	- 2211/2213 = PolizasPeriodo document with Version="1.1"/"1.3"
	- 2312/2313 = AuxiliarFolios document with Version="1.2"/"1.3"
	- 2411/2413 = AuxiliarCtas document with Version="1.1"/"1.3"
	- 2511 = SelloDigitalContElec document with Version="1.1"
	- 4011/4012 = ControlesVolumetricos document with Version="1.1"/"1.2"
	.
	Return values with `nOptions=SAT_GEN_DIGALG`:
	- 1 = SHA-1 is default digest algorithm for document
	- 256 = SHA-256 is default digest algorithm for document
	.
	@remark For example:
	@code
	printf("%ld\n", SAT_XmlReceiptVersion("cfdv40-ejemplo.xml", 0)); // 40
	@endcode
	*/
long __stdcall SAT_XmlReceiptVersion(const char *szXmlFile, long nOptions);


/** Add a UTF-8 byte order mark (BOM) to a file if not already present.
	@param [in] szOutputFile Name of output file to be created.
	@param [in] szInputFile Name of input file to be processed.
	@param [in] nOptions None. Use 0.
	@return Zero (0) if output file with BOM successfully created, 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark This works with _any_ UTF-8 input file. It is an error if the input file contains invalid UTF-8 characters.
*/
long __stdcall SAT_FixBOM(const char *szOutputFile, const char *szInputFile, long nOptions);


/** Get the private key as a base64 string to use in XML de Cancelación.
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szKeyFile Encrypted key file
	@param [in] szPassword Password for encrypted key file
	@param [in] nOptions Use #SAT_KEY_ENCRYPTED to output encrypted key in PEM format.
		The default (0) will output unencrypted key in plain base64 form.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink. 
	@remark The default option creates a private key in base64 form suitable for a `llaveCertificado` node 
	in a `Cancelacion` element.
	@remark The output using #SAT_KEY_ENCRYPTED can be used as input to another function as the `szKeyFile` parameter.
	@warning The default option outputs your private key in _unencrypted_ form. Using it is a huge security risk. Use with caution.
*/
long __stdcall SAT_GetKeyAsString(char *szOut, long nOutChars, const char *szKeyFile, const char *szPassword, long nOptions);


/** Create a PFX (PKCS-12) file in PEM format suitable for a Cancelación.
	@param [in] szOutputFile Name of output PFX file to be created.
	@param [in] szPfxPassword Password to open new PFX file
	@param [in] szKeyFile Name of encrypted key file
	@param [in] szKeyPassword Password for encrypted key file
	@param [in] szCertFile Name of X.509 certificate file
	@param [in] nOptions Use:
	- 0 for the default output (base64)
	- #SAT_FORMAT_PEM for a PKCS12 file in PEM textual form
	- #SAT_FORMAT_BINARY for a PKCS12/PFX file in binary DER form
	@return Zero (0) if output file is successfully created, 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@warning Giving the PFX password to a third party is a security risk. Use with caution.
*/
long __stdcall SAT_WritePfxFile(const char *szOutputFile, const char *szPfxPassword, const char *szKeyFile, const char *szKeyPassword, const char *szCertFile, long nOptions);


/** Query an X.509 certificate.
	@param[out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes
	@param [in] szFileName X.509 certificate file or XML file with a `certificado` node
	@param [in] szQuery Query string. See Remarks.
	@param [in] nOptions Use `#SAT_ENCODE_LATIN1` to encode output in Latin-1; otherwise use 0 for default UTF-8.
	@return Number of characters in or required for output string; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark Valid queries are:
	- \b rfc to get the subject's RFC (expect 12 or 13 characters)
	- \b orgName or \b organizationName to get the issuer's organization name 
	(expect "Servicio de Administración Tributaria" in default UTF-8 encoding)
	- \b companyName to get the subject's organizationName
	- \b notAfter to get the expiry date [a replacement for SAT_GetCertExpiry()]
	- \b notBefore to get the start date [a replacement for SAT_GetCertExpiry() with `SAT_DATE_NOTBEFORE` option]
	- \b serialNumber to get the 20-digit SAT-specific serial number [a replacement for SAT_GetCertNumber()]
	- \b sigAlg to get the algorithm used to sign the certificate (e.g. "sha256WithRSAEncryption")
	- \b keySize to get the size in bits of the certificate's public key (e.g. "2048")
	.
	@note Times are GMT (UTC, Zulu time), not local, and are in the ISO time format `yyyy-mm-ddThh:nn:ssZ`. 
*/
long __stdcall SAT_QueryCert(char *szOut, long nOutChars, const char *szFileName, const char *szQuery, long nOptions);


/** Sign an XML document and outputs to memory.
	@param[out] szOut Buffer to receive output as a null-terminated string
	@param [in] nOutChars Maximum length of output buffer in bytes not including terminating null character
	@param [in] szXmlFile Name of input XML file to be processed (or a string containing XML data)
	@param [in] szKeyFile Encrypted private key file (or a string containing key data in PEM form)
	@param [in] szPassword Password for encrypted key file
	@param [in] szCertFile (optional) X.509 certificate file 
		(or a string containing certificate data in PEM or plain base64 form)
	@param [in] nOptions Use #SAT_XML_EMPTYELEMTAG to write all empty elements in the empty-element tag form `<foo />`. 
	The default (0) is the start-end tag pair form `<foo></foo>`.
	@return Number of bytes in or required for output buffer; 
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark The output string is always encoded in UTF-8
	@note It is an error if the private key and certificate do not match.
*/
long __stdcall SAT_SignXmlToString(char *szOut, long nOutChars, const char *szXmlFile,
	const char *szKeyFile, const char *szPassword, const char *szCertFile, long nOptions);


/** Generate a Universally Unique IDentifier (UUID) compliant with RFC 4122.
	@param[out] szOut Buffer to receive output as a null-terminated string
	@param [in] nOutChars Maximum length of output buffer in bytes not including terminating null character
	@param [in] nOptions None. Use 0.
	@return Number of characters in or required for output string;
	or a @link SAT_ErrorLookup() negative error code @endlink.
	@remark The output string is always exactly 36 characters long in the form
	"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" where 'x' is a lowercase hexadecimal digit [0-9a-f].
*/
long __stdcall SAT_Uuid(char *szOut, long nOutChars, long nOptions);


/** Replace non-ASCII characters in an XML document with XML numeric character references (where permitted).
@param[out] szOut Buffer to receive output as a null-terminated string
@param [in] nOutChars Maximum length of output buffer in bytes not including terminating null character
@param [in] szXmlFile Name of input XML file to be processed (or a string containing XML data)
@param [in] nOptions Default (0) is to encode characters that cannot be asciified in multibyte UTF-8.
Use option #SAT_ENCODE_LATIN1 to encode in ISO-8859-1 (Latin-1).
@return Number of bytes in or required for output buffer;
or a @link SAT_ErrorLookup() negative error code @endlink.
@remark In almost all cases, the output contains only US-ASCII characters and can safely 
be used as input to other functions without concern for character encoding issues. 
For example, the character "ó" (U+00F3 LATIN SMALL LETTER O WITH ACUTE) is replaced by the XML character reference `"&#xF3;"`.
@remark In certain cases, some characters in an XML document cannot be replaced by a numeric character reference,
for example where they are used in an element or attribute _name_, such as `Año="2016"`.
In these cases, they are left as UTF-8-encoded characters.
*/
long __stdcall SAT_Asciify(char *szOut, long nOutChars, const char *szXmlFile, long nOptions);


/** Insert certificate information into an XML document and outputs to a new file.
@param [in] szOutputFile Name of new output file to be created.
@param [in] szXmlFile Name of input XML file to be processed (or a string containing XML data)
@param [in] szCertFile X.509 certificate file
@param [in] nOptions Add any of the following options (use the `|` operator).
Default (0) is to add BOM, empty elements in form `<foo></foo>`.
- #SAT_XML_EMPTYELEMTAG to write all empty elements in the empty-element tag form `<foo />`.
The default is the start-end tag pair form `<foo></foo>`.
- #SAT_FILE_NO_BOM do not add byte-order mark (BOM) to output file. Default = add BOM.
@return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink.
@remark This will create an output XML document copied from the input
with the `noCertificado` and `Certificado` nodes overwritten by new values.
Any existing file with same name as the `szOutputFile` argument will be overwritten without warning.
The input and output files can be the same.
*/
long __stdcall SAT_InsertCert(const char *szOutputFile, const char *szXmlFile, const char *szCertFile, long nOptions);


/** Insert certificate information into an XML document and output to memory.
@param[out] szOut Buffer to receive output as a null-terminated string
@param [in] nOutChars Maximum length of output buffer in bytes not including terminating null character
@param [in] szXmlFile Name of input XML file to be processed (or a string containing XML data)
@param [in] szCertFile X.509 certificate file
(or a string containing certificate data in PEM or plain base64 form)
@param [in] nOptions Use #SAT_XML_EMPTYELEMTAG to write all empty elements in the empty-element tag form `<foo />`.
The default (0) is the start-end tag pair form `<foo></foo>`.
@return Number of bytes in or required for output buffer;
or a @link SAT_ErrorLookup() negative error code @endlink.
@remark The output string is always encoded in UTF-8
*/
long __stdcall SAT_InsertCertToString(char *szOut, long nOutChars, const char *szXmlFile, const char *szCertFile, long nOptions);

/** Save keyfile with a new password.
@param [in] szOutputFile Name of new output file to be created.
@param [in] szNewPassword Password for new key file.
@param [in] szKeyFile Name of input key file (or a string containing the key in PEM form).
@param [in] szPassword Password for existing key file.
@param [in] szReserved Reserved for future use. Specify `""` or `NULL`.
@param [in] nOptions Use #SAT_FORMAT_PEM to output key file in PEM textual format. The default (0) is binary DER encoded.
@return Zero (0) on success or a @link SAT_ErrorLookup() negative error code @endlink.
*/
long __stdcall SAT_NewKeyFile(const char *szOutputFile, const char *szNewPassword, const char *szKeyFile, const char *szPassword, const char *szReserved, long nOptions);

#ifdef __cplusplus
}
#endif

#endif /* DIFIRMASAT2_H_ */