/* $Id: diSc14n.h $ */

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

   Last updated:
   $Date: 2022-04-03 08:23 $
   $Revision: 3.1.0 $
*/

/* This source file has markup for Doxygen documentation <http://www.doxygen.org/> */
/** 
@file
@brief The C/C++ interface to the <b>diSc14n.dll</b> library.
@par Supported XML Canonicalization Transformations
The following C14N transformations are supported:<br>
<br>
"inclusive canonicalization" from 
<a href="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">Canonical XML Version 1.0</a> 
(reproduced as <a href="https://tools.ietf.org/html/rfc3076">RFC 3076</a>) with identifiers
<pre>
%http://www.w3.org/TR/2001/REC-xml-c14n-20010315
%http://www.w3.org/TR/2001/REC-xml-c14n-20010315\#WithComments
</pre>
"exclusive canonicalization" from
<a href="http://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/">Exclusive XML Canonicalization Version 1.0</a> 
(reproduced as <a href="https://tools.ietf.org/html/rfc3741">RFC 3741</a>) with identifiers
<pre>
%http://www.w3.org/2001/10/xml-exc-c14n\#
%http://www.w3.org/2001/10/xml-exc-c14n\#WithComments
</pre>

Identifier | nOptions
------------- | -------------
`http://www.w3.org/TR/2001/REC-xml-c14n-20010315` | `0`
`http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments`  | `#SC14N_METHOD_WITHCOMMENTS`
`http://www.w3.org/2001/10/xml-exc-c14n#`  | `#SC14N_METHOD_EXCLUSIVE` 
`http://www.w3.org/2001/10/xml-exc-c14n#WithComments`  | `#SC14N_METHOD_EXCLUSIVE` \| `#SC14N_METHOD_WITHCOMMENTS`

@par Supported XML encodings
Input is expected to be a well-formed XML document. 
Supported XML encodings are `UTF-8`, `ISO-8859-1` and `US-ASCII`.
@par 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 = C14N_File2String(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 = C14N_File2String(lpszOut, nchars, xmlfile, "", 0);
// ...
// do something with lpszOut...
// ...
free(lpszOut);
@endcode

@anchor nameorid
@par Specifying the tag name or Id with szNameOrId
Use the `szNameOrId` parameter to specify the element of the XML document to include or omit.

 - With options #SC14N_TRAN_OMITBYTAG or #SC14N_TRAN_SUBSETBYTAG, `szNameOrId` specifies the element's tag name.
   - By default, the *first* element with a matching tag name will be chosen.
   - To specify the N'th element, write as `tagname[N]` where `N=1,2,3,...`
 - With options #SC14N_TRAN_OMITBYID or #SC14N_TRAN_SUBSETBYID, `szNameOrId` specifies the element's Id
   - The default Id attribute name is `Id`, so the argument `myvalue` will find the element with `Id="myvalue"`.
   - To use a different attribute name -- for example `ID` -- write in the form `ID=myvalue` with no quotes.
 - With option #SC14N_TRAN_ENTIRE, the parameter is ignored, so just use `""` or `NULL`.

Exactly one element will be omitted or included. 
Tag names and Id values are case sensitive. 
It is an error (`NO_DATA_ERROR`) if no matching element is found.

@code
// Example 1. Omits the first element with the tag name <Signature>
r = C14N_File2File("c14nfile1.txt", "input.xml", "Signature", "", SC14N_TRAN_OMITBYTAG);

// Example 2. Finds and transforms the first element with the tag name <SignedInfo>
r = C14N_File2File("c14nfile2.txt", "input.xml", "SignedInfo", "", SC14N_TRAN_SUBSETBYTAG);

// Example 3. Finds and transforms the third element with the tag name <Data>
r = C14N_File2File("c14nfile3.txt", "input.xml", "Data[3]", "", SC14N_TRAN_SUBSETBYTAG);

// Example 4. Finds and transforms the element with attribute Id="foo"
r = C14N_File2File("c14nfile4.txt", "input.xml", "foo", "", SC14N_TRAN_SUBSETBYID);

// Example 5. Finds and transforms the element with attribute ID="bar"
r = C14N_File2File("c14nfile5.txt", "input.xml", "ID=bar", "", SC14N_TRAN_SUBSETBYID);

// Example 6. Omits element with attribute Id="thesig"
r = C14N_File2File("c14nfile6.txt", "input.xml", "thesig", "", SC14N_TRAN_OMITBYID);
@endcode

*/

#ifndef DISC14N_H_
#define DISC14N_H_ 1

#include <wchar.h>

/** @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 */
#define SC14N_DIG_DEFAULT 0			/**< Use default digest algorithm (SHA-1) */
#define SC14N_DIG_SHA1    0			/**< Use SHA-1 digest algorithm (default) */
#define SC14N_DIG_SHA256  0x2000	/**< Use SHA-256 digest algorithm */
#define SC14N_DIG_SHA384  0x3000	/**< Use SHA-384 digest algorithm */
#define SC14N_DIG_SHA512  0x5000	/**< Use SHA-512 digest algorithm */

/** Flatten the XML - remove all ignorable whitespace between tags */
#define SC14N_OPT_FLATTEN 0x10000

/* ACTION FLAGS */
/** Transform the entire document (default) */
#define SC14N_TRAN_ENTIRE    0
/** Omit the element with the given tag name */
#define SC14N_TRAN_OMITBYTAG 0x01
/** Transform the subset with the given tag name */
#define SC14N_TRAN_SUBSETBYTAG 0x02
/** Omit the element with the given Id */
#define SC14N_TRAN_OMITBYID  0x11
/** Transform the subset with the given Id */
#define SC14N_TRAN_SUBSETBYID  0x12

/** @cond */
/* DEPRECATED FLAGS (use OMIT instead) */
/** Omit (exclude) the element with the given tag name [<i>deprecated</i>]
@deprecated Use `#SC14N_TRAN_OMITBYTAG`
*/
#define SC14N_TRAN_EXCLUDEBYTAG 0x01
/** Omit (exclude) the element with the given Id [<i>deprecated</i>]
@deprecated Use `#SC14N_TRAN_OMITBYID`
*/
#define SC14N_TRAN_EXCLUDEBYID  0x11
/** @endcond */

/** Use inclusive c14n method [RFC 3076] (default) */
#define SC14N_METHOD_INCLUSIVE 0
/** Use exclusive c14n method [RFC 3741] */
#define SC14N_METHOD_EXCLUSIVE 0x100
/** Include comments in c14n form (@c \#WithComments) */
#define SC14N_METHOD_WITHCOMMENTS 0x800

/* CONSTANTS */
/** Maximum number of characters in base64-encoded hash digest value */
#define SC14N_MAX_DIGEST_CHARS 88
/** Maximum number of characters in an error message */
#define SC14N_MAX_ERROR_CHARS 4073


#ifdef __cplusplus
extern "C" {
#endif


/* GENERAL DIAGNOSTIC FUNCTIONS */

/** Gets version number of the core DLL. 
	@return Version number as an integer in the form `major*10000+minor*100+revision`
	e.g. DLL file version 1.2.x.3 will return 10203 */
long __stdcall SC14N_Gen_Version(void);


/** Gets 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 SC14N_Err_ErrorLookup() negative error code @endlink. */ 
long __stdcall SC14N_Gen_CompileTime(char *szOut, long nOutChars);


/** Gets 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.
	@param [in] nOptions Not used. Specify zero.
	@return Number of characters in or required for output string; 
	or a @link SC14N_Err_ErrorLookup() negative error code @endlink */
long __stdcall SC14N_Gen_ModuleName(char *szOut, long nOutChars, long nOptions);


/** Gets platform on which the core DLL is running ("Win32" or "Win64").
	@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 SC14N_Err_ErrorLookup() negative error code @endlink. */
long __stdcall SC14N_Gen_Platform(char *szOut, long nOutChars);


/** Gets licence type.
@returns ASCII value of the licence type: 'D'=Developer, 'T'=Trial 
@remark Note the Australian/English spelling of "Licence". */
long __stdcall SC14N_Gen_LicenceType(void);


/* ERROR-RELATED FUNCTIONS */

/** Retrieves the last error message (if available).
	@param [out] szOut Buffer to receive output string
	@param [in] nOutChars Maximum length of output string in bytes. Will not exceed `SC14N_MAX_ERROR_CHARS`.
	@return Number of characters in or required for output string; 
	or a @link SC14N_Err_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 SC14N_Err_LastError(char *szOut, long nOutChars);


/** Looks up description for 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 (may be positive or negative)
@return Number of characters in or required for output string; 
or a @link SC14N_Err_ErrorLookup() negative error code @endlink. */
long __stdcall SC14N_Err_ErrorLookup(char *szOut, long nOutChars, long nErrCode);


/***********************/
/* MAIN C14N FUNCTIONS */
/***********************/

/** Performs C14N transformation of XML document (file-to-file).
@param [in] szOutputFile Name of output file to create (will be overwritten if exists)
@param [in] szInputFile Name of input file containing XML document to be processed
@param [in] szNameOrId To specify the tag name or Id. See @ref nameorid "Specifying the tag name or Id".
@param [in] szParams InclusiveNamespaces PrefixList parameter (exclusive C14n only). Use `""` or `NULL` to ignore. 
@param [in] nOptions Option flags. Select exactly one of:<br>
`#SC14N_TRAN_ENTIRE` (0) to transform the entire document (default)<br>
`#SC14N_TRAN_OMITBYTAG` to omit the element with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYTAG` to transform subset with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_OMITBYID` to omit the element with Id specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYID` to transform subset with Id specified in `szNameOrId`<br>
and optionally add any of the following. Use the `|` operator to combine:<br>
`#SC14N_METHOD_EXCLUSIVE` to use exclusive c14n method (default is inclusive c14n method)<br>
`#SC14N_METHOD_WITHCOMMENTS` to include comments in c14n form (@c \#WithComments)<br> 
`#SC14N_OPT_FLATTEN` to remove all ignorable whitespace between tags<br>
@return Zero (0) on success or a @link SC14N_Err_ErrorLookup() negative error code @endlink.
*/
long __stdcall C14N_File2File(const char *szOutputFile, const char *szInputFile, const char *szNameOrId, const char *szParams, long nOptions);


/** Performs C14N transformation of XML document (file-to-memory).
@param [out] szOut Buffer to receive output as UTF-8 encoded bytes
@param [in] nOutChars Length of output buffer in bytes
@param [in] szInputFile Name of input file containing XML document to be processed
@param [in] szNameOrId To specify the tag name or Id. See @ref nameorid "Specifying the tag name or Id".
@param [in] szParams InclusiveNamespaces PrefixList parameter (exclusive C14n only). Use `""` or `NULL` to ignore.
@param [in] nOptions Option flags. Select exactly one of:<br>
`#SC14N_TRAN_ENTIRE` (0) to transform the entire document (default)<br>
`#SC14N_TRAN_OMITBYTAG` to omit the element with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYTAG` to transform subset with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_OMITBYID` to omit the element with Id specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYID` to transform subset with Id specified in `szNameOrId`<br>
and optionally add any of the following. Use the `|` operator to combine:<br>
`#SC14N_METHOD_EXCLUSIVE` to use exclusive c14n method (default is inclusive c14n method)<br>
`#SC14N_METHOD_WITHCOMMENTS` to include comments in c14n form (@c \#WithComments)<br>
`#SC14N_OPT_FLATTEN` to remove all ignorable whitespace between tags<br>
@return Number of characters in or required for output string; or a @link SC14N_Err_ErrorLookup() negative error code @endlink.
@remark The output is *always* UTF-8-encoded.
*/
long __stdcall C14N_File2String(char *szOut, long nOutChars, const char *szInputFile, const char *szNameOrId, const char *szParams, long nOptions);


/** Computes digest value of C14N transformation (file-to-digest).
@param [out] szOut Buffer to receive digest value output
@param [in] nOutChars Length of output buffer in bytes
@param [in] szInputFile Name of input file containing XML document to be processed
@param [in] szNameOrId To specify the tag name or Id. See @ref nameorid "Specifying the tag name or Id".
@param [in] szParams InclusiveNamespaces PrefixList parameter (exclusive C14n only). Use `""` or `NULL` to ignore.
@param [in] nOptions Option flags. Select exactly one of:<br>
`#SC14N_TRAN_ENTIRE` (0) to transform the entire document (default)<br>
`#SC14N_TRAN_OMITBYTAG` to omit the element with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYTAG` to transform subset with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_OMITBYID` to omit the element with Id specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYID` to transform subset with Id specified in `szNameOrId`<br>
and add one of:<br>
`#SC14N_DIG_SHA1` (0) to use SHA-1 algorithm (default) or<br>
`#SC14N_DIG_SHA256` to use SHA-256.<br>
and optionally add any of the following. Use the `|` operator to combine:<br>
`#SC14N_METHOD_EXCLUSIVE` to use exclusive c14n method (default is inclusive c14n method)<br>
`#SC14N_METHOD_WITHCOMMENTS` to include comments in c14n form (@c \#WithComments)<br>
`#SC14N_OPT_FLATTEN` to remove all ignorable whitespace between tags<br>
@return Number of characters in or required for output string; or a @link SC14N_Err_ErrorLookup() negative error code @endlink.
@remark The output is always encoded in base64. The maximum length is `SC14N_MAX_HASH_CHARS`.
*/
long __stdcall C14N_File2Digest(char *szOut, long nOutChars, const char *szInputFile, const char *szNameOrId, const char *szParams, long nOptions);


/** Performs C14N transformation of XML document (memory-to-memory).
@param [out] szOut Buffer to receive output as UTF-8 encoded bytes
@param [in] nOutChars Length of output buffer in bytes
@param [in] lpDataIn Pointer to XML data to be processed
@param [in] nDataLen Length of input data in bytes
@param [in] szNameOrId To specify the tag name or Id. See @ref nameorid "Specifying the tag name or Id".
@param [in] szParams InclusiveNamespaces PrefixList parameter (exclusive C14n only). Use `""` or `NULL` to ignore.
@param [in] nOptions Option flags. Select exactly one of:<br>
`#SC14N_TRAN_ENTIRE` (0) to transform the entire document (default)<br>
`#SC14N_TRAN_OMITBYTAG` to omit the element with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYTAG` to transform subset with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_OMITBYID` to omit the element with Id specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYID` to transform subset with Id specified in `szNameOrId`<br>
and optionally add any of the following. Use the `|` operator to combine:<br>
`#SC14N_METHOD_EXCLUSIVE` to use exclusive c14n method (default is inclusive c14n method)<br>
`#SC14N_METHOD_WITHCOMMENTS` to include comments in c14n form (@c \#WithComments)<br>
`#SC14N_OPT_FLATTEN` to remove all ignorable whitespace between tags<br>
@return Zero (0) on success or a @link SC14N_Err_ErrorLookup() negative error code @endlink.
@remark The output is *always* UTF-8-encoded.
*/
long __stdcall C14N_String2String(char *szOut, long nOutChars, const void *lpDataIn, long nDataLen, const char *szNameOrId, const char *szParams, long nOptions);


/** Computes digest value of C14N transformation (memory-to-digest).
@param [out] szOut Buffer to receive digest value output
@param [in] nOutChars Length of output buffer in bytes
@param [in] lpDataIn Pointer to XML data to be processed
@param [in] nDataLen Length of input data in bytes
@param [in] szNameOrId To specify the tag name or Id. See @ref nameorid "Specifying the tag name or Id".
@param [in] szParams InclusiveNamespaces PrefixList parameter (exclusive C14n only). Use `""` or `NULL` to ignore.
@param [in] nOptions Option flags. Select exactly one of:<br>
`#SC14N_TRAN_ENTIRE` (0) to transform the entire document (default)<br>
`#SC14N_TRAN_OMITBYTAG` to omit the element with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYTAG` to transform subset with tag name specified in `szNameOrId`<br>
`#SC14N_TRAN_OMITBYID` to omit the element with Id specified in `szNameOrId`<br>
`#SC14N_TRAN_SUBSETBYID` to transform subset with Id specified in `szNameOrId`<br>
and add one of:<br>
`#SC14N_DIG_SHA1` (0) to use SHA-1 algorithm (default) or<br>
`#SC14N_DIG_SHA256` to use SHA-256.<br>
and optionally add any of the following. Use the `|` operator to combine:<br>
`#SC14N_METHOD_EXCLUSIVE` to use exclusive c14n method (default is inclusive c14n method)<br>
`#SC14N_METHOD_WITHCOMMENTS` to include comments in c14n form (@c \#WithComments)<br>
`#SC14N_OPT_FLATTEN` to remove all ignorable whitespace between tags<br>
@return Number of characters in or required for output string; or a @link SC14N_Err_ErrorLookup() negative error code @endlink.
@remark The output is always encoded in base64. The maximum length is `SC14N_MAX_HASH_CHARS`.
*/
long __stdcall C14N_String2Digest(char *szOut, long nOutChars, const void *lpDataIn, long nDataLen, const char *szNameOrId, const char *szParams, long nOptions);


/*******************************/
/* UTILITY CONVERSION FUNCTION */
/*******************************/

/** Maps a UTF-16 (wide character) string to a UTF-8-encoded string.
@param [out] szOut Buffer to receive null-terminated UTF-8-encoded string.
@param [in] nOutChars Maximum length of output string in bytes (excluding the terminating null).
@param [in] wstr String of wide characters to be processed.
@return Number of characters (bytes) in or required for the output string; or a @link SC14N_Err_ErrorLookup() negative error code @endlink.
@remark Pass a NULL `szOut` or zero `nOutChars` to find the required output length in bytes. Allocate one extra byte for the terminating null.
@remark
```
long nchars;
char *buf = NULL;
wchar_t *wstr = L"áéíñóü"
// Find required output length (12 in this case)
nchars = SC14N_Utf8FromWide(NULL, 0, wstr);
printf("SC14N_Utf8FromWide returns %ld\n", nchars);
assert(nchars >= 0);
buf = malloc(nchars + 1);  // NB one extra byte
nchars = SC14N_Utf8FromWide(buf, nchars, wstr);
assert(nchars >= 0);
// Assumes console codepage is set to UTF-8
printf("[%s]\n", buf);
free(buf);
```
*/
long __stdcall SC14N_Utf8FromWide(char *szOut, long nOutChars, const wchar_t* wstr);


#ifdef __cplusplus
}
#endif

#endif /* DISC14N_H_ */