tqsl-2.7.2/0000755000175000017500000000000014534122272012505 5ustar rmurphyrmurphytqsl-2.7.2/README0000644000175000017500000003317514534122272013376 0ustar rmurphyrmurphyThis is the TrustedQSL project, which provides tools for digitally signing Amateur Radio QSO records. src: Source code and documentation for tqsllib, the TrustedQSL library. apps: Source code for "tqsl" and other sample applications. html: Various legacy documents This document describes the changes to TrustedQSL since version 1.13 and explains how applications can use TQSL in their applications. Command Line Changes -------------------- Many applications use the 'tqsl' application in command line mode to sign log files. There were several new capabilities added to command line operation in 1.14. The first is that tqsl can now automatically sign and upload a log to the LoTW site for the user. This allows your application to simply write an adif file which is then processed and uploaded to LoTW without requiring the application to read the output file and either upload it or tell your user to upload it. The command line parser in 1.14 was rewritten and is less forgiving of improperly formatted command lines. Command Line Options -------------------- The following summarizes the command line options and what they do: Usage: tqsl [-a ] [-b ] [-e ] [-d] [-l ] [-s] [-f ] [-o ] [-u] [-x] [-p ] [-q] [-n] [-v] [-h] [-t ] [-c ] [Input ADIF or Cabrillo log file to sign] The following command line options may be specified on the command line: -a Specify dialog action - abort, all, compliant or ask This option instructs TQSL on how to handle QSOs that do not appear to be valid. There are many potential causes for invalid QSOs. Examples include QSOs with dates outside the valid range for the certificate being used, QSOs with invalid amateur callsigns, duplicate QSOs, and attempts to sign with an expired certificate. This option specifies how tqsl should handle these exceptions. Using "-a ask" instructs tqsl to use a dialog to ask the user how to proceed. This is the default behavior if "-a" is not provided on the command line. Using "-a abort" instructs tqsl to issue an error message when an exception QSO is processed and immediately abort signing. Using "-a compliant" instructs tqsl to sign the QSOs which are compliant (not duplicates, in date range, and with valid callsigns) and ignore any exception QSOs. This is the recommended behavior for command line applications but is not the default action for compatibility reasons. Using "-a all" instructs tqsl to process all QSOs, ignoring duplicates and invalid callsigns. QSOs outside the range of valid dates for the selected station certificate will not be signed, as they would not be accepted by Logbook. -b Set begin date for the QSO date filter. -e Set end date for the QSL date filter. These options filter QSOs being signed to those after the begin date and before the end date. If neither of these are supplied, then no filtering will be performed. These values will override any date range entries provided by the user. This implies that "-d" (suppress date range dialog) should be used with -b or -e. -d Suppress date range dialog This option instructs tqsl to not ask the user to select a range of dates for processing QSOs. If this is used, all QSOs in the input file will be selected for processing. Command line tools will usually include this option to suppress tqsl dialogs. However, this means that the logging program is responsible for filtering QSOs before delivering them to tqsl. -f Select handling option for QTH details This option instructs tqsl on how to handle the MY_ fields in an ADIF log file. These specify the callsign, QTH details such as zones, gridsquare, state/county, etc. for a QSO. If the log includes this detail, TQSL can read these fields and take action to use that information to ensure that the Station Location is correct. By default, TQSL will report any discrepancies between QTH and the Station Location; TQSL can also be directed to ignore the QTH information. -f ignore Directs TQSL to ignore the QTH information -f report Directs TQSL to report any differences between the station location and the MY_ QTH deails -f update Directs TQSL to overwrite the Station Location information with data from the log. When using "-f update", the ideal practice should be to either specify all QTH information (state, county, grid, zones) in the ADIF "MY_" fields, or use an minimal Station Location with no QTH data. -l Select Station Location. This option selects a station location. This is used for signing logs or in conjunction with the "-s" option to define a location for editing. -s Edit (if used with -l) or create Station Location This option can be used to create a new Station Location (-s without -l) or to edit an existing Station Location (when both -s and -l are provided). -o Output file name (defaults to input name minus extension plus .tq8) This option instructs tqsl where the signed output file will be stored. If it is not provided, the output file will be written to the same location as the input file with the extension changed to ".tq8" -u Upload after signing instead of saving This option instructs tqsl to upload the log file after it is successfully signed. -q Operate in batch mode, not menu-driven mode. -x Operate in batch mode, not menu-driven mode. If -x or -q are included on the command line, tqsl suppresses user dialogs and sends error messages to standard error. A logging application is expected to read this file and possibly display the contents to the user so they can see the results of the command action. If these options are not included, a calling application cannot distinguish between a successful signing and one where a user cancels the signing. -n Look for updated (new) versions of key files. If -n is given on the command line, tqsl checks for new versions of the tqsl program, an updated tqsl configuration file, and verifies that any user certificates are not about to expire. If any of these circumstances exist, the user is prompted to perform the required updates. When the check is completed, tqsl exits. This command line option can not be combined with any other command line options as it only performs an update check and does not sign any logs submitted with the command. -p Password for the signing key This option allows an application to provide the password for the private key that will be used to sign the log file. -v Display the version information and exit -h Display command line help These options allow the user to display the version number of tqsl or to obtain help on the command line usage. -t Open a diagnostic trace file at startup When supplied, this option enables diagnostic tracing at startup, opening the supplied file to record TQSL operations details. This is useful for debugging purposes. -c Use the given callsign when signing a log This option allows a logging program to specify what callsign to use for a log signing operation. This will override the callsign associated with the selected station location, if any. Command Line Usage ------------------ An application that uses the command line invokes the tqsl binary, optionally providing a set of options that dictate how tqsl operates. Normally, such an application should include the "-x" or "-q" options to indicate to tqsl that application popups should be suppressed. Errors discovered during the signing process are sent to the standard error file. Callers would normally indicate where those messages should be sent by adding "2> file.txt" to the command line used to run tqsl. This directs the shell (Windows or Unix) to write the error messages to that file. When operated in "batch" mode (i.e. -x or -q used), tqsl provides information that the calling program can use to determine if the signing operation succeeded. The first way is by capturing tqsl's exit status code. This provides information on success or failure using the following values: 0 - Success: all QSOs submitted were signed and saved or uploaded 1 - Cancelled by user 2 - The log was rejected by the LoTW server 3 - The response from the LoTW server was unexpected 4 - An error occurred in tqsl 5 - An error occurred in tqsllib (invalid filename, bad file format) 6 - Unable to open input file 7 - Unable to open output file 8 - No QSOs were processed because some QSOs were duplicates or out of date range (no QSOs written) 9 - Some QSOs were processed, and some QSOs were ignored because they were duplicates or out of date range (some QSOs written) 10 - Command syntax error 11 - LoTW network connection failed (no network or LoTW is unreachable) 12 - Unknown error 13 - The TQSL duplicates database is locked. This exit status is also written to stderr in a format that can be parsed by the calling application. The last output from tqsl will be of the format hh:mm:ss AM|PM Final Status: Description (code) (For cases where the language is not English, this will be duplicated - first in the local language, then in English.) The first two fields are a timestamp, the words "Final Status:" always appears. Following that is a short descriptive message giving the exit status. The last thing on the line is the numeric exit code (as above) in parenthesis. Examples of output follows: 05:57:39 PM: Warning: Signing cancelled 05:57:39 PM: No records output 05:57:39 PM: Final Status: cancelled by user (1) 06:05:56 PM: /home/rmurphy/k1mu.adi: 414 QSO records were duplicates 06:05:56 PM: /home/rmurphy/k1mu.adi: wrote 1 records to /home/rmurphy/k1mu.tq8 06:05:56 PM: /home/rmurphy/k1mu.tq8 is ready to be emailed or uploaded. Note: TQSL assumes that this file will be uploaded to LoTW. Resubmitting these QSOs will cause them to be reported as duplicates. 06:05:56 PM: Final Status: Some QSOs were duplicates or out of date range (9) An example usage for signing a log would be tqsl -q -l "K1MU home" -p "Insecure" -a compliant -u -d k1mu.adi 2>temp.txt This indicates quiet mode (-q), selects a station location and a password, indicates that only compliant QSOs will be written (-a), uploads to LoTW (-u), suppresses date popups (-d), provides an input file (k1mu.adi), and finally writes log messages to temp.txt. The logging program would read and process that log once tqsl is done. An application would add "-o" to indicate where tqsl should write the signed log if "-u" (upload) is not provided. Command line applications are strongly encouraged to add "-a=compliant" to their invocations of tqsl, and to consider storing and displaying the log messages to their users. Application Changes ------------------- Some logging applications directly call tqsllib functions to sign log files. The application programming interface (API) to tqsllib has not changed in ways that introduce incompatibilities, but there are additional API calls which are necessary for applications to allow duplicate QSO processing to work properly. Normally, an application will call tqsl_beginCabrilloConverter() or tqsl_beginADIFConverter to begin signing a log file. After the converter is created by those calls, the application should then call tqsl_setConverterAllowDuplicates(conv, false) which tells tqsllib that duplicate processing should be enabled. If you do not call tqsl_setConverterAllowDuplicates, the library will assume that duplicates should be permitted (for compatibility reasons), which may cause unnecessary QSOs to be uploaded. If duplicate suppression is enabled, there is a new error return from tqsl_getConverterGABBI that indicates duplicate QSOs. In this case, tQSL_Error is set to TQSL_DUPLICATE_QSO. Software may need to be modified to handle this new result and act appropriately (ignore it, or abort the signing operation.) After successful processing of a log, an application should call either tqsl_convertCommit(conv) or tqsl_convertRollBack(conv) prior to calling tqsl_endConverter() to signal that a log conversion has completed. tqsl_converterCommit() indicates to tqsllib that the log has been successfully processed and that the QSOs should be added to the duplicate detection database. Calling tqsl_converterRollBack() indicates to tqsllib that the log has not been successfully processed and that the QSO records should not be added to the duplicate database. Simply adding the necessary call before the converter is closed is enough to bring the application up to date. change tqsl_endConverter(&conv) to tqsl_converterCommit(conv); tqsl_endConverter(&conv); Using tqsllib ------------- A minimal set of calls to permit an application to sign a log is the following. Of course, error checking should be performed for each call. tqsl_getStationLocation(&loc, location_name); tqsl_getLocationCallSign(loc, callsign, sizeof callsign); tqsl_getLocationDXCCEntity(loc, &dxcc); tqsl_selectCertificates(&certlist, &ncerts, callsign, dxcc); tqsl_beginADIFConverter(&conv, input_file, certlist, ncerts, loc); tqsl_setConverterAllowDuplicates(conv, false); tqsl_setConverterAppName(conv, "myAppName"); (tell tqsllib the name of your application) while (cp = tqsl_getConverterGABBI(conv) != 0) write the string pointed to by "cp" to your file tqsl_converterCommit(conv); tqsl_endConverter(&conv); tqsl_endStationLocationCapture(&loc); The tq8 files created by tqsl are compressed using zlib functions. You can also submit uncompressed files using a .tq7 extension. tqsl-2.7.2/win32-msi/0000755000175000017500000000000014534122221014227 5ustar rmurphyrmurphytqsl-2.7.2/win32-msi/tqsl-install/0000755000175000017500000000000014534122221016656 5ustar rmurphyrmurphytqsl-2.7.2/win32-msi/tqsl-install/update-helpfrag.cmd0000644000175000017500000000024414534122221022413 0ustar rmurphyrmurphy"C:\Program Files (x86)\WiX Toolset v3.11\bin\heat.exe" dir ..\..\apps\help -cg "HelpDir" -dr "APPLICATIONFOLDER" -indent 2 -out helpfrag.wxs -var "var.helpSrc" -agtqsl-2.7.2/win32-msi/tqsl-install/tqsl-install.wixproj0000644000175000017500000000503114534122221022730 0ustar rmurphyrmurphy Debug x86 3.7 1dfa6e6b-1725-4fa3-81d7-64d8a82cb824 2.0 tqsl-2.7 Package $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets bin\$(Configuration)\ obj\$(Configuration)\ Debug -b "..\..\bin\Release" -b "..\..\apps" -b "..\..\src" -b "..\..\src\Release" -b "..\..\apps\Release" bin\$(Configuration)\ obj\$(Configuration)\ -b "..\..\bin\Release" -b "..\..\apps" -b "..\..\src" -b "..\..\src\Release" -b "..\..\..\apps\Release" $(WixExtDir)\WixUIExtension.dll WixUIExtension tqsl-2.7.2/win32-msi/tqsl-install/tqsl-install.sln0000644000175000017500000000151614534122221022026 0ustar rmurphyrmurphy Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "tqsl-install", "tqsl-install.wixproj", "{1DFA6E6B-1725-4FA3-81D7-64D8A82CB824}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1DFA6E6B-1725-4FA3-81D7-64D8A82CB824}.Debug|x86.ActiveCfg = Debug|x86 {1DFA6E6B-1725-4FA3-81D7-64D8A82CB824}.Debug|x86.Build.0 = Debug|x86 {1DFA6E6B-1725-4FA3-81D7-64D8A82CB824}.Release|x86.ActiveCfg = Release|x86 {1DFA6E6B-1725-4FA3-81D7-64D8A82CB824}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal tqsl-2.7.2/win32-msi/tqsl-install/langfrags.wxs0000644000175000017500000002402614534122221021371 0ustar rmurphyrmurphy tqsl-2.7.2/win32-msi/tqsl-install/helpfrag.wxs0000644000175000017500000007507314534122221021225 0ustar rmurphyrmurphy tqsl-2.7.2/win32-msi/tqsl-install/Product.wxs0000644000175000017500000002147614534122221021053 0ustar rmurphyrmurphy NOT Version9X INSTALLDESKTOPSHORTCUT ISINNOINSTALLED NEWERFOUND notepad.exe CLONEXIT AND NOT Installed QSONEXIT AND NOT Installed tqsl-2.7.2/win32-msi/tqsl-install/MyWixUI_InstallDir.wxs0000644000175000017500000001110714534122221023061 0ustar rmurphyrmurphy 1 "1"]]> 1 NOT Installed Installed AND PATCH 1 LicenseAccepted = "1" 1 1 NOT WIXUI_DONTVALIDATEPATH "1"]]> (ISINNOINSTALLED) AND (WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1") (NOT ISINNOINSTALLED) AND (WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1") 1 1 NOT Installed Installed AND NOT PATCH Installed AND PATCH 1 1 1 1 tqsl-2.7.2/win32-msi/tqsl-install/MyInstallDirDlg.wxs0000644000175000017500000000501414534122221022423 0ustar rmurphyrmurphy 1 tqsl-2.7.2/win32-msi/tqsl-install/MyExitDialog.wxs0000644000175000017500000000730714534122221021767 0ustar rmurphyrmurphy tqsl-2.7.2/win32-msi/tqsl-install/AlertUninstall.wxs0000644000175000017500000000210214534122221022355 0ustar rmurphyrmurphy 1 1 1 tqsl-2.7.2/win32-msi/tqsl-install/.gitignore0000644000175000017500000000001214534122221020637 0ustar rmurphyrmurphybin/ obj/ tqsl-2.7.2/toolset-to-vc08.py0000644000175000017500000000120214534122221015733 0ustar rmurphyrmurphyVCXPROJ=".vcxproj" v2012_PLATFORM_TOOLSET="v110" v2008_PLATFORM_TOOLSET="v90" from os import walk, path if __name__=="__main__": count=0 for root, dirs, files in walk("."): for file in files: if file.endswith(VCXPROJ): print "Replacing in", path.join(root, file), "...", with open(path.join(root, file), 'r') as proj: s=proj.read() s=s.replace(v2012_PLATFORM_TOOLSET, v2008_PLATFORM_TOOLSET) with open(path.join(root, file), 'w') as proj: proj.write(s) print "done" count+=1 print "Replaced toolset in", count, "project files"tqsl-2.7.2/src/0000755000175000017500000000000014534122221013266 5ustar rmurphyrmurphytqsl-2.7.2/src/xml.h0000644000175000017500000001416614534122221014247 0ustar rmurphyrmurphy/*************************************************************************** xml.h - description ------------------- begin : Fri Aug 9 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef __xml_h #define __xml_h #include #include #include #include #include using std::pair; using std::string; using std::ostream; using std::map; using std::multimap; using std::vector; namespace tqsllib { class XMLElement; typedef multimap XMLElementList; typedef map XMLElementAttributeList; /** Encapsulates an XML element * * An XMLElement comprises a name, the enclosed text, an optional set of * attributes, and an optional list of contained elements. * * Having a list of contained elements allows construction of the XML * document tree structure. In most cases, the structure will be populated * by a call to parseFile(). */ class XMLElement { public: XMLElement() : _name(""), _text(""), _pretext("") {} /// Constructor initializes element name explicit XMLElement(const string& name) : _text(""), _pretext("") { _name = name; } /// Clear the element of all data void clear(); /// Set the element name void setElementName(const string& name) { _name = name; } /// Get the element name string getElementName() const { return _name; } /// Set an attribute. /** Attributes are treated as unique key/value pairs. */ void setAttribute(const string& key, const string& value); /// Get an attribute by its key. /** Returns a pair where: * * \li \c getAttribute().first := the attribute's value * \li \c getAttribute().second := a bool, true if the attribute key exists */ pair getAttribute(const string& key); /// Add an element to the list of contained subelements XMLElementList::iterator addElement(XMLElement* element); XMLElementAttributeList& getAttributeList() { return _attributes; } XMLElementList& getElementList() { return _elements; } /// Parse an XML file and add its element tree to this element int parseFile(const char *filename); #define XML_PARSE_NO_ERROR 0 #define XML_PARSE_SYSTEM_ERROR 1 #define XML_PARSE_SYNTAX_ERROR 2 /// Parse an XML string and add its element tree to this element int parseString(const char *xmlstring); /// Get the first attribute of the element /** Provides the attribute key and value. Returns \c false if the * element contains no attributes */ bool getFirstAttribute(string& key, string& attr); /// Get the next attribute of the element /** Should be called only after calling getFirstAttribute and getting * a return value of \c true. * Provides the attribute key and value. Returns \c false if the * element contains no more attributes */ bool getNextAttribute(string& key, string& attr); /// Get the first contained element named \c name. /** Returns \c false if the element contains no elements named \c name */ bool getFirstElement(const string& name, XMLElement&); /// Get the first contained element. /** Returns \c false if the element contains no elements */ bool getFirstElement(XMLElement&); /// Get the next contained element. /** Should be called only after calling getFirstElement and getting * a return value of \c true. If the getFirstElement that takes an * element name was called, getNextElement will return \c false when there * are no more elements of that name in the element list. * * Returns \c false if the element contains no more elements */ bool getNextElement(XMLElement&); /// Set the contained text string void setText(const string& s) { _text = s; } /// Get the contained text string. /** Note that this string comprises the text contained in this * element only, not any text contained in elements on the * element list; they each have their own contained text. */ string getText() const { return _text; } void setPretext(const string& s) { _pretext = s; } string getPretext() const { return _pretext; } private: static void xml_start(void *data, const XML_Char *name, const XML_Char **atts); static void xml_end(void *data, const XML_Char *name); static void xml_text(void *data, const XML_Char *text, int len); string _name, _text, _pretext; XMLElementAttributeList _attributes; XMLElementList _elements; vector _parsingStack; XMLElementList::iterator _iter; bool _iterByName; string _iterName; XMLElementAttributeList::iterator _aiter; }; inline void XMLElement::clear() { _name = _text = _pretext = _iterName = ""; _attributes.clear(); _elements.clear(); _parsingStack.clear(); } inline void XMLElement::setAttribute(const string& key, const string& value) { _attributes[key] = value; } inline XMLElementList::iterator XMLElement::addElement(XMLElement* element) { XMLElementList::iterator it = _elements.insert(make_pair(element->getElementName(), element)); return it; } inline bool XMLElement::getFirstElement(XMLElement& element) { _iterByName = false; _iter = _elements.begin(); return getNextElement(element); } inline bool XMLElement::getFirstElement(const string& name, XMLElement& element) { _iterName = name; _iterByName = true; _iter = _elements.find(_iterName); return getNextElement(element); } inline bool XMLElement::getNextElement(XMLElement& element) { if (_iter == _elements.end()) return false; if (_iterByName && _iter->second->getElementName() != _iterName) return false; element = *_iter->second; ++_iter; return true; } inline bool XMLElement::getFirstAttribute(string& key, string& attr) { _aiter = _attributes.begin(); return getNextAttribute(key, attr); } inline bool XMLElement::getNextAttribute(string& key, string& attr) { if (_aiter == _attributes.end()) return false; key = _aiter->first; attr = _aiter->second; ++_aiter; return true; } ostream& operator<< (ostream& stream, XMLElement& el); } // namespace tqsllib #endif // __xml_h tqsl-2.7.2/src/xml.cpp0000644000175000017500000001213114534122221014570 0ustar rmurphyrmurphy/*************************************************************************** xml.cpp - description ------------------- begin : Fri Aug 9 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #define TQSLLIB_DEF #include "xml.h" #include "tqsllib.h" #ifdef _WIN32 #include #endif #include #include #include #include #include #include using std::pair; using std::string; using std::ostream; using std::map; namespace tqsllib { pair XMLElement::getAttribute(const string& key) { string s; XMLElementAttributeList::iterator pos; pos = _attributes.find(key); pair rval; if (pos == _attributes.end()) { rval.second = false; } else { rval.first = pos->second; rval.second = true; } return rval; } void XMLElement::xml_start(void *data, const XML_Char *name, const XML_Char **atts) { XMLElement *el = reinterpret_cast(data); XMLElement *new_el = new XMLElement(name); //cout << "Element: " << name << endl; for (int i = 0; atts[i]; i += 2) { new_el->setAttribute(atts[i], atts[i+1]); } if (el->_parsingStack.empty()) { el->_parsingStack.push_back(el->addElement(new_el)); } else { new_el->setPretext(el->_parsingStack.back()->second->getText()); el->_parsingStack.back()->second->setText(""); el->_parsingStack.push_back(el->_parsingStack.back()->second->addElement(new_el)); } } void XMLElement::xml_end(void *data, const XML_Char *name) { XMLElement *el = reinterpret_cast(data); if (!(el->_parsingStack.empty())) el->_parsingStack.pop_back(); } void XMLElement::xml_text(void *data, const XML_Char *text, int len) { XMLElement *el = reinterpret_cast(data); el->_parsingStack.back()->second->_text.append(text, len); } int XMLElement::parseString(const char *xmlstring) { XML_Parser xp = XML_ParserCreate(0); XML_SetUserData(xp, reinterpret_cast(this)); XML_SetStartElementHandler(xp, &XMLElement::xml_start); XML_SetEndElementHandler(xp, &XMLElement::xml_end); XML_SetCharacterDataHandler(xp, &XMLElement::xml_text); _parsingStack.clear(); // Process the XML if (XML_Parse(xp, xmlstring, strlen(xmlstring), 1) == 0) { XML_ParserFree(xp); strncpy(tQSL_CustomError, xmlstring, 80); tQSL_CustomError[79] = '\0'; return XML_PARSE_SYNTAX_ERROR; } XML_ParserFree(xp); return XML_PARSE_NO_ERROR; } int XMLElement::parseFile(const char *filename) { gzFile in = NULL; #ifdef _WIN32 wchar_t* fn = utf8_to_wchar(filename); int fd = _wopen(fn, _O_RDONLY|_O_BINARY); free_wchar(fn); if (fd != -1) in = gzdopen(fd, "rb"); #else in = gzopen(filename, "rb"); #endif if (!in) return XML_PARSE_SYSTEM_ERROR; // Failed to open file char buf[256]; XML_Parser xp = XML_ParserCreate(0); XML_SetUserData(xp, reinterpret_cast(this)); XML_SetStartElementHandler(xp, &XMLElement::xml_start); XML_SetEndElementHandler(xp, &XMLElement::xml_end); XML_SetCharacterDataHandler(xp, &XMLElement::xml_text); _parsingStack.clear(); int rcount; while ((rcount = gzread(in, buf, sizeof buf)) > 0) { // Process the XML if (XML_Parse(xp, buf, rcount, 0) == 0) { gzclose(in); strncpy(tQSL_CustomError, buf, 80); tQSL_CustomError[79] = '\0'; XML_ParserFree(xp); return XML_PARSE_SYNTAX_ERROR; } } gzclose(in); bool rval = (rcount == 0); if (rval) rval = (XML_Parse(xp, "", 0, 1) != 0); XML_ParserFree(xp); return (rval ? XML_PARSE_NO_ERROR : XML_PARSE_SYNTAX_ERROR); } static struct { char c; const char *ent; } xml_entity_table[] = { { '"', """ }, { '\'', "'" }, { '>', ">" }, { '<', "<" } }; static string xml_entities(const string& s) { string ns = s; string::size_type idx = 0; while ((idx = ns.find('&', idx)) != string::npos) { ns.replace(idx, 1, "&"); idx++; } for (int i = 0; i < static_cast((sizeof xml_entity_table / sizeof xml_entity_table[0])); i++) { while ((idx = ns.find(xml_entity_table[i].c)) != string::npos) ns.replace(idx, 1, xml_entity_table[i].ent); } return ns; } /* Stream out an XMLElement as XML text */ ostream& operator<< (ostream& stream, XMLElement& el) { bool ok; XMLElement subel; if (el.getElementName() != "") { stream << "<" << el.getElementName(); string key, val; bool ok = el.getFirstAttribute(key, val); while (ok) { stream << " " << key << "=\"" << xml_entities(val) << "\""; ok = el.getNextAttribute(key, val); } if (el.getText() == "" && !el.getFirstElement(subel)) { stream << " />"; return stream; } else { stream << ">"; } } ok = el.getFirstElement(subel); while (ok) { string s = subel.getPretext(); if (s != "") stream << xml_entities(s); stream << subel; ok = el.getNextElement(subel); } if (el.getText() != "") stream << xml_entities(el.getText()); if (el.getElementName() != "") stream << ""; return stream; } } // namespace tqsllib tqsl-2.7.2/src/winstrdefs.h0000644000175000017500000000046414534122221015633 0ustar rmurphyrmurphy#ifndef WINSTRDEFS_H #define WINSTRDEFS_H #if defined(_WIN32) || defined(_WIN64) #define snprintf _snprintf #define vsnprintf _vsnprintf #define strcasecmp _stricmp #define strncasecmp _strnicmp #define unlink _unlink #define strdup _strdup #define fileno _fileno #endif #endif//WINSTRDEFS_H tqsl-2.7.2/src/windirent.h0000644000175000017500000006075414534122221015456 0ustar rmurphyrmurphy/* * dirent.h - dirent API for Microsoft Visual Studio * * Copyright (C) 2006-2012 Toni Ronkko * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * ``Software''), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * * Version 1.13, Dec 12 2012, Toni Ronkko * Use traditional 8+3 file name if the name cannot be represented in the * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to * Konstantin Khomoutov for testing. * * Version 1.12.1, Oct 1 2012, Toni Ronkko * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with * capital W) in order to maintain compatibility with MingW. * * Version 1.12, Sep 30 2012, Toni Ronkko * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR, * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir(). * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code. * * Do not include windows.h. This allows dirent.h to be integrated more * easily into programs using winsock. Thanks to Fernando Azaldegui. * * Version 1.11, Mar 15, 2011, Toni Ronkko * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0. * * Version 1.10, Aug 11, 2010, Toni Ronkko * Added d_type and d_namlen fields to dirent structure. The former is * especially useful for determining whether directory entry represents a * file or a directory. For more information, see * http://www.delorie.com/gnu/docs/glibc/libc_270.html * * Improved conformance to the standards. For example, errno is now set * properly on failure and assert() is never used. Thanks to Peter Brockam * for suggestions. * * Fixed a bug in rewinddir(): when using relative directory names, change * of working directory no longer causes rewinddir() to fail. * * Version 1.9, Dec 15, 2009, John Cunningham * Added rewinddir member function * * Version 1.8, Jan 18, 2008, Toni Ronkko * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string * between multi-byte and unicode representations. This makes the * code simpler and also allows the code to be compiled under MingW. Thanks * to Azriel Fasten for the suggestion. * * Mar 4, 2007, Toni Ronkko * Bug fix: due to the strncpy_s() function this file only compiled in * Visual Studio 2005. Using the new string functions only when the * compiler version allows. * * Nov 2, 2006, Toni Ronkko * Major update: removed support for Watcom C, MS-DOS and Turbo C to * simplify the file, updated the code to compile cleanly on Visual * Studio 2005 with both unicode and multi-byte character strings, * removed rewinddir() as it had a bug. * * Aug 20, 2006, Toni Ronkko * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified * comments by removing SGML tags. * * May 14 2002, Toni Ronkko * Embedded the function definitions directly to the header so that no * source modules need to be included in the Visual Studio project. Removed * all the dependencies to other projects so that this header file can be * used independently. * * May 28 1998, Toni Ronkko * First version. *****************************************************************************/ #ifndef DIRENT_H #define DIRENT_H #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) # define _X86_ #endif #include #include #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #include /* Indicates that d_type field is available in dirent structure */ #define _DIRENT_HAVE_D_TYPE /* Indicates that d_namlen field is available in dirent structure */ #define _DIRENT_HAVE_D_NAMLEN /* Entries missing from MSVC 6.0 */ #if !defined(FILE_ATTRIBUTE_DEVICE) # define FILE_ATTRIBUTE_DEVICE 0x40 #endif /* File type and permission flags for stat() */ #if !defined(S_IFMT) # define S_IFMT _S_IFMT /* File type mask */ #endif #if !defined(S_IFDIR) # define S_IFDIR _S_IFDIR /* Directory */ #endif #if !defined(S_IFCHR) # define S_IFCHR _S_IFCHR /* Character device */ #endif #if !defined(S_IFFIFO) # define S_IFFIFO _S_IFFIFO /* Pipe */ #endif #if !defined(S_IFREG) # define S_IFREG _S_IFREG /* Regular file */ #endif #if !defined(S_IREAD) # define S_IREAD _S_IREAD /* Read permission */ #endif #if !defined(S_IWRITE) # define S_IWRITE _S_IWRITE /* Write permission */ #endif #if !defined(S_IEXEC) # define S_IEXEC _S_IEXEC /* Execute permission */ #endif #if !defined(S_IFIFO) # define S_IFIFO _S_IFIFO /* Pipe */ #endif #if !defined(S_IFBLK) # define S_IFBLK 0 /* Block device */ #endif #if !defined(S_IFLNK) # define S_IFLNK 0 /* Link */ #endif #if !defined(S_IFSOCK) # define S_IFSOCK 0 /* Socket */ #endif #if defined(_MSC_VER) # define S_IRUSR S_IREAD /* Read user */ # define S_IWUSR S_IWRITE /* Write user */ # define S_IXUSR 0 /* Execute user */ # define S_IRGRP 0 /* Read group */ # define S_IWGRP 0 /* Write group */ # define S_IXGRP 0 /* Execute group */ # define S_IROTH 0 /* Read others */ # define S_IWOTH 0 /* Write others */ # define S_IXOTH 0 /* Execute others */ #endif /* Maximum length of file name */ #if !defined(PATH_MAX) # define PATH_MAX MAX_PATH #endif #if !defined(FILENAME_MAX) # define FILENAME_MAX MAX_PATH #endif #if !defined(NAME_MAX) # define NAME_MAX FILENAME_MAX #endif /* File type flags for d_type */ #define DT_UNKNOWN 0 #define DT_REG S_IFREG #define DT_DIR S_IFDIR #define DT_FIFO S_IFIFO #define DT_SOCK S_IFSOCK #define DT_CHR S_IFCHR #define DT_BLK S_IFBLK /* Macros for converting between st_mode and d_type */ #define IFTODT(mode) ((mode) & S_IFMT) #define DTTOIF(type) (type) /* * File type macros. Note that block devices, sockets and links cannot be * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are * only defined for compatibility. These macros should always return false * on Windows. */ #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) /* Return the exact length of d_namlen without zero terminator */ #define _D_EXACT_NAMLEN(p) ((p)->d_namlen) /* Return number of bytes needed to store d_namlen */ #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1) #ifdef __cplusplus extern "C" { #endif /* Wide-character version */ struct _wdirent { long d_ino; /* Always zero */ unsigned short d_reclen; /* Structure size */ size_t d_namlen; /* Length of name without \0 */ int d_type; /* File type */ wchar_t d_name[PATH_MAX + 1]; /* File name */ }; typedef struct _wdirent _wdirent; struct _WDIR { struct _wdirent ent; /* Current directory entry */ WIN32_FIND_DATAW data; /* Private file data */ int cached; /* True if data is valid */ HANDLE handle; /* Win32 search handle */ wchar_t *patt; /* Initial directory name */ }; typedef struct _WDIR _WDIR; static _WDIR *_wopendir(const wchar_t *dirname); static struct _wdirent *_wreaddir(_WDIR *dirp); static int _wclosedir(_WDIR *dirp); static void _wrewinddir(_WDIR* dirp); /* For compatibility with Symbian */ #define wdirent _wdirent #define WDIR _WDIR #define wopendir _wopendir #define wreaddir _wreaddir #define wclosedir _wclosedir #define wrewinddir _wrewinddir /* Multi-byte character versions */ struct dirent { long d_ino; /* Always zero */ unsigned short d_reclen; /* Structure size */ size_t d_namlen; /* Length of name without \0 */ int d_type; /* File type */ char d_name[PATH_MAX + 1]; /* File name */ }; typedef struct dirent dirent; struct DIR { struct dirent ent; struct _WDIR *wdirp; }; typedef struct DIR DIR; static DIR *opendir(const char *dirname); static struct dirent *readdir(DIR *dirp); static int closedir(DIR *dirp); static void rewinddir(DIR* dirp); /* Internal utility functions */ static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); static int dirent_mbstowcs_s( size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count); static int dirent_wcstombs_s( size_t *pReturnValue, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count); static void dirent_set_errno(int error); /* * Open directory stream DIRNAME for read and return a pointer to the * internal working area that is used to retrieve individual directory * entries. */ static _WDIR* _wopendir(const wchar_t *dirname) { _WDIR *dirp = NULL; int error; /* Must have directory name */ if (dirname == NULL || dirname[0] == '\0') { dirent_set_errno(ENOENT); return NULL; } /* Allocate new _WDIR structure */ dirp = reinterpret_cast<_WDIR*>(malloc(sizeof(struct _WDIR))); if (dirp != NULL) { DWORD n; /* Reset _WDIR structure */ dirp->handle = INVALID_HANDLE_VALUE; dirp->patt = NULL; dirp->cached = 0; /* Compute the length of full path plus zero terminator */ n = GetFullPathNameW(dirname, 0, NULL, NULL); /* Allocate room for absolute directory name and search pattern */ dirp->patt = reinterpret_cast(malloc(sizeof(wchar_t) * n + 16)); if (dirp->patt) { /* * Convert relative directory name to an absolute one. This * allows rewinddir() to function correctly even when current * working directory is changed between opendir() and rewinddir(). */ n = GetFullPathNameW(dirname, n, dirp->patt, NULL); if (n > 0) { wchar_t *p; /* Append search pattern \* to the directory name */ p = dirp->patt + n; if (dirp->patt < p) { switch (p[-1]) { case '\\': case '/': case ':': /* Directory ends in path separator, e.g. c:\temp\ */ /*NOP*/ break; default: /* Directory name doesn't end in path separator */ *p++ = '\\'; } } *p++ = '*'; *p = '\0'; /* Open directory stream and retrieve the first entry */ if (dirent_first(dirp)) { /* Directory stream opened successfully */ error = 0; } else { /* Cannot retrieve first entry */ error = 1; dirent_set_errno(ENOENT); } } else { /* Cannot retrieve full path name */ dirent_set_errno(ENOENT); error = 1; } } else { /* Cannot allocate memory for search pattern */ error = 1; } } else { /* Cannot allocate _WDIR structure */ error = 1; } /* Clean up in case of error */ if (error && dirp) { _wclosedir(dirp); dirp = NULL; } return dirp; } /* * Read next directory entry. The directory entry is returned in dirent * structure in the d_name field. Individual directory entries returned by * this function include regular files, sub-directories, pseudo-directories * "." and ".." as well as volume labels, hidden files and system files. */ static struct _wdirent* _wreaddir(_WDIR *dirp) { WIN32_FIND_DATAW *datap; struct _wdirent *entp; /* Read next directory entry */ datap = dirent_next(dirp); if (datap) { size_t n; DWORD attr; /* Pointer to directory entry to return */ entp = &dirp->ent; /* * Copy file name as wide-character string. If the file name is too * long to fit in to the destination buffer, then truncate file name * to PATH_MAX characters and zero-terminate the buffer. */ n = 0; while (n < PATH_MAX && datap->cFileName[n] != 0) { entp->d_name[n] = datap->cFileName[n]; n++; } dirp->ent.d_name[n] = 0; /* Length of file name excluding zero terminator */ entp->d_namlen = n; /* File type */ attr = datap->dwFileAttributes; if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { entp->d_type = DT_CHR; } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { entp->d_type = DT_DIR; } else { entp->d_type = DT_REG; } /* Reset dummy fields */ entp->d_ino = 0; entp->d_reclen = sizeof(struct _wdirent); } else { /* Last directory entry read */ entp = NULL; } return entp; } /* * Close directory stream opened by opendir() function. This invalidates the * DIR structure as well as any directory entry read previously by * _wreaddir(). */ static int _wclosedir(_WDIR *dirp) { int ok; if (dirp) { /* Release search handle */ if (dirp->handle != INVALID_HANDLE_VALUE) { FindClose(dirp->handle); dirp->handle = INVALID_HANDLE_VALUE; } /* Release search pattern */ if (dirp->patt) { free(dirp->patt); dirp->patt = NULL; } /* Release directory structure */ free(dirp); ok = /*success*/0; } else { /* Invalid directory stream */ dirent_set_errno(EBADF); ok = /*failure*/-1; } return ok; } /* * Rewind directory stream such that _wreaddir() returns the very first * file name again. */ static void _wrewinddir(_WDIR* dirp) { if (dirp) { /* Release existing search handle */ if (dirp->handle != INVALID_HANDLE_VALUE) { FindClose(dirp->handle); } /* Open new search handle */ dirent_first(dirp); } } /* Get first directory entry (internal) */ static WIN32_FIND_DATAW* dirent_first(_WDIR *dirp) { WIN32_FIND_DATAW *datap; /* Open directory and retrieve the first entry */ dirp->handle = FindFirstFileW(dirp->patt, &dirp->data); if (dirp->handle != INVALID_HANDLE_VALUE) { /* a directory entry is now waiting in memory */ datap = &dirp->data; dirp->cached = 1; } else { /* Failed to re-open directory: no directory entry in memory */ dirp->cached = 0; datap = NULL; } return datap; } /* Get next directory entry (internal) */ static WIN32_FIND_DATAW* dirent_next(_WDIR *dirp) { WIN32_FIND_DATAW *p; /* Get next directory entry */ if (dirp->cached != 0) { /* A valid directory entry already in memory */ p = &dirp->data; dirp->cached = 0; } else if (dirp->handle != INVALID_HANDLE_VALUE) { /* Get the next directory entry from stream */ if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { /* Got a file */ p = &dirp->data; } else { /* The very last entry has been processed or an error occurred */ FindClose(dirp->handle); dirp->handle = INVALID_HANDLE_VALUE; p = NULL; } } else { /* End of directory stream reached */ p = NULL; } return p; } /* * Open directory stream using plain old C-string. */ static DIR* opendir(const char *dirname) { struct DIR *dirp; int error; /* Must have directory name */ if (dirname == NULL || dirname[0] == '\0') { dirent_set_errno(ENOENT); return NULL; } /* Allocate memory for DIR structure */ dirp = reinterpret_cast(malloc(sizeof(struct DIR))); if (dirp) { wchar_t wname[PATH_MAX + 1]; size_t n; /* Convert directory name to wide-character string */ error = dirent_mbstowcs_s( &n, wname, PATH_MAX + 1, dirname, PATH_MAX); if (!error) { /* Open directory stream using wide-character name */ dirp->wdirp = _wopendir(wname); if (dirp->wdirp) { /* Directory stream opened */ error = 0; } else { /* Failed to open directory stream */ error = 1; } } else { /* * Cannot convert file name to wide-character string. This * occurs if the string contains invalid multi-byte sequences or * the output buffer is too small to contain the resulting * string. */ error = 1; } } else { /* Cannot allocate DIR structure */ error = 1; } /* Clean up in case of error */ if (error && dirp) { free(dirp); dirp = NULL; } return dirp; } /* * Read next directory entry. * * When working with text consoles, please note that file names returned by * readdir() are represented in the default ANSI code page while any output to * console is typically formatted on another code page. Thus, non-ASCII * characters in file names will not usually display correctly on console. The * problem can be fixed in two ways: (1) change the character set of console * to 1252 using chcp utility and use Lucida Console font, or (2) use * _cprintf function when writing to console. The _cprinf() will re-encode * ANSI strings to the console code page so many non-ASCII characters will * display correctly. */ static struct dirent* readdir(DIR *dirp) { WIN32_FIND_DATAW *datap; struct dirent *entp; /* Read next directory entry */ datap = dirent_next(dirp->wdirp); if (datap) { size_t n; int error; /* Attempt to convert file name to multi-byte string */ error = dirent_wcstombs_s( &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH); /* * If the file name cannot be represented by a multi-byte string, * then attempt to use old 8+3 file name. This allows traditional * Unix-code to access some file names despite of unicode * characters, although file names may seem unfamiliar to the user. * * Be ware that the code below cannot come up with a short file * name unless the file system provides one. At least * VirtualBox shared folders fail to do this. */ if (error && datap->cAlternateFileName[0] != '\0') { error = dirent_wcstombs_s( &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName, sizeof(datap->cAlternateFileName) / sizeof(datap->cAlternateFileName[0])); } if (!error) { DWORD attr; /* Initialize directory entry for return */ entp = &dirp->ent; /* Length of file name excluding zero terminator */ entp->d_namlen = n - 1; /* File attributes */ attr = datap->dwFileAttributes; if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { entp->d_type = DT_CHR; } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { entp->d_type = DT_DIR; } else { entp->d_type = DT_REG; } /* Reset dummy fields */ entp->d_ino = 0; entp->d_reclen = sizeof(struct dirent); } else { /* * Cannot convert file name to multi-byte string so construct * an erroneous directory entry and return that. Note that * we cannot return NULL as that would stop the processing * of directory entries completely. */ entp = &dirp->ent; entp->d_name[0] = '?'; entp->d_name[1] = '\0'; entp->d_namlen = 1; entp->d_type = DT_UNKNOWN; entp->d_ino = 0; entp->d_reclen = 0; } } else { /* No more directory entries */ entp = NULL; } return entp; } /* * Close directory stream. */ static int closedir(DIR *dirp) { int ok; if (dirp) { /* Close wide-character directory stream */ ok = _wclosedir(dirp->wdirp); dirp->wdirp = NULL; /* Release multi-byte character version */ free(dirp); } else { /* Invalid directory stream */ dirent_set_errno(EBADF); ok = /*failure*/-1; } return ok; } /* * Rewind directory stream to beginning. */ static void rewinddir( DIR* dirp) { /* Rewind wide-character string directory stream */ _wrewinddir(dirp->wdirp); } /* Convert multi-byte string to wide character string */ static int dirent_mbstowcs_s( size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count) { int error; #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Microsoft Visual Studio 2005 or later */ error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count); #else /* Older Visual Studio or non-Microsoft compiler */ size_t n; /* Convert to wide-character string */ n = mbstowcs(wcstr, mbstr, count); if (n < sizeInWords) { /* Zero-terminate output buffer */ if (wcstr) { wcstr[n] = 0; } /* Length of resuting multi-byte string WITH zero terminator */ if (pReturnValue) { *pReturnValue = n + 1; } /* Success */ error = 0; } else { /* Could not convert string */ error = 1; } #endif return error; } /* Convert wide-character string to multi-byte string */ static int dirent_wcstombs_s( size_t *pReturnValue, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count) { int error; #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Microsoft Visual Studio 2005 or later */ error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); #else /* Older Visual Studio or non-Microsoft compiler */ size_t n; /* Convert to multi-byte string */ n = wcstombs(mbstr, wcstr, count); if (n < sizeInBytes) { /* Zero-terminate output buffer */ if (mbstr) { mbstr[n] = '\0'; } /* Length of resulting multi-bytes string WITH zero-terminator */ if (pReturnValue) { *pReturnValue = n + 1; } /* Success */ error = 0; } else { /* Cannot convert string */ error = 1; } #endif return error; } /* Set errno variable */ static void dirent_set_errno(int error) { #if defined(_MSC_VER) /* Microsoft Visual Studio */ _set_errno(error); #else /* Non-Microsoft compiler */ errno = error; #endif } #ifdef __cplusplus } #endif #endif /*DIRENT_H*/ tqsl-2.7.2/src/tqsllib2.def0000644000175000017500000004716514534122221015517 0ustar rmurphyrmurphyLIBRARY tqsllib2.dll EXPORTS _tqsl_getSelectedCertificate@12 tqsl_getSelectedCertificate@12=_tqsl_getSelectedCertificate@12 tqsl_getSelectedCertificate=_tqsl_getSelectedCertificate@12 _tqsl_getNumStationLocationCapturePages@8 tqsl_getNumStationLocationCapturePages@8=_tqsl_getNumStationLocationCapturePages@8 tqsl_getNumStationLocationCapturePages=_tqsl_getNumStationLocationCapturePages@8 _tqsl_adifGetError@4 tqsl_adifGetError@4=_tqsl_adifGetError@4 tqsl_adifGetError=_tqsl_adifGetError@4 _tqsl_adifMakeField@24 tqsl_adifMakeField@24=_tqsl_adifMakeField@24 tqsl_adifMakeField=_tqsl_adifMakeField@24 _tqsl_beginADIF@8 tqsl_beginADIF@8=_tqsl_beginADIF@8 tqsl_beginADIF=_tqsl_beginADIF@8 _tqsl_beginADIFConverter@20 tqsl_beginADIFConverter@20=_tqsl_beginADIFConverter@20 tqsl_beginADIFConverter=_tqsl_beginADIFConverter@20 _tqsl_beginCabrillo@8 tqsl_beginCabrillo@8=_tqsl_beginCabrillo@8 tqsl_beginCabrillo=_tqsl_beginCabrillo@8 _tqsl_beginCabrilloConverter@20 tqsl_beginCabrilloConverter@20=_tqsl_beginCabrilloConverter@20 tqsl_beginCabrilloConverter=_tqsl_beginCabrilloConverter@20 _tqsl_beginSigning@16 tqsl_beginSigning@16=_tqsl_beginSigning@16 tqsl_beginSigning=_tqsl_beginSigning@16 _tqsl_cabrilloGetError@4 tqsl_cabrilloGetError@4=_tqsl_cabrilloGetError@4 tqsl_cabrilloGetError=_tqsl_cabrilloGetError@4 _tqsl_checkSigningStatus@4 tqsl_checkSigningStatus@4=_tqsl_checkSigningStatus@4 tqsl_checkSigningStatus=_tqsl_checkSigningStatus@4 _tqsl_clearADIFModes@0 tqsl_clearADIFModes@0=_tqsl_clearADIFModes@0 tqsl_clearADIFModes=_tqsl_clearADIFModes@0 _tqsl_clearCabrilloMap@0 tqsl_clearCabrilloMap@0=_tqsl_clearCabrilloMap@0 tqsl_clearCabrilloMap=_tqsl_clearCabrilloMap@0 _tqsl_compareDates@8 tqsl_compareDates@8=_tqsl_compareDates@8 tqsl_compareDates=_tqsl_compareDates@8 _tqsl_convertDateToText@12 tqsl_convertDateToText@12=_tqsl_convertDateToText@12 tqsl_convertDateToText=_tqsl_convertDateToText@12 _tqsl_convertTimeToText@12 tqsl_convertTimeToText@12=_tqsl_convertTimeToText@12 tqsl_convertTimeToText=_tqsl_convertTimeToText@12 _tqsl_converterCommit@4 tqsl_converterCommit@4=_tqsl_converterCommit@4 tqsl_converterCommit=_tqsl_converterCommit@4 _tqsl_converterRollBack@4 tqsl_converterRollBack@4=_tqsl_converterRollBack@4 tqsl_converterRollBack=_tqsl_converterRollBack@4 _tqsl_createCertRequest@16 tqsl_createCertRequest@16=_tqsl_createCertRequest@16 tqsl_createCertRequest=_tqsl_createCertRequest@16 _tqsl_decodeBase64@12 tqsl_decodeBase64@12=_tqsl_decodeBase64@12 tqsl_decodeBase64=_tqsl_decodeBase64@12 _tqsl_deleteCertificate@4 tqsl_deleteCertificate@4=_tqsl_deleteCertificate@4 tqsl_deleteCertificate=_tqsl_deleteCertificate@4 _tqsl_deleteStationLocation@4 tqsl_deleteStationLocation@4=_tqsl_deleteStationLocation@4 tqsl_deleteStationLocation=_tqsl_deleteStationLocation@4 _tqsl_encodeBase64@16 tqsl_encodeBase64@16=_tqsl_encodeBase64@16 tqsl_encodeBase64=_tqsl_encodeBase64@16 _tqsl_endADIF@4 tqsl_endADIF@4=_tqsl_endADIF@4 tqsl_endADIF=_tqsl_endADIF@4 _tqsl_endCabrillo@4 tqsl_endCabrillo@4=_tqsl_endCabrillo@4 tqsl_endCabrillo=_tqsl_endCabrillo@4 _tqsl_endConverter@4 tqsl_endConverter@4=_tqsl_endConverter@4 tqsl_endConverter=_tqsl_endConverter@4 _tqsl_endSigning@4 tqsl_endSigning@4=_tqsl_endSigning@4 tqsl_endSigning=_tqsl_endSigning@4 _tqsl_endStationLocationCapture@4 tqsl_endStationLocationCapture@4=_tqsl_endStationLocationCapture@4 tqsl_endStationLocationCapture=_tqsl_endStationLocationCapture@4 _tqsl_exportPKCS12File@12 tqsl_exportPKCS12File@12=_tqsl_exportPKCS12File@12 tqsl_exportPKCS12File=_tqsl_exportPKCS12File@12 _tqsl_freeCertificate@4 tqsl_freeCertificate@4=_tqsl_freeCertificate@4 tqsl_freeCertificate=_tqsl_freeCertificate@4 _tqsl_getADIFField@24 tqsl_getADIFField@24=_tqsl_getADIFField@24 tqsl_getADIFField=_tqsl_getADIFField@24 _tqsl_getADIFLine@8 tqsl_getADIFLine@8=_tqsl_getADIFLine@8 tqsl_getADIFLine=_tqsl_getADIFLine@8 _tqsl_getADIFMode@12 tqsl_getADIFMode@12=_tqsl_getADIFMode@12 tqsl_getADIFMode=_tqsl_getADIFMode@12 _tqsl_getBand@20 tqsl_getBand@20=_tqsl_getBand@20 tqsl_getBand=_tqsl_getBand@20 _tqsl_getCabrilloContest@12 tqsl_getCabrilloContest@12=_tqsl_getCabrilloContest@12 tqsl_getCabrilloContest=_tqsl_getCabrilloContest@12 _tqsl_getCabrilloField@12 tqsl_getCabrilloField@12=_tqsl_getCabrilloField@12 tqsl_getCabrilloField=_tqsl_getCabrilloField@12 _tqsl_getCabrilloFreqType@8 tqsl_getCabrilloFreqType@8=_tqsl_getCabrilloFreqType@8 tqsl_getCabrilloFreqType=_tqsl_getCabrilloFreqType@8 _tqsl_getCabrilloLine@8 tqsl_getCabrilloLine@8=_tqsl_getCabrilloLine@8 tqsl_getCabrilloLine=_tqsl_getCabrilloLine@8 _tqsl_getCabrilloMapEntry@12 tqsl_getCabrilloMapEntry@12=_tqsl_getCabrilloMapEntry@12 tqsl_getCabrilloMapEntry=_tqsl_getCabrilloMapEntry@12 _tqsl_getCabrilloRecordText@4 tqsl_getCabrilloRecordText@4=_tqsl_getCabrilloRecordText@4 tqsl_getCabrilloRecordText=_tqsl_getCabrilloRecordText@4 _tqsl_getCertificateAROName@12 tqsl_getCertificateAROName@12=_tqsl_getCertificateAROName@12 tqsl_getCertificateAROName=_tqsl_getCertificateAROName@12 _tqsl_getCertificateCallSign@12 tqsl_getCertificateCallSign@12=_tqsl_getCertificateCallSign@12 tqsl_getCertificateCallSign=_tqsl_getCertificateCallSign@12 _tqsl_getCertificateDXCCEntity@8 tqsl_getCertificateDXCCEntity@8=_tqsl_getCertificateDXCCEntity@8 tqsl_getCertificateDXCCEntity=_tqsl_getCertificateDXCCEntity@8 _tqsl_getCertificateEmailAddress@12 tqsl_getCertificateEmailAddress@12=_tqsl_getCertificateEmailAddress@12 tqsl_getCertificateEmailAddress=_tqsl_getCertificateEmailAddress@12 _tqsl_getCertificateEncoded@12 tqsl_getCertificateEncoded@12=_tqsl_getCertificateEncoded@12 tqsl_getCertificateEncoded=_tqsl_getCertificateEncoded@12 _tqsl_getCertificateIssuer@12 tqsl_getCertificateIssuer@12=_tqsl_getCertificateIssuer@12 tqsl_getCertificateIssuer=_tqsl_getCertificateIssuer@12 _tqsl_getCertificateIssuerOrganization@12 tqsl_getCertificateIssuerOrganization@12=_tqsl_getCertificateIssuerOrganization@12 tqsl_getCertificateIssuerOrganization=_tqsl_getCertificateIssuerOrganization@12 _tqsl_getCertificateIssuerOrganizationalUnit@12 tqsl_getCertificateIssuerOrganizationalUnit@12=_tqsl_getCertificateIssuerOrganizationalUnit@12 tqsl_getCertificateIssuerOrganizationalUnit=_tqsl_getCertificateIssuerOrganizationalUnit@12 _tqsl_getCertificateKeyOnly@8 tqsl_getCertificateKeyOnly@8=_tqsl_getCertificateKeyOnly@8 tqsl_getCertificateKeyOnly=_tqsl_getCertificateKeyOnly@8 _tqsl_getCertificateNotAfterDate@8 tqsl_getCertificateNotAfterDate@8=_tqsl_getCertificateNotAfterDate@8 tqsl_getCertificateNotAfterDate=_tqsl_getCertificateNotAfterDate@8 _tqsl_getCertificateNotBeforeDate@8 tqsl_getCertificateNotBeforeDate@8=_tqsl_getCertificateNotBeforeDate@8 tqsl_getCertificateNotBeforeDate=_tqsl_getCertificateNotBeforeDate@8 _tqsl_getCertificatePrivateKeyType@4 tqsl_getCertificatePrivateKeyType@4=_tqsl_getCertificatePrivateKeyType@4 tqsl_getCertificatePrivateKeyType=_tqsl_getCertificatePrivateKeyType@4 _tqsl_getCertificateQSONotAfterDate@8 tqsl_getCertificateQSONotAfterDate@8=_tqsl_getCertificateQSONotAfterDate@8 tqsl_getCertificateQSONotAfterDate=_tqsl_getCertificateQSONotAfterDate@8 _tqsl_getCertificateQSONotBeforeDate@8 tqsl_getCertificateQSONotBeforeDate@8=_tqsl_getCertificateQSONotBeforeDate@8 tqsl_getCertificateQSONotBeforeDate=_tqsl_getCertificateQSONotBeforeDate@8 _tqsl_getCertificateRequestAddress1@12 tqsl_getCertificateRequestAddress1@12=_tqsl_getCertificateRequestAddress1@12 tqsl_getCertificateRequestAddress1=_tqsl_getCertificateRequestAddress1@12 _tqsl_getCertificateRequestAddress2@12 tqsl_getCertificateRequestAddress2@12=_tqsl_getCertificateRequestAddress2@12 tqsl_getCertificateRequestAddress2=_tqsl_getCertificateRequestAddress2@12 _tqsl_getCertificateRequestCity@12 tqsl_getCertificateRequestCity@12=_tqsl_getCertificateRequestCity@12 tqsl_getCertificateRequestCity=_tqsl_getCertificateRequestCity@12 _tqsl_getCertificateRequestCountry@12 tqsl_getCertificateRequestCountry@12=_tqsl_getCertificateRequestCountry@12 tqsl_getCertificateRequestCountry=_tqsl_getCertificateRequestCountry@12 _tqsl_getCertificateRequestPostalCode@12 tqsl_getCertificateRequestPostalCode@12=_tqsl_getCertificateRequestPostalCode@12 tqsl_getCertificateRequestPostalCode=_tqsl_getCertificateRequestPostalCode@12 _tqsl_getCertificateRequestState@12 tqsl_getCertificateRequestState@12=_tqsl_getCertificateRequestState@12 tqsl_getCertificateRequestState=_tqsl_getCertificateRequestState@12 _tqsl_getCertificateSerial@8 tqsl_getCertificateSerial@8=_tqsl_getCertificateSerial@8 tqsl_getCertificateSerial=_tqsl_getCertificateSerial@8 _tqsl_getCertificateSerialExt@12 tqsl_getCertificateSerialExt@12=_tqsl_getCertificateSerialExt@12 tqsl_getCertificateSerialExt=_tqsl_getCertificateSerialExt@12 _tqsl_getCertificateSerialLength@4 tqsl_getCertificateSerialLength@4=_tqsl_getCertificateSerialLength@4 tqsl_getCertificateSerialLength=_tqsl_getCertificateSerialLength@4 _tqsl_getConfigVersion@8 tqsl_getConfigVersion@8=_tqsl_getConfigVersion@8 tqsl_getConfigVersion=_tqsl_getConfigVersion@8 _tqsl_getConverterCert@8 tqsl_getConverterCert@8=_tqsl_getConverterCert@8 tqsl_getConverterCert=_tqsl_getConverterCert@8 _tqsl_getConverterGABBI@4 tqsl_getConverterGABBI@4=_tqsl_getConverterGABBI@4 tqsl_getConverterGABBI=_tqsl_getConverterGABBI@4 _tqsl_getConverterLine@8 tqsl_getConverterLine@8=_tqsl_getConverterLine@8 tqsl_getConverterLine=_tqsl_getConverterLine@8 _tqsl_getConverterRecordText@4 tqsl_getConverterRecordText@4=_tqsl_getConverterRecordText@4 tqsl_getConverterRecordText=_tqsl_getConverterRecordText@4 _tqsl_getDXCCEntity@12 tqsl_getDXCCEntity@12=_tqsl_getDXCCEntity@12 tqsl_getDXCCEntity=_tqsl_getDXCCEntity@12 _tqsl_getDXCCEntityName@8 tqsl_getDXCCEntityName@8=_tqsl_getDXCCEntityName@8 tqsl_getDXCCEntityName=_tqsl_getDXCCEntityName@8 _tqsl_getDXCCZoneMap@8 tqsl_getDXCCZoneMap@8=_tqsl_getDXCCZoneMap@8 tqsl_getDXCCZoneMap=_tqsl_getDXCCZoneMap@8 _tqsl_getErrorString@0 tqsl_getErrorString@0=_tqsl_getErrorString@0 tqsl_getErrorString=_tqsl_getErrorString@0 _tqsl_getErrorString_v@4 tqsl_getErrorString_v@4=_tqsl_getErrorString_v@4 tqsl_getErrorString_v=_tqsl_getErrorString_v@4 _tqsl_getGABBItCERT@8 tqsl_getGABBItCERT@8=_tqsl_getGABBItCERT@8 tqsl_getGABBItCERT=_tqsl_getGABBItCERT@8 _tqsl_getGABBItCONTACT@16 tqsl_getGABBItCONTACT@16=_tqsl_getGABBItCONTACT@16 tqsl_getGABBItCONTACT=_tqsl_getGABBItCONTACT@16 _tqsl_getGABBItCONTACTData@24 tqsl_getGABBItCONTACTData@24=_tqsl_getGABBItCONTACTData@24 tqsl_getGABBItCONTACTData=_tqsl_getGABBItCONTACTData@24 _tqsl_getGABBItSTATION@12 tqsl_getGABBItSTATION@12=_tqsl_getGABBItSTATION@12 tqsl_getGABBItSTATION=_tqsl_getGABBItSTATION@12 _tqsl_getLocationCallSign@12 tqsl_getLocationCallSign@12=_tqsl_getLocationCallSign@12 tqsl_getLocationCallSign=_tqsl_getLocationCallSign@12 _tqsl_getLocationDXCCEntity@8 tqsl_getLocationDXCCEntity@8=_tqsl_getLocationDXCCEntity@8 tqsl_getLocationDXCCEntity=_tqsl_getLocationDXCCEntity@8 _tqsl_getLocationFieldChanged@12 tqsl_getLocationFieldChanged@12=_tqsl_getLocationFieldChanged@12 tqsl_getLocationFieldChanged=_tqsl_getLocationFieldChanged@12 _tqsl_getLocationFieldCharData@16 tqsl_getLocationFieldCharData@16=_tqsl_getLocationFieldCharData@16 tqsl_getLocationFieldCharData=_tqsl_getLocationFieldCharData@16 _tqsl_getLocationFieldDataGABBI@16 tqsl_getLocationFieldDataGABBI@16=_tqsl_getLocationFieldDataGABBI@16 tqsl_getLocationFieldDataGABBI=_tqsl_getLocationFieldDataGABBI@16 _tqsl_getLocationFieldDataGABBISize@12 tqsl_getLocationFieldDataGABBISize@12=_tqsl_getLocationFieldDataGABBISize@12 tqsl_getLocationFieldDataGABBISize=_tqsl_getLocationFieldDataGABBISize@12 _tqsl_getLocationFieldDataLabel@16 tqsl_getLocationFieldDataLabel@16=_tqsl_getLocationFieldDataLabel@16 tqsl_getLocationFieldDataLabel=_tqsl_getLocationFieldDataLabel@16 _tqsl_getLocationFieldDataLabelSize@12 tqsl_getLocationFieldDataLabelSize@12=_tqsl_getLocationFieldDataLabelSize@12 tqsl_getLocationFieldDataLabelSize=_tqsl_getLocationFieldDataLabelSize@12 _tqsl_getLocationFieldDataLength@12 tqsl_getLocationFieldDataLength@12=_tqsl_getLocationFieldDataLength@12 tqsl_getLocationFieldDataLength=_tqsl_getLocationFieldDataLength@12 _tqsl_getLocationFieldDataType@12 tqsl_getLocationFieldDataType@12=_tqsl_getLocationFieldDataType@12 tqsl_getLocationFieldDataType=_tqsl_getLocationFieldDataType@12 _tqsl_getLocationFieldFlags@12 tqsl_getLocationFieldFlags@12=_tqsl_getLocationFieldFlags@12 tqsl_getLocationFieldFlags=_tqsl_getLocationFieldFlags@12 _tqsl_getLocationFieldIndex@12 tqsl_getLocationFieldIndex@12=_tqsl_getLocationFieldIndex@12 tqsl_getLocationFieldIndex=_tqsl_getLocationFieldIndex@12 _tqsl_getLocationFieldInputType@12 tqsl_getLocationFieldInputType@12=_tqsl_getLocationFieldInputType@12 tqsl_getLocationFieldInputType=_tqsl_getLocationFieldInputType@12 _tqsl_getLocationFieldIntData@12 tqsl_getLocationFieldIntData@12=_tqsl_getLocationFieldIntData@12 tqsl_getLocationFieldIntData=_tqsl_getLocationFieldIntData@12 _tqsl_getLocationFieldListItem@20 tqsl_getLocationFieldListItem@20=_tqsl_getLocationFieldListItem@20 tqsl_getLocationFieldListItem=_tqsl_getLocationFieldListItem@20 _tqsl_getMaxSignatureSize@8 tqsl_getMaxSignatureSize@8=_tqsl_getMaxSignatureSize@8 tqsl_getMaxSignatureSize=_tqsl_getMaxSignatureSize@8 _tqsl_getMode@12 tqsl_getMode@12=_tqsl_getMode@12 tqsl_getMode=_tqsl_getMode@12 _tqsl_getNumBand@4 tqsl_getNumBand@4=_tqsl_getNumBand@4 tqsl_getNumBand=_tqsl_getNumBand@4 _tqsl_getNumDXCCEntity@4 tqsl_getNumDXCCEntity@4=_tqsl_getNumDXCCEntity@4 tqsl_getNumDXCCEntity=_tqsl_getNumDXCCEntity@4 _tqsl_getNumLocationField@8 tqsl_getNumLocationField@8=_tqsl_getNumLocationField@8 tqsl_getNumLocationField=_tqsl_getNumLocationField@8 _tqsl_getNumLocationFieldListItems@12 tqsl_getNumLocationFieldListItems@12=_tqsl_getNumLocationFieldListItems@12 tqsl_getNumLocationFieldListItems=_tqsl_getNumLocationFieldListItems@12 _tqsl_getNumMode@4 tqsl_getNumMode@4=_tqsl_getNumMode@4 tqsl_getNumMode=_tqsl_getNumMode@4 _tqsl_getNumPropagationMode@4 tqsl_getNumPropagationMode@4=_tqsl_getNumPropagationMode@4 tqsl_getNumPropagationMode=_tqsl_getNumPropagationMode@4 _tqsl_getNumProviders@4 tqsl_getNumProviders@4=_tqsl_getNumProviders@4 tqsl_getNumProviders=_tqsl_getNumProviders@4 _tqsl_getNumSatellite@4 tqsl_getNumSatellite@4=_tqsl_getNumSatellite@4 tqsl_getNumSatellite=_tqsl_getNumSatellite@4 _tqsl_getNumStationLocations@8 tqsl_getNumStationLocations@8=_tqsl_getNumStationLocations@8 tqsl_getNumStationLocations=_tqsl_getNumStationLocations@8 _tqsl_getPropagationMode@12 tqsl_getPropagationMode@12=_tqsl_getPropagationMode@12 tqsl_getPropagationMode=_tqsl_getPropagationMode@12 _tqsl_getProvider@8 tqsl_getProvider@8=_tqsl_getProvider@8 tqsl_getProvider=_tqsl_getProvider@8 _tqsl_getSatellite@20 tqsl_getSatellite@20=_tqsl_getSatellite@20 tqsl_getSatellite=_tqsl_getSatellite@20 _tqsl_getSerialFromTQSLFile@8 tqsl_getSerialFromTQSLFile@8=_tqsl_getSerialFromTQSLFile@8 tqsl_getSerialFromTQSLFile=_tqsl_getSerialFromTQSLFile@8 _tqsl_getStationLocation@8 tqsl_getStationLocation@8=_tqsl_getStationLocation@8 tqsl_getStationLocation=_tqsl_getStationLocation@8 _tqsl_getStationLocationCallSign@16 tqsl_getStationLocationCallSign@16=_tqsl_getStationLocationCallSign@16 tqsl_getStationLocationCallSign=_tqsl_getStationLocationCallSign@16 _tqsl_getStationLocationCaptureName@12 tqsl_getStationLocationCaptureName@12=_tqsl_getStationLocationCaptureName@12 tqsl_getStationLocationCaptureName=_tqsl_getStationLocationCaptureName@12 _tqsl_getStationLocationCapturePage@8 tqsl_getStationLocationCapturePage@8=_tqsl_getStationLocationCapturePage@8 tqsl_getStationLocationCapturePage=_tqsl_getStationLocationCapturePage@8 _tqsl_getStationLocationName@16 tqsl_getStationLocationName@16=_tqsl_getStationLocationName@16 tqsl_getStationLocationName=_tqsl_getStationLocationName@16 _tqsl_getVersion@8 tqsl_getVersion@8=_tqsl_getVersion@8 tqsl_getVersion=_tqsl_getVersion@8 _tqsl_hasNextStationLocationCapture@8 tqsl_hasNextStationLocationCapture@8=_tqsl_hasNextStationLocationCapture@8 tqsl_hasNextStationLocationCapture=_tqsl_hasNextStationLocationCapture@8 _tqsl_hasPrevStationLocationCapture@8 tqsl_hasPrevStationLocationCapture@8=_tqsl_hasPrevStationLocationCapture@8 tqsl_hasPrevStationLocationCapture=_tqsl_hasPrevStationLocationCapture@8 _tqsl_importPKCS12File@24 tqsl_importPKCS12File@24=_tqsl_importPKCS12File@24 tqsl_importPKCS12File=_tqsl_importPKCS12File@24 _tqsl_importTQSLFile@12 tqsl_importTQSLFile@12=_tqsl_importTQSLFile@12 tqsl_importTQSLFile=_tqsl_importTQSLFile@12 _tqsl_init@0 tqsl_init@0=_tqsl_init@0 tqsl_init=_tqsl_init@0 _tqsl_initDate@8 tqsl_initDate@8=_tqsl_initDate@8 tqsl_initDate=_tqsl_initDate@8 _tqsl_initStationLocationCapture@4 tqsl_initStationLocationCapture@4=_tqsl_initStationLocationCapture@4 tqsl_initStationLocationCapture=_tqsl_initStationLocationCapture@4 _tqsl_initTime@8 tqsl_initTime@8=_tqsl_initTime@8 tqsl_initTime=_tqsl_initTime@8 _tqsl_isDateNull@4 tqsl_isDateNull@4=_tqsl_isDateNull@4 tqsl_isDateNull=_tqsl_isDateNull@4 _tqsl_isDateValid@4 tqsl_isDateValid@4=_tqsl_isDateValid@4 tqsl_isDateValid=_tqsl_isDateValid@4 _tqsl_isTimeValid@4 tqsl_isTimeValid@4=_tqsl_isTimeValid@4 tqsl_isTimeValid=_tqsl_isTimeValid@4 _tqsl_nextStationLocationCapture@4 tqsl_nextStationLocationCapture@4=_tqsl_nextStationLocationCapture@4 tqsl_nextStationLocationCapture=_tqsl_nextStationLocationCapture@4 _tqsl_prevStationLocationCapture@4 tqsl_prevStationLocationCapture@4=_tqsl_prevStationLocationCapture@4 tqsl_prevStationLocationCapture=_tqsl_prevStationLocationCapture@4 _tqsl_saveStationLocationCapture@8 tqsl_saveStationLocationCapture@8=_tqsl_saveStationLocationCapture@8 tqsl_saveStationLocationCapture=_tqsl_saveStationLocationCapture@8 _tqsl_selectCertificates@28 tqsl_selectCertificates@28=_tqsl_selectCertificates@28 tqsl_selectCertificates=_tqsl_selectCertificates@28 _tqsl_setADIFConverterDateFilter@12 tqsl_setADIFConverterDateFilter@12=_tqsl_setADIFConverterDateFilter@12 tqsl_setADIFConverterDateFilter=_tqsl_setADIFConverterDateFilter@12 _tqsl_setADIFMode@8 tqsl_setADIFMode@8=_tqsl_setADIFMode@8 tqsl_setADIFMode=_tqsl_setADIFMode@8 _tqsl_setCabrilloMapEntry@12 tqsl_setCabrilloMapEntry@12=_tqsl_setCabrilloMapEntry@12 tqsl_setCabrilloMapEntry=_tqsl_setCabrilloMapEntry@12 _tqsl_setConverterAllowBadCall@8 tqsl_setConverterAllowBadCall@8=_tqsl_setConverterAllowBadCall@8 tqsl_setConverterAllowBadCall=_tqsl_setConverterAllowBadCall@8 _tqsl_setConverterAllowDuplicates@8 tqsl_setConverterAllowDuplicates@8=_tqsl_setConverterAllowDuplicates@8 tqsl_setConverterAllowDuplicates=_tqsl_setConverterAllowDuplicates@8 _tqsl_setDirectory@4 tqsl_setDirectory@4=_tqsl_setDirectory@4 tqsl_setDirectory=_tqsl_setDirectory@4 _tqsl_setLocationFieldCharData@12 tqsl_setLocationFieldCharData@12=_tqsl_setLocationFieldCharData@12 tqsl_setLocationFieldCharData=_tqsl_setLocationFieldCharData@12 _tqsl_setLocationFieldIndex@12 tqsl_setLocationFieldIndex@12=_tqsl_setLocationFieldIndex@12 tqsl_setLocationFieldIndex=_tqsl_setLocationFieldIndex@12 _tqsl_setLocationFieldIntData@12 tqsl_setLocationFieldIntData@12=_tqsl_setLocationFieldIntData@12 tqsl_setLocationFieldIntData=_tqsl_setLocationFieldIntData@12 _tqsl_setStationLocationCaptureName@8 tqsl_setStationLocationCaptureName@8=_tqsl_setStationLocationCaptureName@8 tqsl_setStationLocationCaptureName=_tqsl_setStationLocationCaptureName@8 _tqsl_setStationLocationCapturePage@8 tqsl_setStationLocationCapturePage@8=_tqsl_setStationLocationCapturePage@8 tqsl_setStationLocationCapturePage=_tqsl_setStationLocationCapturePage@8 _tqsl_signDataBlock@20 tqsl_signDataBlock@20=_tqsl_signDataBlock@20 tqsl_signDataBlock=_tqsl_signDataBlock@20 _tqsl_signQSORecord@20 tqsl_signQSORecord@20=_tqsl_signQSORecord@20 tqsl_signQSORecord=_tqsl_signQSORecord@20 _tqsl_updateStationLocationCapture@4 tqsl_updateStationLocationCapture@4=_tqsl_updateStationLocationCapture@4 tqsl_updateStationLocationCapture=_tqsl_updateStationLocationCapture@4 _tqsl_verifyDataBlock@20 tqsl_verifyDataBlock@20=_tqsl_verifyDataBlock@20 tqsl_verifyDataBlock=_tqsl_verifyDataBlock@20 tQSL_ADIF_Error DATA tQSL_Cabrillo_Error DATA tQSL_CustomError DATA tQSL_Errno DATA tQSL_Error DATA tQSL_ErrorFile DATA tqsl-2.7.2/src/tqsllib2-x64.def0000644000175000017500000000727014534122221016127 0ustar rmurphyrmurphyLIBRARY tqsllib2.dll EXPORTS tqsl_getSelectedCertificate tqsl_getNumStationLocationCapturePages tqsl_adifGetError tqsl_adifMakeField tqsl_beginADIF tqsl_beginADIFConverter tqsl_beginCabrillo tqsl_beginCabrilloConverter tqsl_beginSigning tqsl_cabrilloGetError tqsl_checkSigningStatus tqsl_clearADIFModes tqsl_clearCabrilloMap tqsl_compareDates tqsl_convertDateToText tqsl_convertTimeToText tqsl_converterCommit tqsl_converterRollBack tqsl_createCertRequest tqsl_decodeBase64 tqsl_deleteCertificate tqsl_deleteStationLocation tqsl_encodeBase64 tqsl_endADIF tqsl_endCabrillo tqsl_endConverter tqsl_endSigning tqsl_endStationLocationCapture tqsl_exportPKCS12File tqsl_freeCertificate tqsl_getADIFField tqsl_getADIFLine tqsl_getADIFMode tqsl_getBand tqsl_getCabrilloContest tqsl_getCabrilloField tqsl_getCabrilloFreqType tqsl_getCabrilloLine tqsl_getCabrilloMapEntry tqsl_getCabrilloRecordText tqsl_getCertificateAROName tqsl_getCertificateCallSign tqsl_getCertificateDXCCEntity tqsl_getCertificateEmailAddress tqsl_getCertificateEncoded tqsl_getCertificateIssuer tqsl_getCertificateIssuerOrganization tqsl_getCertificateIssuerOrganizationalUnit tqsl_getCertificateKeyOnly tqsl_getCertificateNotAfterDate tqsl_getCertificateNotBeforeDate tqsl_getCertificatePrivateKeyType tqsl_getCertificateQSONotAfterDate tqsl_getCertificateQSONotBeforeDate tqsl_getCertificateRequestAddress1 tqsl_getCertificateRequestAddress2 tqsl_getCertificateRequestCity tqsl_getCertificateRequestCountry tqsl_getCertificateRequestPostalCode tqsl_getCertificateRequestState tqsl_getCertificateSerial tqsl_getCertificateSerialExt tqsl_getCertificateSerialLength tqsl_getConfigVersion tqsl_getConverterCert tqsl_getConverterGABBI tqsl_getConverterLine tqsl_getConverterRecordText tqsl_getDXCCEntity tqsl_getDXCCEntityName tqsl_getDXCCZoneMap tqsl_getErrorString tqsl_getErrorString_v tqsl_getGABBItCERT tqsl_getGABBItCONTACT tqsl_getGABBItCONTACTData tqsl_getGABBItSTATION tqsl_getLocationCallSign tqsl_getLocationDXCCEntity tqsl_getLocationFieldChanged tqsl_getLocationFieldCharData tqsl_getLocationFieldDataGABBI tqsl_getLocationFieldDataGABBISize tqsl_getLocationFieldDataLabel tqsl_getLocationFieldDataLabelSize tqsl_getLocationFieldDataLength tqsl_getLocationFieldDataType tqsl_getLocationFieldFlags tqsl_getLocationFieldIndex tqsl_getLocationFieldInputType tqsl_getLocationFieldIntData tqsl_getLocationFieldListItem tqsl_getMaxSignatureSize tqsl_getMode tqsl_getNumBand tqsl_getNumDXCCEntity tqsl_getNumLocationField tqsl_getNumLocationFieldListItems tqsl_getNumMode tqsl_getNumPropagationMode tqsl_getNumProviders tqsl_getNumSatellite tqsl_getNumStationLocations tqsl_getPropagationMode tqsl_getProvider tqsl_getSatellite tqsl_getSerialFromTQSLFile tqsl_getStationLocation tqsl_getStationLocationCallSign tqsl_getStationLocationCaptureName tqsl_getStationLocationCapturePage tqsl_getStationLocationName tqsl_getVersion tqsl_hasNextStationLocationCapture tqsl_hasPrevStationLocationCapture tqsl_importPKCS12File tqsl_importTQSLFile tqsl_init tqsl_initDate tqsl_initStationLocationCapture tqsl_initTime tqsl_isDateNull tqsl_isDateValid tqsl_isTimeValid tqsl_nextStationLocationCapture tqsl_prevStationLocationCapture tqsl_saveStationLocationCapture tqsl_selectCertificates tqsl_setADIFConverterDateFilter tqsl_setADIFMode tqsl_setCabrilloMapEntry tqsl_setConverterAllowBadCall tqsl_setConverterAllowDuplicates tqsl_setDirectory tqsl_setLocationFieldCharData tqsl_setLocationFieldIndex tqsl_setLocationFieldIntData tqsl_setStationLocationCaptureName tqsl_setStationLocationCapturePage tqsl_signDataBlock tqsl_signQSORecord tqsl_updateStationLocationCapture tqsl_verifyDataBlock tQSL_ADIF_Error DATA tQSL_Cabrillo_Error DATA tQSL_CustomError DATA tQSL_Errno DATA tQSL_Error DATA tQSL_ErrorFile DATA tqsl-2.7.2/src/tqsllib.spec.in0000644000175000017500000000276414534122221016232 0ustar rmurphyrmurphySummary: The TrustedQSL library Name: tqsllib Version: @VERSION@ Release: 2 Copyright: Custom BSD-like Group: Development/Libraries Source: tqsllib-%{version}.tar.gz BuildRoot: /var/tmp/%{name}-buildroot Requires: openssl expat zlib BuildPrereq: openssl-devel expat-devel zlib-devel %package devel Summary: The TrustedQSL Library development tools Group: System/Libraries %description The TrustedQSL library is used for generating digitally signed QSO records (records of Amateur Radio contacts). This package contains the library and configuration files needed to run TrustedQSL applications. %description devel The TrustedQSL library is used for generating digitally signed QSO records (records of Amateur Radio contacts). This package contains the header files needed to build TrustedQSL applications as well as a static tqsllib library and API documentation. %prep %setup -q -n tqsllib-%{version} %build # use --disable-docs because RPM handles docs itself cmake -DCMAKE_INSTALL_PREFIX=/usr . make %install make install %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc LICENSE ChangeLog /usr/lib/libtqsllib.so /usr/lib/libtqsllib.so.1 /usr/lib/libtqsllib.so.1.0.0 /usr/share/tqsl/config.xml /usr/bin/dumptqsldata %files devel %defattr(-,root,root) %doc LICENSE ChangeLog doxygen/html /usr/lib/libtqsllib.a /usr/lib/libtqsllib.la /usr/include/tqsllib.h /usr/include/tqslerrno.h /usr/include/cabrillo.h /usr/include/adif.h /usr/include/tqslconvert.h %post /sbin/ldconfig %postun /sbin/ldconfig tqsl-2.7.2/src/tqsllib.rc.in0000644000175000017500000000210314534122221015667 0ustar rmurphyrmurphy#include 1 VERSIONINFO FILEVERSION @TQSLLIB_VERSION_MAJOR@, @TQSLLIB_VERSION_MINOR@, 0, 0 PRODUCTVERSION @TQSLLIB_VERSION_MAJOR@, @TQSLLIB_VERSION_MINOR@, 0, 0 FILEFLAGSMASK 0 FILEFLAGS VS_FFI_FILEFLAGSMASK FILEOS VOS__WINDOWS32 FILETYPE VFT_DLL BEGIN BLOCK "StringFileInfo" BEGIN // Language type = U.S. English(0x0409) and Character Set = Windows, Multilingual(0x04e4) BLOCK "040904E4" // Matches VarFileInfo Translation hex value. BEGIN VALUE "CompanyName", "American Radio Relay League, Inc.\000" VALUE "FileDescription", "TrustedQSL Library\000" VALUE "FileVersion", "@TQSLLIB_VERSION@\000" VALUE "InternalName", "TQSLLIB\000" VALUE "LegalCopyright", "Copyright 2020 American Radio Relay League.\000" VALUE "OriginalFilename", "tqsllib@DLLVER@.dll\000" VALUE "ProductName", "TQSLLIB\000" VALUE "ProductVersion", "@TQSLLIB_VERSION@\000" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 0x04e4 // U.S. English(0x0409) & Windows Multilingual(0x04e4) 1252 END END tqsl-2.7.2/src/tqsllib.h0000644000175000017500000016635014534122221015124 0ustar rmurphyrmurphy/*************************************************************************** tqsllib.h - description ------------------- begin : Mon May 20 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id: tqsllib.h,v 1.14 2013/03/01 13:26:44 k1mu Exp $ ***************************************************************************/ #ifndef TQSLLIB_H #define TQSLLIB_H #if defined(_WIN32) && !defined(TQSL_NODLL) #ifdef TQSLLIB_DEF #define DLLEXPORT __declspec(dllexport) #define DLLEXPORTDATA __declspec(dllexport) #define CALLCONVENTION __stdcall #else #define DLLEXPORT __declspec(dllimport) #define DLLEXPORTDATA __declspec(dllimport) #define CALLCONVENTION __stdcall #endif #else #define DLLEXPORT ///< Symbol exports - Windows only #define DLLEXPORTDATA ///< Symbol exports - Windows only #define CALLCONVENTION ///< Symbol exports - Windows only #include #endif #include "adif.h" #include "cabrillo.h" /** \file * tQSL library functions. */ #ifndef PATH_MAX // Should be set by #define PATH_MAX 4096 #endif /* Sizes */ #define TQSL_MAX_PATH_LEN PATH_MAX ///< Max length of a FS path #define TQSL_PASSWORD_MAX 80 ///< Max password length #define TQSL_NAME_ELEMENT_MAX 256 ///< Max Org name length #define TQSL_CALLSIGN_MAX 20 ///< Max callsign length #define TQSL_CRQ_NAME_MAX 60 ///< Max length of request name #define TQSL_CRQ_ADDR_MAX 80 ///< Max length of request addr #define TQSL_CRQ_CITY_MAX 80 ///< Max length of request city #define TQSL_CRQ_STATE_MAX 80 ///< Max length of request state #define TQSL_CRQ_POSTAL_MAX 20 ///< Max length of request zip #define TQSL_CRQ_COUNTRY_MAX 80 ///< Max length of req entity #define TQSL_CRQ_EMAIL_MAX 180 ///< Max length of req email #define TQSL_BAND_MAX 6 ///< Max length of a band name #define TQSL_MODE_MAX 16 ///< Max length of a mode name #define TQSL_FREQ_MAX 20 ///< Max length of a frequency #define TQSL_SATNAME_MAX 20 ///< Max length of a sat name #define TQSL_PROPMODE_MAX 20 ///< Max length of a prop mode #define TQSL_STATE_MAX 30 ///< Max length of a state name #define TQSL_GRID_MAX 30 ///< Max length of a grid set #define TQSL_CNTY_MAX 30 ///< Max length of a county name #define TQSL_COUNTRY_MAX 60 ///< Max length of a country name #define TQSL_ZONE_MAX 5 ///< Max length of a zone number #define TQSL_IOTA_MAX 10 ///< Max length of a IOTA identifier #define TQSL_CERT_CB_USER 0 ///< Callback is for user cert #define TQSL_CERT_CB_CA 1 ///< Callback is for CA cert #define TQSL_CERT_CB_ROOT 2 ///< Callback is for root cert #define TQSL_CERT_CB_PKEY 3 ///< Callback is for private key #define TQSL_CERT_CB_CONFIG 4 ///< Callback for config file #define TQSL_CERT_CB_CERT_TYPE(x) ((x) & 0xf) ///< Type of the cert #define TQSL_CERT_CB_MILESTONE 0 ///< New certificate #define TQSL_CERT_CB_RESULT 0x10 ///< Cert import result #define TQSL_CERT_CB_CALL_TYPE(x) ((x) & TQSL_CERT_CB_RESULT) ///< Callback type #define TQSL_CERT_CB_PROMPT 0 ///< Callback prompt #define TQSL_CERT_CB_DUPLICATE 0x100 ///< Dupe cert callback #define TQSL_CERT_CB_ERROR 0x200 ///< Error import callback #define TQSL_CERT_CB_LOADED 0x300 ///< Cert loaded callback #define TQSL_CERT_CB_RESULT_TYPE(x) ((x) & 0x0f00) ///< Result type mask typedef void * tQSL_Cert; ///< Opaque certificate type typedef void * tQSL_Location; ///< Opaque location type typedef char * tQSL_StationDataEnc; ///< Opaque station data type /** Struct that holds y-m-d */ typedef struct { int year; ///< Numeric year int month; ///< Numeric month int day; ///< Numeric day } tQSL_Date; /** Struct that holds h-m-s */ typedef struct { int hour; ///< Time hour field int minute; ///< Time minute field int second; ///< Time seconds field } tQSL_Time; /** Certificate provider data */ typedef struct tqsl_provider_st { char organizationName[TQSL_NAME_ELEMENT_MAX+1]; ///< Provider name char organizationalUnitName[TQSL_NAME_ELEMENT_MAX+1]; ///< Provider unit char emailAddress[TQSL_NAME_ELEMENT_MAX+1]; ///< Provider e-mail char url[TQSL_NAME_ELEMENT_MAX+1]; ///< Provider URL } TQSL_PROVIDER; /** Certificate request data */ typedef struct tqsl_cert_req_st { ///< Cert request data char providerName[TQSL_NAME_ELEMENT_MAX+1]; ///< Provider name char providerUnit[TQSL_NAME_ELEMENT_MAX+1]; ///< Provider unit char callSign[TQSL_CALLSIGN_MAX+1]; ///< Callsign char name[TQSL_CRQ_NAME_MAX+1]; ///< Name char address1[TQSL_CRQ_ADDR_MAX+1]; ///< Address 1 char address2[TQSL_CRQ_ADDR_MAX+1]; ///< Address 2 char city[TQSL_CRQ_CITY_MAX+1]; ///< City char state[TQSL_CRQ_STATE_MAX+1]; ///< State char postalCode[TQSL_CRQ_POSTAL_MAX+1]; ///< Postal Code char country[TQSL_CRQ_COUNTRY_MAX+1]; ///< Country char emailAddress[TQSL_CRQ_EMAIL_MAX+1]; ///< e-mail int dxccEntity; ///< DXCC Entity code tQSL_Date qsoNotBefore; ///< QSOs not before date tQSL_Date qsoNotAfter; ///< QSOs not after date char password[TQSL_PASSWORD_MAX+1]; ///< Password tQSL_Cert signer; ///< Signing cert char renew; ///< Rewewal reference } TQSL_CERT_REQ; /** QSO data */ typedef struct { char callsign[TQSL_CALLSIGN_MAX+1]; ///< QSO callsign char band[TQSL_BAND_MAX+1]; ///< QSO band char mode[TQSL_MODE_MAX+1]; ///< QSO mode char submode[TQSL_MODE_MAX+1]; ///< QSO submode tQSL_Date date; ///< QSO date tQSL_Time time; ///< QSO time char freq[TQSL_FREQ_MAX+1]; ///< QSO frequency char rxfreq[TQSL_FREQ_MAX+1]; ///< QSO receive frequency char rxband[TQSL_BAND_MAX+1]; ///< QSO RX band char propmode[TQSL_PROPMODE_MAX+1]; ///< QSO prop mode char satname[TQSL_SATNAME_MAX+1]; ///< QSO satellite name bool callsign_set; ///< QSO specifies a call worked bool mode_set; ///< QSO specifies a mode bool band_set; ///< QSO specifies a band or frequency bool date_set; ///< QSO specifies a date bool time_set; ///< QSO specifies a time char my_state[TQSL_STATE_MAX+1]; ///< QSO specifies MY_STATE char my_gridsquare[TQSL_GRID_MAX+1]; ///< QSO specifies MY_GRIDSQUARE char my_vucc_grids[TQSL_GRID_MAX+1]; ///< QSO specifies MY_VUCC_GRIDS char my_county[TQSL_CNTY_MAX+1]; ///< QSO specifies MY_CNTY char my_cnty_state[TQSL_STATE_MAX+1]; ///< QSO specifies a state with MY_CNTY char my_country[TQSL_COUNTRY_MAX+1]; ///< QSO specifies MY_COUNTRY char my_cq_zone[TQSL_ZONE_MAX+1]; ///< QSO specifies MY_CQ_ZONE char my_itu_zone[TQSL_ZONE_MAX+1]; ///< QSO specifies MY_ITU_ZONE int my_dxcc; ///< QSO specifies MY_DXCC char my_call[TQSL_CALLSIGN_MAX+1]; ///< Station Callsign #ifdef USE_OWNER_CALLSIGN char my_owner[TQSL_CALLSIGN_MAX+1]; ///< Station Owner Callsign #endif char my_operator[TQSL_CALLSIGN_MAX+1]; ///< Operator's callsign char my_iota[TQSL_IOTA_MAX+1]; ///< QSO specifies MY_IOTA_ } TQSL_QSO_RECORD; /// Base directory for tQSL library working files. DLLEXPORTDATA extern const char *tQSL_BaseDir; /// Directory for resources bundled with tqsl executable DLLEXPORTDATA extern const char *tQSL_RsrcDir; #ifdef __cplusplus extern "C" { #endif /** \defgroup Util Utility API */ /** @{ */ /// Error code from most recent tQSL library call. /** * The values for the error code are defined in tqslerrno.h */ DLLEXPORTDATA extern int tQSL_Error; /// The ADIF error code DLLEXPORTDATA extern TQSL_ADIF_GET_FIELD_ERROR tQSL_ADIF_Error; /// The ADIF error code DLLEXPORTDATA extern TQSL_CABRILLO_ERROR_TYPE tQSL_Cabrillo_Error; /// File name of file giving error. (May be empty.) DLLEXPORTDATA extern char tQSL_ErrorFile[TQSL_MAX_PATH_LEN]; /// Custom error message string DLLEXPORTDATA extern char tQSL_CustomError[256]; /// System errno - stored when tQSL_Error == TQSL_SYSTEM_ERROR DLLEXPORTDATA extern int tQSL_Errno; /// Callsign used in import - used for missing public key error DLLEXPORTDATA extern char tQSL_ImportCall[256]; /// Serial number of recent certificate import DLLEXPORTDATA extern long tQSL_ImportSerial; /// Diagnostic log file DLLEXPORTDATA extern FILE* tQSL_DiagFile; /** Initialize the tQSL library * * This function should be called prior to calling any other library functions. */ DLLEXPORT int CALLCONVENTION tqsl_init(); /** Set the directory where the TQSL files are kept. * May be called either before of after tqsl_init(), but should be called * before calling any other functions in the library. * * Note that this is purely optional. The library will figure out an * appropriate directory if tqsl_setDirectory isn't called. Unless there is * some particular need to set the directory explicitly, programs should * refrain from doing so. */ DLLEXPORT int CALLCONVENTION tqsl_setDirectory(const char *dir); /** Gets the error string for the current tQSL library error and resets the error status. * See tqsl_getErrorString_v(). */ DLLEXPORT const char* CALLCONVENTION tqsl_getErrorString(); /** Gets the error string corresponding to the given error number. * The error string is available only until the next call to * tqsl_getErrorString_v or tqsl_getErrorString. */ DLLEXPORT const char* CALLCONVENTION tqsl_getErrorString_v(int err); /** Encode a block of data into Base64 text. * * \li \c data = block of data to encode * \li \c datalen = length of \c data in bytes * \li \c output = pointer to output buffer * \li \c outputlen = size of output buffer in bytes */ DLLEXPORT int CALLCONVENTION tqsl_encodeBase64(const unsigned char *data, int datalen, char *output, int outputlen); /** Decode Base64 text into binary data. * * \li \c input = NUL-terminated text string of Base64-encoded data * \li \c data = pointer to output buffer * \li \c datalen = pointer to int containing the size of the output buffer in bytes * * Places the number of resulting data bytes into \c *datalen. */ DLLEXPORT int CALLCONVENTION tqsl_decodeBase64(const char *input, unsigned char *data, int *datalen); /** Initialize a tQSL_Date object from a date string. * * The date string must be YYYY-MM-DD or YYYYMMDD format. * * Returns 0 on success, nonzero on failure */ DLLEXPORT int CALLCONVENTION tqsl_initDate(tQSL_Date *date, const char *str); /** Initialize a tQSL_Time object from a time string. * * The time string must be HH[:]MM[[:]SS] format. * * Returns 0 on success, nonzero on failure */ DLLEXPORT int CALLCONVENTION tqsl_initTime(tQSL_Time *time, const char *str); /** Compare two tQSL_Date objects. * * Returns: * - -1 if \c a < \c b * * - 0 if \c a == \c b * * - 1 if \c a > \c b */ DLLEXPORT int CALLCONVENTION tqsl_compareDates(const tQSL_Date *a, const tQSL_Date *b); /** Calculate the number of days between two tQSL_Date objects. * * Returns a positive result if the first date is earlier, otherwise * negative. */ DLLEXPORT int CALLCONVENTION tqsl_subtractDates(const tQSL_Date *a, const tQSL_Date *b, int *diff); /** Converts a tQSL_Date object to a YYYY-MM-DD string. * * Returns a pointer to \c buf or NULL on error */ DLLEXPORT char* CALLCONVENTION tqsl_convertDateToText(const tQSL_Date *date, char *buf, int bufsiz); /** Test whether a tQSL_Date contains a valid date value * * Returns 1 if the date is valid */ DLLEXPORT int CALLCONVENTION tqsl_isDateValid(const tQSL_Date *d); /** Test whether a tQSL_Date is empty (contains all zeroes) * * Returns 1 if the date is null */ DLLEXPORT int CALLCONVENTION tqsl_isDateNull(const tQSL_Date *d); /** Test whether a tQSL_Time contains a valid time value * * Returns 1 if the time is valid */ DLLEXPORT int CALLCONVENTION tqsl_isTimeValid(const tQSL_Time *t); /** Converts a tQSL_Time object to a HH:MM:SSZ string. * * Returns a pointer to \c buf or NULL on error */ DLLEXPORT char* CALLCONVENTION tqsl_convertTimeToText(const tQSL_Time *time, char *buf, int bufsiz); /** Returns the library version. \c major and/or \c minor may be NULL. */ DLLEXPORT int CALLCONVENTION tqsl_getVersion(int *major, int *minor); /** Returns the configuration-file version. \c major and/or \c minor may be NULL. */ DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion(int *major, int *minor); /** @} */ /** \defgroup CertStuff Certificate Handling API * * Certificates are managed by manipulating \c tQSL_Cert objects. A \c tQSL_Cert * contains: * * \li The identity of the organization that issued the certificate (the "issuer"). * \li The name and call sign of the amateur radio operator (ARO). * \li The DXCC entity number for which this certificate is valid. * \li The range of QSO dates for which this certificate can be used. * \li The resources needed to digitally sign and verify QSO records. * * The certificate management process consists of: * * \li Applying for a certificate. Certificate requests are produced via the * tqsl_createCertRequest() function, which produces a certificate-request * file to send to the issuer. * \li Importing the certificate file received from the issuer into the local * "certificate store," a directory managed by the tQSL library, via * tqsl_importTQSLFile(). * \li Selecting an appropriate certificate to use to sign a QSO record via * tqsl_selectCertificates(). */ /** @{ */ #define TQSL_SELECT_CERT_WITHKEYS 1 ///< Private keys only (no cert) #define TQSL_SELECT_CERT_EXPIRED 2 ///< Include expired certs #define TQSL_SELECT_CERT_SUPERCEDED 4 ///< Include superseded certs /** Get a list of certificates * * Selects a set of certificates from the user's certificate store * based on optional selection criteria. The function produces a * list of tQSL_Cert objects. * * \li \c certlist - Pointer to a variable that is set by the * function to point to the list of tQSL_Cert objects. * \li \c ncerts - Pointer to an int that is set to the number * of objects in the \c certlist list. * \li \c callsign - Optional call sign to match. * \li \c date - Optional QSO date string in ISO format. Only certs * that have a QSO date range that encompasses this date will be * returned. * \li \c issuer - Optional issuer (DN) string to match. * \li \c flag - OR of \c TQSL_SELECT_CERT_EXPIRED (include expired * certs), \c TQSL_SELECT_CERT_SUPERCEDED and \c TQSL_SELECT_CERT_WITHKEYS * (keys that don't have associated certs will be returned). * * Returns 0 on success, nonzero on failure. * * Each of the tQSL_Cert objects in the list should be freed * by calling tqsl_freeCertificate(). tqsl_freeCertificateList() is a better * function to use for that as it also frees the allocated array that * holds the certificate pointers. * */ DLLEXPORT int CALLCONVENTION tqsl_selectCertificates(tQSL_Cert **certlist, int *ncerts, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flag); /** Get a list of authority certificates * * Selects a set of certificates from the root or authorities certificate stores * The function produces a list of tQSL_Cert objects. * * Each of the tQSL_Cert objects in the list should be freed * by calling tqsl_freeCertificate(). tqsl_freeCertificateList() is a better * function to use for that as it also frees the allocated array that * holds the certificate pointers. * */ DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates(tQSL_Cert **certlist, int *ncerts, const char *type); /** Get a particulat certificate from the list returnded by * tqsl_selectCertificates. This function exists principally * to make it easier for VB programs to access the list of * certificates. * * It is the caller's responsibility to ensure that 0 <= idx < ncerts * (where ncerts is the value returned by tqsl_selectCertificates) */ DLLEXPORT int CALLCONVENTION tqsl_getSelectedCertificate(tQSL_Cert *cert, const tQSL_Cert **certlist, int idx); /** Find out if the "certificate" is expired */ DLLEXPORT int CALLCONVENTION tqsl_isCertificateExpired(tQSL_Cert cert, int *status); /** Find out if the "certificate" is superceded */ DLLEXPORT int CALLCONVENTION tqsl_isCertificateSuperceded(tQSL_Cert cert, int *status); /** Find out if the "certificate" is just a key pair. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateKeyOnly(tQSL_Cert cert, int *keyonly); /** Get the encoded certificate for inclusion in a GABBI file. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateEncoded(tQSL_Cert cert, char *buf, int bufsiz); /** Get the encoded private key for inclusion in a backup file. */ DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded(tQSL_Cert cert, char *buf, int bufsiz); /** Import a base64 encoded certificate and private key from a backup file. */ DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded(const char *callsign, const char *type, const char *keybuf, const char *certbuf); /** Get the issuer's serial number of the certificate. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerial(tQSL_Cert cert, long *serial); /** Get the issuer's serial number of the certificate as a hexadecimal string. * Needed for certs with long serial numbers (typically root certs). */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt(tQSL_Cert cert, char *serial, int serialsiz); /** Get the length of the issuer's serial number of the certificate as it will be * returned by tqsl_getCertificateSerialExt. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialLength(tQSL_Cert cert); /** Get the issuer (DN) string from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuer(tQSL_Cert cert, char *buf, int bufsiz); /** Get the issuer's organization name from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganization(tQSL_Cert cert, char *buf, int bufsiz); /** Get the issuer's organizational unit name from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganizationalUnit(tQSL_Cert cert, char *buf, int bufsiz); /** Get the ARO call sign string from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateCallSign(tQSL_Cert cert, char *buf, int bufsiz); /** Get the ARO name string from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateAROName(tQSL_Cert cert, char *buf, int bufsiz); /** Get the email address from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateEmailAddress(tQSL_Cert cert, char *buf, int bufsiz); /** Get the QSO not-before date from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c date - Pointer to a tQSL_Date struct to hold the returned date. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotBeforeDate(tQSL_Cert cert, tQSL_Date *date); /** Get the QSO not-after date from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c date - Pointer to a tQSL_Date struct to hold the returned date. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotAfterDate(tQSL_Cert cert, tQSL_Date *date); /** Get the certificate's not-before date from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c date - Pointer to a tQSL_Date struct to hold the returned date. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotBeforeDate(tQSL_Cert cert, tQSL_Date *date); /** Get the certificate's not-after date from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c date - Pointer to a tQSL_Date struct to hold the returned date. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotAfterDate(tQSL_Cert cert, tQSL_Date *date); /** Get the DXCC entity number from a tQSL_Cert. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c dxcc - Pointer to an int to hold the returned date. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateDXCCEntity(tQSL_Cert cert, int *dxcc); /** Get the first address line from the certificate request used in applying * for a tQSL_Cert certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress1(tQSL_Cert cert, char *str, int bufsiz); /** Get the second address line from the certificate request used in applying * for a tQSL_Cert certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress2(tQSL_Cert cert, char *str, int bufsiz); /** Get the city from the certificate request used in applying * for a tQSL_Cert certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCity(tQSL_Cert cert, char *str, int bufsiz); /** Get the state from the certificate request used in applying * for a tQSL_Cert certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestState(tQSL_Cert cert, char *str, int bufsiz); /** Get the postal (ZIP) code from the certificate request used in applying * for a tQSL_Cert certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestPostalCode(tQSL_Cert cert, char *str, int bufsiz); /** Get the country from the certificate request used in applying * for a tQSL_Cert certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * \li \c buf - Buffer to hold the returned string. * \li \c bufsiz - Size of \c buf. * * Returns 0 on success, nonzero on failure. */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCountry(tQSL_Cert cert, char *str, int bufsiz); #define TQSL_PK_TYPE_ERR 0 ///< Error retrieving private key #define TQSL_PK_TYPE_NONE 1 ///< No private key #define TQSL_PK_TYPE_UNENC 2 ///< Private key is not encrypted #define TQSL_PK_TYPE_ENC 3 ///< Private key is encrypted /** Determine the nature of the private key associated with a * certificate. * * \li \c cert - a tQSL_Cert object, normally one returned from * tqsl_selectCertificates() * * Returns one of the following values: * * \li \c TQSL_PK_TYPE_ERR - An error occurred. Use tqsl_getErrorString() to examine. * \li \c TQSL_PK_TYPE_NONE - No matching private key was found. * \li \c TQSL_PK_TYPE_UNENC - The matching private key is unencrypted. * \li \c TQSL_PK_TYPE_ENC - The matching private key is encrypted * (password protected). */ DLLEXPORT int CALLCONVENTION tqsl_getCertificatePrivateKeyType(tQSL_Cert cert); /** Free the memory used by the tQSL_Cert. Once this function is called, * \c cert should not be used again in any way. */ DLLEXPORT void CALLCONVENTION tqsl_freeCertificate(tQSL_Cert cert); /** Free the memory used by a certificate list. The allocated list * of tQSL_Certs are freed and the pointer array is freed. * Once this function is called, the \c list or the \c cert * should not be used again in any way. */ DLLEXPORT void CALLCONVENTION tqsl_freeCertificateList(tQSL_Cert* list, int ncerts); #define TQSL_CERT_STATUS_UNK 0 ///< Status is unknown #define TQSL_CERT_STATUS_SUP 1 ///< Certificate is superceded #define TQSL_CERT_STATUS_EXP 2 ///< Certificate is expired #define TQSL_CERT_STATUS_OK 3 ///< Certificate is valid #define TQSL_CERT_STATUS_INV 4 ///< Invalid serial number /** Determine the status of a callsign certificate * \li \c serial - the serial number of the certificate * tqsl_selectCertificates() * \li \c status - an integer to receive the certificate status * * Returns one of the following values: * * \li \c TQSL_CERT_STATUS_UNK - An error occurred and the status is unknown * \li \c TQSL_CERT_STATUS_SUP - The certificate has been superceded * \li \c TQSL_CERT_STATUS_EXP - The certificate has expired * \li \c TQSL_CERT_STATUS_OK - The certificate is valid * \li \c TQSL_CERT_STATUS_INV - The serial number supplied is invalid * */ DLLEXPORT int CALLCONVENTION tqsl_getCertificateStatus(long serial); /** Store the status of a callsign certificate * \li \c serial - serial number of the certificate * \li \c status - the status value to store. */ DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus(long serial, const char *status); /* int tqsl_checkCertificate(tQSL_Cert); */ /** Import a Gabbi cert file received from a CA * * The callback, \c cb, will be called whenever a certificate is ready * to be imported: * * cb(type, message); * * \c type has several fields that can be accessed via macros: * * \c TQSL_CERT_CB_CALL_TYPE(type) := \c TQSL_CERT_CB_MILESTONE | \c TQSL_CERT_CB_RESULT * * \c TQSL_CERT_CB_CERT_TYPE(type) := \c TQSL_CERT_CB_ROOT | \c TQSL_CERT_CB_CA | \c TQSL_CERT_CB_USER * * \c TQSL_CERT_CB_RESULT_TYPE(type) := \c TQSL_CERT_CB_PROMPT | \c TQSL_CERT_CB_WARNING | \c TQSL_CERT_CB_ERROR * * \c TQSL_CERT_CB_RESULT_TYPE() is meaningful only if \c TQSL_CERT_CB_CALL_TYPE() == \c TQSL_CERT_CB_RESULT */ DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile(const char *file, int(*cb)(int type, const char *message, void *userdata), void *user); /** Get the serial for the first user cert from a .tq6 file * used to support asking the user to save their cert after import * \li \c file is the path to the file * \li \c serial is where the serial number is returned * * Returns 0 on success, nonzero on failure. * */ DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile(const char *file, long *serial); /** Get the number of certificate providers known to tqsllib. */ DLLEXPORT int CALLCONVENTION tqsl_getNumProviders(int *n); /** Get the information for a certificate provider. * * \li \c idx is the index, 0 <= idx < tqsl_getNumProviders() */ DLLEXPORT int CALLCONVENTION tqsl_getProvider(int idx, TQSL_PROVIDER *provider); /** Create a certificate-request Gabbi file. * * The \c req parameter must be properly populated with the required fields. * * If \c req->password is NULL and \c cb is not NULL, the callback will be * called to acquire the password. Otherwise \c req->password will be used as * the password. If the password is NULL or an empty string the generated * private key will be stored unencrypted. * * If req->signer is not zero and the signing certificate requires a password, * the password may be in req->signer_password, else signer_pwcb is called. */ DLLEXPORT int CALLCONVENTION tqsl_createCertRequest(const char *filename, TQSL_CERT_REQ *req, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user); /** Save a key pair and certificates to a file in PKCS12 format. * * The tQSL_Cert must be initialized for signing (see tqsl_beginSigning()) * if the user certificate is being exported. * * The supplied \c p12password is used to encrypt the PKCS12 data. */ DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File(tQSL_Cert cert, const char *filename, const char *p12password); /** Save a key pair and certificates to a Base64 string in PKCS12 format. * * The tQSL_Cert must be initialized for signing (see tqsl_beginSigning()) * if the user certificate is being exported. * * The supplied \c p12password is used to encrypt the PKCS12 data. */ DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64(tQSL_Cert cert, char *base64, int b64len, const char *p12password); /** Load certificates and a private key from a PKCS12 file. */ DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File(const char *filename, const char *p12password, const char *password, int (*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type , const char *message, void *userdata), void *user); /** Load certificates and a private key from a Base64 encoded PKCS12 string. */ DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64(const char *base64, const char *p12password, const char *password, int (*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type , const char *message, void *userdata), void *user); /** Get the list of restorable station locations. */ DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates(char ***calls, int *ncall, const char *filter); /** Free the list of restorable Callsign Certificates. */ DLLEXPORT void CALLCONVENTION tqsl_freeDeletedCertificateList(char **list, int nloc); /** Restore a deleted callsign certificate by callsign. */ DLLEXPORT int CALLCONVENTION tqsl_restoreCallsignCertificate(const char *callsign); /** Delete a certificate and private key */ DLLEXPORT int CALLCONVENTION tqsl_deleteCertificate(tQSL_Cert cert); /** @} */ /** \defgroup Sign Signing API * * The Signing API uses a tQSL_Cert (see \ref CertStuff) to digitally * sign a block of data. */ /** @{ */ /** Initialize the tQSL_Cert object for use in signing. * * This produces an unencrypted copy of the private key in memory. * * if \c password is not NULL, it must point to the password to use to decrypt * the private key. If \c password is NULL and \c pwcb is not NULL, \c pwcb * is called to get the password. If the private key is encrypted and both * \c password and \c pwcb are NULL, or if the supplied password fails to * decrypt the key, a TQSL_PASSWORD_ERROR error is returned. * * \c pwcb parameters: \c pwbuf is a pointer to a buffer of \c pwsize chars. * The buffer should be NUL-terminated. */ DLLEXPORT int CALLCONVENTION tqsl_beginSigning(tQSL_Cert cert, char *password, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user); /** Test whether the tQSL_Cert object is initialized for signing. * * Returns 0 if initialized. Sets tQSL_Error to TQSL_SIGNINIT_ERROR if not. */ DLLEXPORT int CALLCONVENTION tqsl_checkSigningStatus(tQSL_Cert cert); /** Get the maximum size of a signature block that will be produced * when the tQSL_Cert is used to sign data. (Note that the size of the * signature block is unaffected by the size of the data block being signed.) */ DLLEXPORT int CALLCONVENTION tqsl_getMaxSignatureSize(tQSL_Cert cert, int *sigsize); /** Sign a data block. * * tqsl_beginSigning() must have been called for * the tQSL_Cert object before calling this function. */ DLLEXPORT int CALLCONVENTION tqsl_signDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int *siglen); /** Verify a signed data block. * * tqsl_beginSigning() need \em not have been called. */ DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int siglen); /** Sign a single QSO record * * tqsl_beginSigning() must have been called for * the tQSL_Cert object before calling this function. * * \c loc must be a valid tQSL_Location object. See \ref Data. */ DLLEXPORT int CALLCONVENTION tqsl_signQSORecord(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *rec, unsigned char *sig, int *siglen); /** Terminate signing operations for this tQSL_Cert object. * * This zero-fills the unencrypted private key in memory. */ DLLEXPORT int CALLCONVENTION tqsl_endSigning(tQSL_Cert cert); /** @} */ /** \defgroup Data Data API * * The Data API is used to form data into TrustedQSL records. A TrustedQSL record * consists of a station record and a QSO record. Together, the two records * fully describe one station's end of the QSO -- just as a paper QSL card does. * * The station record contains the callsign and geographic location of the * station submitting the QSO record. The library manages the station records. * The tqsl_xxxStationLocationCapture functions are used to generate and save * a station record. The intent is to provide an interface that makes a step-by-step * system (such as a GUI "wizard") easily implemented. * * The tqsl_getStationLocation() function is used to retrieve station records. * * With the necessary station location available, a signed GABBI output file can * be generated using the tqsl_getGABBIxxxxx functions: * * \li tqsl_getGABBItCERT() - Returns a GABBI tCERT record for the given tQSL_Cert * \li tqsl_getGABBItSTATION() - Returns a GABBI tSTATION record for the given * tQSL_Location * \li tqsl_getGABBItCONTACT() - Returns a GABBI tCONTACT record for the given * TQSL_QSO_RECORD, using the given tQSL_Cert and tQSL_Location. * \li tqsl_getGABBItCONTACTData() - Returns a GABBI tCONTACT record and the * SIGNDATA for the given TQSL_QSO_RECORD, using the given tQSL_Cert and * tQSL_Location. * * The GABBI format requires that the tCERT record contain an integer identifier * that is unique within the GABBI file. Similarly, each tSTATION record must * contain a unique identifier. Additionally, the tSTATION record must reference * the identifier of a preceding tCERT record. Finally, each tCONTACT record must * reference a preceding tSTATION record. (A GABBI processor uses these identifiers * and references to tie the station and contact records together and to verify * their signature via the certificate.) It is the responsibility of the caller * to supply these identifiers and to ensure that the supplied references match * the tQSL_Cert and tQSL_Location used to create the referenced GABBI records. * * Station Location Generation * * The station-location generation process involves determining the values * for a number of station-location parameters. Normally this * will be done by prompting the user for the values. The responses given * by the user may determine which later fields are required. For example, * if the user indicates that the DXCC entity is UNITED STATES, a later * field would ask for the US state. This field would not be required if the * DXCC entity were not in the US. * * To accommodate the dynamic nature of the field requirements, the fields * are ordered such that dependent fields are queried after the field(s) * on which they depend. To make this process acceptable in a GUI * system, the fields are grouped into pages, where multiple fields may * be displayed on the same page. The grouping is such that which fields * are within the page is not dependent on any of the values of the * fields within the page. That is, a page of fields contains the same * fields no matter what value any of the fields contains. (However, * the \em values of fields within the page can depend on the values * of fields that precede them in the page.) * * Here is a brief overview of the sequence of events involved in * generating a station location interactively, one field at a time: * * 1) Call tqsl_initStationLocationCapture() (new location) or tqsl_getStationLocation() * (existing location). * * 2) For \c field from 0 to tqsl_getNumLocationField(): * \li Display the field label [tqsl_getLocationFieldDataLabel()] * \li Get the field content from the user. This can be a selection * from a list, an entered integer or an entered character string, * depending on the value returned by tqsl_getLocationFieldInputType(). * * 3) If tqsl_hasNextStationLocationCapture() returns 1, call * tqsl_nextStationLocationCapture() and go back to step 2. * * In the case of a GUI system, you'll probably want to display the * fields in pages. The sequence of events is a bit different: * * 1) Call tqsl_initStationLocationCapture() (new location) or tqsl_getStationLocation() * (existing location). * * 2) For \c field from 0 to tqsl_getNumLocationField(), * \li Display the field label [tqsl_getLocationFieldDataLabel()] * \li Display the field-input control This can be a list-selection * or an entered character string or integer, depending on the value * returned by tqsl_getLocationFieldInputType(). * * 3) Each time the user changes a field, call tqsl_updateStationLocationCapture(). * This may change the allowable selection for fields that follow the field * the user changed, so the control for each of those fields should be updated * as in step 2. * * 4) Once the user has completed entries for the page, if * tqsl_hasNextStationLocationCapture() returns 1, call * tqsl_nextStationLocationCapture() and go back to step 2. * * N.B. The first two fields in the station-location capture process are * always call sign and DXCC entity, in that order. As a practical matter, these * two fields must match the corresponding fields in the available certificates. * The library will therefore constrain the values of these fields to match * what's available in the certificate store. See \ref CertStuff. */ /** @{ */ /* Location field input types */ #define TQSL_LOCATION_FIELD_TEXT 1 ///< Text type input field #define TQSL_LOCATION_FIELD_DDLIST 2 ///< Dropdown list input field #define TQSL_LOCATION_FIELD_LIST 3 ///< List type input field #define TQSL_LOCATION_FIELD_BADZONE 4 ///< Used to return zone selection errors /* Location field data types */ #define TQSL_LOCATION_FIELD_CHAR 1 ///< Character field #define TQSL_LOCATION_FIELD_INT 2 ///< Integer field /** Begin the process of generating a station record */ DLLEXPORT int CALLCONVENTION tqsl_initStationLocationCapture(tQSL_Location *locp); /** Release the station-location resources. This should be called for * any tQSL_Location that was initialized via tqsl_initStationLocationCapture() * or tqsl_getStationLocation() */ DLLEXPORT int CALLCONVENTION tqsl_endStationLocationCapture(tQSL_Location *locp); /** Update the pages based on the currently selected settings. */ DLLEXPORT int CALLCONVENTION tqsl_updateStationLocationCapture(tQSL_Location loc); /** Return the number of station location capture pages. */ DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocationCapturePages(tQSL_Location loc, int *npages); /** Get the current page number */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCapturePage(tQSL_Location loc, int *page); /** Set the current page number. * Typically, the page number will be 1 (the starting page) or a value * obtained from tqsl_getStationLocationCapturePage(). */ DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCapturePage(tQSL_Location loc, int page); /** Set the certificate flags used in a location page. * This is used to enable expired certs (or disable). */ DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCertFlags(tQSL_Location loc, int flags); /** Advance the page to the next one in the page sequence */ DLLEXPORT int CALLCONVENTION tqsl_nextStationLocationCapture(tQSL_Location loc); /** Return the next page to in the page sequence */ DLLEXPORT int CALLCONVENTION tqsl_getNextStationLocationCapturePage(tQSL_Location loc, int *page); /** Return the page to the previous one in the page sequence. */ DLLEXPORT int CALLCONVENTION tqsl_prevStationLocationCapture(tQSL_Location loc); /** Return the previous page in the page sequence. */ DLLEXPORT int CALLCONVENTION tqsl_getPrevStationLocationCapturePage(tQSL_Location loc, int *page); /** Return the current page in the page sequence. */ DLLEXPORT int CALLCONVENTION tqsl_getCurrentStationLocationCapturePage(tQSL_Location loc, int *page); /** Returns 1 (in rval) if there is a next page */ DLLEXPORT int CALLCONVENTION tqsl_hasNextStationLocationCapture(tQSL_Location loc, int *rval); /** Returns 1 (in rval) if there is a previous page */ DLLEXPORT int CALLCONVENTION tqsl_hasPrevStationLocationCapture(tQSL_Location loc, int *rval); /** Save the station location data. Note that the name must have been * set via tqsl_setStationLocationCaptureName if this is a new * station location. If the \c overwrite parameter is zero and a * station location of that name is already in existence, an error * occurs with tQSL_Error set to TQSL_NAME_EXISTS. */ DLLEXPORT int CALLCONVENTION tqsl_saveStationLocationCapture(tQSL_Location loc, int overwrite); /** Get the name of the station location */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCaptureName(tQSL_Location loc, char *namebuf, int bufsiz); /** Set the name of the station location */ DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCaptureName(tQSL_Location loc, const char *name); /** Get the number of saved station locations */ DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocations(tQSL_Location loc, int *nloc); /** Get the name of the specified (by \c idx) saved station location */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName(tQSL_Location loc, int idx, char *buf, int bufsiz); /** Get the call sign from the station location */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCallSign(tQSL_Location loc, int idx, char *buf, int bufsiz); /** Get a named field from the station location */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField(tQSL_Location locp, const char *name, char *namebuf, int bufsize); /** Retrieve a saved station location. * Once finished with the station location, tqsl_endStationLocationCapture() * should be called to release resources. */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocation(tQSL_Location *loc, const char *name); /** Get any errors returned from parsing the selected station location. * This should be called after tqsl_getStationLocation to determine if * any of the existing fields failed validation. Currently only zone * data is validated here, but future validations for things like * properly formatted grid squares is likely. */ DLLEXPORT int CALLCONVENTION tqsl_getStationLocationErrors(tQSL_Location loc, char *buf, int bufsiz); /** Return the contents of the station data file as a byte stream. * The caller is required to tqsl_freeStationDataEnc() this pointer when done with it. */ DLLEXPORT int CALLCONVENTION tqsl_getStationDataEnc(tQSL_StationDataEnc *sdata); /** Free the pointer returned by tqsl_getStationDataEnc(tQSL_StationDataEnc*) */ DLLEXPORT int CALLCONVENTION tqsl_freeStationDataEnc(tQSL_StationDataEnc sdata); /** Merge saved location data with existing */ DLLEXPORT int CALLCONVENTION tqsl_mergeStationLocations(const char *locdata); /** Remove the stored station location by name. */ DLLEXPORT int CALLCONVENTION tqsl_deleteStationLocation(const char *name); /** Restore the deleted station location by name. */ DLLEXPORT int CALLCONVENTION tqsl_restoreStationLocation(const char *name); /** Get the list of restorable station locations. */ DLLEXPORT int CALLCONVENTION tqsl_getDeletedStationLocations(char ***locp, int *nloc); /** Free the list of restorable station locations. */ DLLEXPORT void CALLCONVENTION tqsl_freeDeletedLocationList(char **list, int nloc); /** Get the number of fields on the current station location page */ DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField(tQSL_Location loc, int *numf); /** Get the number of characters in the label for the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize(tQSL_Location loc, int field_num, int *rval); /** Get the label for the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel(tQSL_Location loc, int field_num, char *buf, int bufsiz); /** Get the size of the GABBI name of the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize(tQSL_Location loc, int field_num, int *rval); /** Get the GABBI name of the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI(tQSL_Location loc, int field_num, char *buf, int bufsiz); /** Get the input type of the input field. * * \c type will be one of TQSL_LOCATION_FIELD_TEXT, TQSL_LOCATION_FIELD_DDLIST * or TQSL_LOCATION_FIELD_LIST */ /** Get the number of fields on the current station location page */ DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField(tQSL_Location loc, int *numf); /** Get the number of characters in the label for the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize(tQSL_Location loc, int field_num, int *rval); /** Get the label for the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel(tQSL_Location loc, int field_num, char *buf, int bufsiz); /** Get the size of the GABBI name of the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize(tQSL_Location loc, int field_num, int *rval); /** Get the GABBI name of the specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI(tQSL_Location loc, int field_num, char *buf, int bufsiz); /** Get the input type of the input field. * * \c type will be one of TQSL_LOCATION_FIELD_TEXT, TQSL_LOCATION_FIELD_DDLIST * or TQSL_LOCATION_FIELD_LIST */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldInputType(tQSL_Location loc, int field_num, int *type); /** Get the data type of the input field. * * \c type will be either TQSL_LOCATION_FIELD_CHAR or TQSL_LOCATION_FIELD_INT */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataType(tQSL_Location loc, int field_num, int *type); /** Get the flags for the input field. * * \c flags will be either * TQSL_LOCATION_FIELD_UPPER Field is to be uppercased on input * TQSL_LOCATION_FIELD_MUSTSEL Value must be selected * TQSL_LOCATION_FIELD_SELNXT Value must be selected to allow Next/Finish * */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldFlags(tQSL_Location loc, int field_num, int *flags); /** Get the length of the input field data. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLength(tQSL_Location loc, int field_num, int *rval); /** Get the character data from the specified field. * * If the field input type (see tqsl_getLocationFieldInputType()) is * TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST, this will * return the text of the selected item. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData(tQSL_Location loc, int field_num, char *buf, int bufsiz); /** Get the integer data from the specified field. * * This is only meaningful if the field data type (see tqsl_getLocationFieldDataType()) * is TQSL_LOCATION_FIELD_INT. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIntData(tQSL_Location loc, int field_num, int *dat); /** If the field input type (see tqsl_getLocationFieldInputType()) is * TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST, gets the * index of the selected list item. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIndex(tQSL_Location loc, int field_num, int *dat); /** Get the number of items in the specified field's pick list. */ DLLEXPORT int CALLCONVENTION tqsl_getNumLocationFieldListItems(tQSL_Location loc, int field_num, int *rval); /** Get the text of a specified item of a specified field */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem(tQSL_Location loc, int field_num, int item_idx, char *buf, int bufsiz); /** Set the text data of a specified field. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData(tQSL_Location loc, int field_num, const char *buf); /** Set the integer data of a specified field. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIntData(tQSL_Location loc, int field_num, int dat); /** If the field input type (see tqsl_getLocationFieldInputType()) is * TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST, sets the * index of the selected list item. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIndex(tQSL_Location loc, int field_num, int dat); /** Get the \e changed status of a field. The changed flag is set to 1 if the * field's pick list was changed during the last call to tqsl_updateStationLocationCapture * or zero if the list was not changed. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldChanged(tQSL_Location loc, int field_num, int *changed); /** Get the call sign from the station location. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationCallSign(tQSL_Location loc, char *buf, int bufsiz); /** Set the call sign for the station location. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationCallSign(tQSL_Location loc, const char *buf, int dxcc); /** Get a field from the station location. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationField(tQSL_Location locp, const char *field, char *buf, int bufsiz); /** Get a field label from the station location. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel(tQSL_Location locp, const char *field, char *buf, int bufsiz); /** Set a field in a station location. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationField(tQSL_Location locp, const char *field, const char *buf); /** Get the DXCC entity from the station location. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationDXCCEntity(tQSL_Location loc, int *dxcc); /** Get the QSO details in canonical form. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationQSODetails(tQSL_Location locp, char *buf, int buflen); /** Get the station location details in canonical form. */ DLLEXPORT int CALLCONVENTION tqsl_getLocationStationDetails(tQSL_Location locp, char *buf, int buflen); /** Save the json results for a given callsign location Detail. */ DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo(const char *callsign, const char *json); /** Retrieve the json results for a given callsign location Detail. */ DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo(const char *callsign, char **buf); /** Get the number of DXCC entities in the primary DXCC list. */ DLLEXPORT int CALLCONVENTION tqsl_getNumDXCCEntity(int *number); /** Get a DXCC entity from the list of DXCC entities by its index. */ DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity(int index, int *number, const char **name); /** Get the name of a DXCC Entity by its DXCC number. */ DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName(int number, const char **name); /** Get the zonemap of a DXCC Entity by its DXCC number. */ DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap(int number, const char **zonemap); /** Get the start date of a DXCC Entity by its DXCC number. */ DLLEXPORT int CALLCONVENTION tqsl_getDXCCStartDate(int number, tQSL_Date *d); /** Get the end date of a DXCC Entity by its DXCC number. */ DLLEXPORT int CALLCONVENTION tqsl_getDXCCEndDate(int number, tQSL_Date *d); /** Get the deleted status of a DXCC Entity by its DXCC number. */ DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted(int number, int *deleted); /** Get the number of Band entries in the Band list */ DLLEXPORT int CALLCONVENTION tqsl_getNumBand(int *number); /** Get a band by its index. * * \c name - The GAABI name of the band. * \c spectrum - HF | VHF | UHF * \c low - The low end of the band in kHz (HF) or MHz (VHF/UHF) * \c high - The low high of the band in kHz (HF) or MHz (VHF/UHF) * * Note: \c spectrum, \c low and/or \c high may be NULL. */ DLLEXPORT int CALLCONVENTION tqsl_getBand(int index, const char **name, const char **spectrum, int *low, int *high); /** Get the number of Mode entries in the Mode list */ DLLEXPORT int CALLCONVENTION tqsl_getNumMode(int *number); /** Get a mode by its index. * * \c mode - The GAABI mode name * \c group - CW | PHONE | IMAGE | DATA * * Note: \c group may be NULL. */ DLLEXPORT int CALLCONVENTION tqsl_getMode(int index, const char **mode, const char **group); /** Get the number of ADIF Mode entries in the Mode list */ DLLEXPORT int CALLCONVENTION tqsl_getNumADIFMode(int *number); /** Get an ADIF mode by its index. * * \c mode - The ADIF mode name * */ DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry(int index, const char **mode); /** Get the number of Propagation Mode entries in the Propagation Mode list */ DLLEXPORT int CALLCONVENTION tqsl_getNumPropagationMode(int *number); /** Get a propagation mode by its index. * * \c name - The GAABI propagation mode name * \c descrip - Text description of the propagation mode * * Note: \c descrip may be NULL. */ DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode(int index, const char **name, const char **descrip); /** Get the number of Satellite entries in the Satellite list */ DLLEXPORT int CALLCONVENTION tqsl_getNumSatellite(int *number); /** Get a satellite by its index. * * \c name - The GAABI satellite name * \c descrip - Text description of the satellite * \c start - The date the satellite entered service * \c end - The last date the satellite was in service * * Note: \c descrip, start and/or end may be NULL. */ DLLEXPORT int CALLCONVENTION tqsl_getSatellite(int index, const char **name, const char **descrip, tQSL_Date *start, tQSL_Date *end); /** Clear the map of Cabrillo contests. */ DLLEXPORT int CALLCONVENTION tqsl_clearCabrilloMap(); /** Set the mapping of a Cabrillo contest name (as found in the * CONTEST line of a Cabrillo file) to the QSO line call-worked field number * and the contest type. * * \c field can have a value of TQSL_MIN_CABRILLO_MAP_FIELD (cabrillo.h) * or greater. Field number starts at 1. * * \c contest_type must be TQSL_CABRILLO_HF or TQSL_CABRILLO_VHF, * defined in cabrillo.h */ DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry(const char *contest, int field, int contest_type); /** Get the mapping of a Cabrillo contest name (as found in the * CONTEST line of a Cabrillo file) to a call-worked field number * and the contest type. * * \c fieldnum will be set to 0 if the contest name isn't in the Cabrillo * map. Otherwise it is set to the QSO line field number of the call-worked * field, with field counting starting at 1. * * \c contest_type may be NULL. If not, it is set to the Cabrillo contest * type (TQSL_CABRILLO_HF or TQSL_CABRILLO_VHF), defined in cabrillo.h. */ DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry(const char *contest, int *fieldnum, int *contest_type); /** Clear the map of ADIF modes */ DLLEXPORT int CALLCONVENTION tqsl_clearADIFModes(); /** Set the mapping of an ADIF mode to a TQSL mode. */ DLLEXPORT int CALLCONVENTION tqsl_setADIFMode(const char *adif_item, const char *mode); /** Map an ADIF mode to its TQSL equivalent. */ DLLEXPORT int CALLCONVENTION tqsl_getADIFMode(const char *adif_item, char *mode, int nmode); /** Map a GABBI mode to its mode/submode pair. */ DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode(const char *adif_item, char *mode, char *submode, int nmode); /** Get a GABBI record that contains the certificate. * * \c uid is the value for the CERT_UID field * * Returns the NULL pointer on error. * * N.B. On systems that distinguish text-mode files from binary-mode files, * notably Windows, the GABBI records should be written in binary mode. */ DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCERT(tQSL_Cert cert, int uid); /** Get a GABBI record that contains the Station Location data. * * \li \c uid is the value for the STATION_UID field. * \li \c certuid is the value of the associated CERT_UID field. * * Returns the NULL pointer on error. * * N.B. On systems that distinguish text-mode files from binary-mode files, * notably Windows, the GABBI records should be written in binary mode. */ DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItSTATION(tQSL_Location loc, int uid, int certuid); /** Get a GABBI record that contains the QSO data. * * \li \c stationuid is the value of the associated STATION_UID field. * * N.B.: If \c cert is not initialized for signing (see tqsl_beginSigning()) * the function will return with a TQSL_SIGNINIT_ERROR error. * * Returns the NULL pointer on error. * * N.B. On systems that distinguish text-mode files from binary-mode files, * notably Windows, the GABBI records should be written in binary mode. */ DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCONTACT(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid); /** Get a GABBI record that contains the QSO data along with the associated * signdata (QSO data signed to validate the QSO). * * \li \c stationuid is the value of the associated STATION_UID field. * * N.B.: If \c cert is not initialized for signing (see tqsl_beginSigning()) * the function will return with a TQSL_SIGNINIT_ERROR error. * * Returns the NULL pointer on error. * * N.B. On systems that distinguish text-mode files from binary-mode files, * notably Windows, the GABBI records should be written in binary mode. */ DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCONTACTData(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid, char *signdata, int sdlen); /** @} */ /** Output to a diagnostic trace file (if one is opened. * * \li \c name is the name of the function being executed */ DLLEXPORT void CALLCONVENTION tqslTrace(const char *name, const char *format, ...); /** Close the diagnostic trace file (if it is open) */ DLLEXPORT void CALLCONVENTION tqsl_closeDiagFile(void); /** Close the diagnostic trace file (if it is open) */ DLLEXPORT int CALLCONVENTION tqsl_diagFileOpen(void); /** Returns true if the log file is open * */ DLLEXPORT int CALLCONVENTION tqsl_openDiagFile(const char* file); /** Removes the upload database if it exists * */ DLLEXPORT void CALLCONVENTION tqsl_removeUploadDatabase(void); #ifdef _WIN32 DLLEXPORT wchar_t* CALLCONVENTION utf8_to_wchar(const char* str); DLLEXPORT char* CALLCONVENTION wchar_to_utf8(const wchar_t* str, bool forceUTF8); DLLEXPORT void CALLCONVENTION free_wchar(wchar_t* ptr); #endif #ifdef __cplusplus } #endif /* Useful defines */ #define TQSL_MAX_PW_LENGTH 32 ///< Password buffer length #endif /* TQSLLIB_H */ tqsl-2.7.2/src/tqsllib.css0000644000175000017500000000211614534122221015452 0ustar rmurphyrmurphyBODY { font-family: Helvetica,Arial,sans-serif; font-size: small } H1 { text-align: center; font-size: x-large } H2 { font-size: large } CODE { font-size: medium } A.qindex {} A.qindexRef {} A.el { text-decoration: none; font-weight: bold; } A.elRef { font-weight: bold } A.code { text-decoration: none; font-weight: normal; color: #4444ee } A.codeRef { font-weight: normal; color: #4444ee } A:link { color: #0000ff } A:visited { color: #0066cc } DL.el { margin-left: -1cm } DIV.fragment { width: 100%; border: none; background-color: #eeeeee } DIV.ah { background-color: black; margin-bottom: 3; margin-top: 3 } TD.md { background-color: #f2f2ff } DIV.groupHeader { margin-left: 16; margin-top: 12; margin-bottom: 6; font-weight: bold } DIV.groupText { margin-left: 16; font-style: italic; font-size: smaller } FONT.keyword { color: #008000 } FONT.keywordtype { color: #604020 } FONT.keywordflow { color: #e08000 } FONT.comment { color: #800000 } FONT.preprocessor { color: #806020 } FONT.stringliteral { color: #002080 } FONT.charliteral { color: #008080 } TD { font-size: small } tqsl-2.7.2/src/tqsllib.cpp0000644000175000017500000007547614534122221015467 0ustar rmurphyrmurphy/*************************************************************************** tqsllib.c - description ------------------- begin : Mon May 20 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #define TQSLLIB_DEF #include "tqsllib.h" #include #include #include #include #include #ifdef _WIN32 #include #include #include #include #include #else #include #endif #ifdef __APPLE__ #include #endif #include using std::string; #include #include #include #if OPENSSL_VERSION_MAJOR >= 3 #include #endif #include "tqslerrno.h" #include "adif.h" #include "winstrdefs.h" #ifdef _WIN32 #define MKDIR(x, y) _wmkdir((x)) #else #define MKDIR(x, y) mkdir((x), (y)) #endif DLLEXPORTDATA int tQSL_Error = 0; DLLEXPORTDATA int tQSL_Errno = 0; DLLEXPORTDATA TQSL_ADIF_GET_FIELD_ERROR tQSL_ADIF_Error; DLLEXPORTDATA const char *tQSL_BaseDir = NULL; DLLEXPORTDATA const char *tQSL_RsrcDir = NULL; DLLEXPORTDATA char tQSL_ErrorFile[TQSL_MAX_PATH_LEN]; DLLEXPORTDATA char tQSL_CustomError[256]; DLLEXPORTDATA char tQSL_ImportCall[256]; DLLEXPORTDATA long tQSL_ImportSerial = 0; DLLEXPORTDATA FILE* tQSL_DiagFile = NULL; #define TQSL_OID_BASE "1.3.6.1.4.1.12348.1." #define TQSL_OID_CALLSIGN TQSL_OID_BASE "1" #define TQSL_OID_QSO_NOT_BEFORE TQSL_OID_BASE "2" #define TQSL_OID_QSO_NOT_AFTER TQSL_OID_BASE "3" #define TQSL_OID_DXCC_ENTITY TQSL_OID_BASE "4" #define TQSL_OID_SUPERCEDED_CERT TQSL_OID_BASE "5" #define TQSL_OID_CRQ_ISSUER_ORGANIZATION TQSL_OID_BASE "6" #define TQSL_OID_CRQ_ISSUER_ORGANIZATIONAL_UNIT TQSL_OID_BASE "7" #define TQSL_OID_CRQ_EMAIL TQSL_OID_BASE "8" #define TQSL_OID_CRQ_ADDRESS1 TQSL_OID_BASE "9" #define TQSL_OID_CRQ_ADDRESS2 TQSL_OID_BASE "10" #define TQSL_OID_CRQ_CITY TQSL_OID_BASE "11" #define TQSL_OID_CRQ_STATE TQSL_OID_BASE "12" #define TQSL_OID_CRQ_POSTAL TQSL_OID_BASE "13" #define TQSL_OID_CRQ_COUNTRY TQSL_OID_BASE "14" static const char *custom_objects[][3] = { { TQSL_OID_CALLSIGN, "AROcallsign", "AROcallsign" }, { TQSL_OID_QSO_NOT_BEFORE, "QSONotBeforeDate", "QSONotBeforeDate" }, { TQSL_OID_QSO_NOT_AFTER, "QSONotAfterDate", "QSONotAfterDate" }, { TQSL_OID_DXCC_ENTITY, "dxccEntity", "dxccEntity" }, { TQSL_OID_SUPERCEDED_CERT, "supercededCertificate", "supercededCertificate" }, { TQSL_OID_CRQ_ISSUER_ORGANIZATION, "tqslCRQIssuerOrganization", "tqslCRQIssuerOrganization" }, { TQSL_OID_CRQ_ISSUER_ORGANIZATIONAL_UNIT, "tqslCRQIssuerOrganizationalUnit", "tqslCRQIssuerOrganizationalUnit" }, { TQSL_OID_CRQ_EMAIL, "tqslCRQEmail", "tqslCRQEmail" }, { TQSL_OID_CRQ_ADDRESS1, "tqslCRQAddress1", "tqslCRQAddress1" }, { TQSL_OID_CRQ_ADDRESS2, "tqslCRQAddress2", "tqslCRQAddress2" }, { TQSL_OID_CRQ_CITY, "tqslCRQCity", "tqslCRQCity" }, { TQSL_OID_CRQ_STATE, "tqslCRQState", "tqslCRQState" }, { TQSL_OID_CRQ_POSTAL, "tqslCRQPostal", "tqslCRQPostal" }, { TQSL_OID_CRQ_COUNTRY, "tqslCRQCountry", "tqslCRQCountry" }, }; static const char *error_strings[] = { "Memory allocation failure", /* TQSL_ALLOC_ERROR */ "Unable to initialize random number generator", /* TQSL_RANDOM_ERROR */ "Invalid argument", /* TQSL_ARGUMENT_ERROR */ "Operator aborted operation", /* TQSL_OPERATOR_ABORT */ "No Certificate Request matches the selected Callsign Certificate",/* TQSL_NOKEY_ERROR */ "Buffer too small", /* TQSL_BUFFER_ERROR */ "Invalid date format", /* TQSL_INVALID_DATE */ "Certificate not initialized for signing", /* TQSL_SIGNINIT_ERROR */ "Passphrase not correct", /* TQSL_PASSWORD_ERROR */ "Expected name", /* TQSL_EXPECTED_NAME */ "Name exists", /* TQSL_NAME_EXISTS */ "Data for this DXCC entity could not be found", /* TQSL_NAME_NOT_FOUND */ "Invalid time format", /* TQSL_INVALID_TIME */ "QSO date is not within the date range specified on your Callsign Certificate", /* TQSL_CERT_DATE_MISMATCH */ "Certificate provider not found", /* TQSL_PROVIDER_NOT_FOUND */ "No callsign certificate for key", /* TQSL_CERT_KEY_ONLY */ "Configuration file cannot be opened", /* TQSL_CONFIG_ERROR */ "The private key for this Callsign Certificate is not present on this computer; you can obtain it by loading a .tbk or .p12 file", /* TQSL_CERT_NOT_FOUND */ "PKCS#12 file not TQSL compatible", /* TQSL_PKCS12_ERROR */ "Callsign Certificate not TQSL compatible", /* TQSL_CERT_TYPE_ERROR */ "Date out of range", /* TQSL_DATE_OUT_OF_RANGE */ "Already Uploaded QSO suppressed", /* TQSL_DUPLICATE_QSO */ "Database error", /* TQSL_DB_ERROR */ "The selected station location could not be found", /* TQSL_LOCATION_NOT_FOUND */ "The selected callsign could not be found", /* TQSL_CALL_NOT_FOUND */ "The TQSL configuration file cannot be parsed", /* TQSL_CONFIG_SYNTAX_ERROR */ "This file can not be processed due to a system error", /* TQSL_FILE_SYSTEM_ERROR */ "The format of this file is incorrect.", /* TQSL_FILE_SYNTAX_ERROR */ "This Callsign Certificate could not be installed", /* TQSL_CERT_ERROR */ "Callsign Certificate does not match QSO details", /* TQSL_CERT_MISMATCH */ "Station Location does not match QSO details", /* TQSL_LOCATION_MISMATCH */ /* note - dupe table in wxutil.cpp */ }; #if !defined(__APPLE__) && !defined(_WIN32) && !defined(__clang__) #pragma GCC diagnostic ignored "-Wformat-truncation" #endif const char* tqsl_openssl_error(void); #if defined(_WIN32) static int pmkdir(const wchar_t *path, int perm) { wchar_t dpath[TQSL_MAX_PATH_LEN]; wchar_t npath[TQSL_MAX_PATH_LEN]; wchar_t *cp; char *p = wchar_to_utf8(path, true); tqslTrace("pmkdir", "path=%s", p); free(p); int nleft = sizeof(npath) / sizeof(npath[0]) - 1; wcsncpy(dpath, path, sizeof(dpath) / sizeof(dpath[0])); cp = wcstok(dpath, L"/\\"); npath[0] = 0; while (cp) { if (wcslen(cp) > 0 && cp[wcslen(cp)-1] != ':') { wcsncat(npath, L"\\", nleft); nleft--; wcsncat(npath, cp, nleft); nleft -= wcslen(cp); if (MKDIR(npath, perm) != 0 && errno != EEXIST) { tqslTrace("pmkdir", "Error creating %s: %s", npath, strerror(errno)); return 1; } } else { wcsncat(npath, cp, nleft); nleft -= wcslen(cp); } cp = wcstok(NULL, L"/\\"); } return 0; } #else // defined(_WIN32) static int pmkdir(const char *path, int perm) { char dpath[TQSL_MAX_PATH_LEN]; char npath[TQSL_MAX_PATH_LEN]; char *cp; tqslTrace("pmkdir", "path=%s", path); int nleft = sizeof npath - 1; strncpy(dpath, path, sizeof dpath); cp = strtok(dpath, "/\\"); npath[0] = 0; while (cp) { if (strlen(cp) > 0 && cp[strlen(cp)-1] != ':') { strncat(npath, "/", nleft); nleft--; strncat(npath, cp, nleft); nleft -= strlen(cp); if (MKDIR(npath, perm) != 0 && errno != EEXIST) { tqslTrace("pmkdir", "Error creating %s: %s", npath, strerror(errno)); return 1; } } else { strncat(npath, cp, nleft); nleft -= strlen(cp); } cp = strtok(NULL, "/\\"); } return 0; } #endif // defined(_WIN32) static void tqsl_get_rsrc_dir() { tqslTrace("tqsl_get_rsrc_dir", NULL); #ifdef _WIN32 HKEY hkey; DWORD dtype; char wpath[TQSL_MAX_PATH_LEN]; DWORD bsize = sizeof wpath; int wval; if ((wval = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\TrustedQSL"), 0, KEY_READ, &hkey)) == ERROR_SUCCESS) { wval = RegQueryValueEx(hkey, _T("InstallPath"), 0, &dtype, (LPBYTE)wpath, &bsize); RegCloseKey(hkey); if (wval == ERROR_SUCCESS) { string p = string(wpath); if (p[p.length() -1] == '\\') p = p.substr(0, p.length() - 1); tQSL_RsrcDir = strdup(p.c_str()); } } #elif defined(__APPLE__) // Get path to config.xml resource from bundle CFBundleRef tqslBundle = CFBundleGetMainBundle(); CFURLRef configXMLURL = CFBundleCopyResourceURL(tqslBundle, CFSTR("config"), CFSTR("xml"), NULL); if (configXMLURL) { CFStringRef pathString = CFURLCopyFileSystemPath(configXMLURL, kCFURLPOSIXPathStyle); CFRelease(configXMLURL); // Convert CFString path to config.xml to string object CFIndex maxStringLengthInBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(pathString), kCFStringEncodingUTF8); char *pathCString = static_cast(malloc(maxStringLengthInBytes)); if (pathCString) { CFStringGetCString(pathString, pathCString, maxStringLengthInBytes, kCFStringEncodingASCII); CFRelease(pathString); size_t p; string path = string(pathCString); if ((p = path.find("/config.xml")) != string::npos) { path = path.substr(0, p); } tQSL_RsrcDir = strdup(path.c_str()); free(pathCString); } } #else // Get the base directory string p = CONFDIR; // Strip trailing "/" if (p[p.length() - 1] == '/') p = p.substr(0, p.length() - 1); // Check if running as an AppImage char *appdir = getenv("APPDIR"); if (appdir == NULL) { tQSL_RsrcDir = strdup(p.c_str()); } else { string p1 = appdir; // Strip trailing "/" if (p1[p1.length() - 1] == '/') p1 = p1.substr(0, p1.length() - 1); p1 = p1 + p; // Assume APPDIR is probably not an AppImage root tQSL_RsrcDir = strdup(p.c_str()); // See if it's likely to be an AppImage struct stat s; if (stat(p1.c_str(), &s) == 0) { if (S_ISDIR(s.st_mode)) { tQSL_RsrcDir = strdup(p1.c_str()); } } } #endif tqslTrace("tqsl_get_rsrc_dir", "rsrc_path=%s", tQSL_RsrcDir); } DLLEXPORT int CALLCONVENTION tqsl_init() { static char semaphore = 0; unsigned int i; ERR_clear_error(); tqsl_getErrorString(); /* Clear the error status */ if (semaphore) return 0; #ifdef _WIN32 static wchar_t path[TQSL_MAX_PATH_LEN]; // lets cin/out/err work in windows // AllocConsole(); // freopen("CONIN$", "r", stdin); // freopen("CONOUT$", "w", stdout); // freopen("CONOUT$", "w", stderr); // not used DWORD bsize = sizeof path; int wval; #else static char path[TQSL_MAX_PATH_LEN]; #endif #if !defined(_WIN32) && !defined(__APPLE__) // Work around ill-considered decision by Fedora to stop allowing // certificates with MD5 signatures setenv("OPENSSL_ENABLE_MD5_VERIFY", "1", 0); #endif /* OpenSSL API tends to change between minor version numbers, so make sure * we're using the right version */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L unsigned long SSLver = OpenSSL_version_num(); #else long SSLver = SSLeay(); #endif int SSLmajor = (SSLver >> 28) & 0xff; int SSLminor = (SSLver >> 20) & 0xff; int TQSLmajor = (OPENSSL_VERSION_NUMBER >> 28) & 0xff; int TQSLminor = (OPENSSL_VERSION_NUMBER >> 20) & 0xff; if (SSLmajor != TQSLmajor || (SSLminor != TQSLminor && (SSLmajor != 9 && SSLminor != 7 && TQSLminor == 6))) { tqslTrace("tqsl_init", "version error - ssl %d.%d", SSLmajor, SSLminor); tQSL_Error = TQSL_OPENSSL_VERSION_ERROR; return 1; } #if OPENSSL_VERSION_MAJOR >= 3 // // OpenSSL 3.x moved several algorithms to "legacy" status and doesn't // enable them by default. Initialize the legacy provider to enable these. // Then enable the default provider. // OSSL_PROVIDER *def; OSSL_PROVIDER *legacy; legacy = OSSL_PROVIDER_load(NULL, "legacy"); if (legacy == NULL) { tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } def = OSSL_PROVIDER_load(NULL, "default"); if (def == NULL) { tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); #endif for (i = 0; i < (sizeof custom_objects / sizeof custom_objects[0]); i++) { if (OBJ_create(custom_objects[i][0], custom_objects[i][1], custom_objects[i][2]) == 0) { tqslTrace("tqsl_init", "Error making custom objects: %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } } if (tQSL_RsrcDir == NULL) { tqsl_get_rsrc_dir(); } if (tQSL_BaseDir == NULL) { #if defined(_WIN32) wchar_t *wcp; if ((wcp = _wgetenv(L"TQSLDIR")) != NULL && *wcp != '\0') { wcsncpy(path, wcp, sizeof(path) / sizeof(path[0])); #else char *cp; if ((cp = getenv("TQSLDIR")) != NULL && *cp != '\0') { strncpy(path, cp, sizeof path); #endif } else { #if defined(_WIN32) wval = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path); if (wval != ERROR_SUCCESS) wcsncpy(path, L"C:", sizeof(path) / sizeof(path[0])); wcsncat(path, L"\\TrustedQSL", sizeof(path) / sizeof(path[0]) - wcslen(path) - 1); #elif defined(LOTW_SERVER) strncpy(path, "/var/lotw/tqsl", sizeof path); #else // some unix flavor if (getenv("HOME") != NULL) { strncpy(path, getenv("HOME"), sizeof path); strncat(path, "/", sizeof path - strlen(path)-1); strncat(path, ".tqsl", sizeof path - strlen(path)-1); } else { strncpy(path, ".tqsl", sizeof path); } #endif } if (pmkdir(path, 0700)) { #if defined(_WIN32) char *p = wchar_to_utf8(path, false); strncpy(tQSL_ErrorFile, p, sizeof tQSL_ErrorFile); #else strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; #if defined(_WIN32) tqslTrace("tqsl_init", "Error creating working path %s: %s", p, strerror(errno)); free(p); #else tqslTrace("tqsl_init", "Error creating working path %s: %s", path, strerror(errno)); #endif return 1; } FILE *test; #if defined(_WIN32) tQSL_BaseDir = wchar_to_utf8(path, true); wcsncat(path, L"\\tmp.tmp", sizeof(path) / sizeof(path[0]) - wcslen(path) - 1); if ((test = _wfopen(path, L"wb")) == NULL) { tQSL_Errno = errno; char *p = wchar_to_utf8(path, false); snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Unable to create files in the TQSL working directory (%s): %m", p); tQSL_Error = TQSL_CUSTOM_ERROR; return 1; } fclose(test); _wunlink(path); #else if (tQSL_BaseDir) free (const_cast(tQSL_BaseDir)); tQSL_BaseDir = strdup(path); strncat(path, "/tmp.tmp", sizeof path -strlen(path) - 1); if ((test = fopen(path, "wb")) == NULL) { tQSL_Errno = errno; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Unable to create files in the TQSL working directory (%s): %m", tQSL_BaseDir); tQSL_Error = TQSL_CUSTOM_ERROR; return 1; } fclose(test); unlink(path); #endif } // // Ensure that tQSL_RsrcDir is set // Correction from JJ1BDX // if (!tQSL_RsrcDir) tQSL_RsrcDir = tQSL_BaseDir; semaphore = 1; return 0; } DLLEXPORT int CALLCONVENTION tqsl_setDirectory(const char *dir) { static char path[TQSL_MAX_PATH_LEN]; if (strlen(dir) >= TQSL_MAX_PATH_LEN) { tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(path, dir, sizeof path); tQSL_BaseDir = path; return 0; } DLLEXPORT const char* CALLCONVENTION tqsl_getErrorString_v(int err) { static char buf[512]; unsigned long openssl_err; int adjusted_err; if (err == 0) return "NO ERROR"; if (err == TQSL_CUSTOM_ERROR) { if (tQSL_CustomError[0] == 0) { return "Unknown custom error"; } else { strncpy(buf, tQSL_CustomError, sizeof buf); return buf; } } if (err == TQSL_DB_ERROR && tQSL_CustomError[0] != 0) { snprintf(buf, sizeof buf, "Database Error: %s", tQSL_CustomError); return buf; } if (err == TQSL_SYSTEM_ERROR || err == TQSL_FILE_SYSTEM_ERROR) { if (strlen(tQSL_ErrorFile) > 0) { snprintf(buf, sizeof buf, "System error: %s : %s", tQSL_ErrorFile, strerror(tQSL_Errno)); tQSL_ErrorFile[0] = '\0'; } else { snprintf(buf, sizeof buf, "System error: %s", strerror(tQSL_Errno)); } return buf; } if (err == TQSL_FILE_SYNTAX_ERROR) { tqslTrace("SyntaxError", "File (partial) content '%s'", tQSL_CustomError); if (strlen(tQSL_ErrorFile) > 0) { snprintf(buf, sizeof buf, "File syntax error: %s", tQSL_ErrorFile); tQSL_ErrorFile[0] = '\0'; } else { strncpy(buf, "File syntax error", sizeof buf); } return buf; } if (err == TQSL_OPENSSL_ERROR) { openssl_err = ERR_get_error(); strncpy(buf, "OpenSSL error: ", sizeof buf); if (openssl_err) ERR_error_string_n(openssl_err, buf + strlen(buf), sizeof buf - strlen(buf)-1); else strncat(buf, "[error code not available]", sizeof buf - strlen(buf)-1); return buf; } if (err == TQSL_ADIF_ERROR) { buf[0] = 0; if (strlen(tQSL_ErrorFile) > 0) { snprintf(buf, sizeof buf, "%s: %s", tQSL_ErrorFile, tqsl_adifGetError(tQSL_ADIF_Error)); tQSL_ErrorFile[0] = '\0'; } else { snprintf(buf, sizeof buf, "%s", tqsl_adifGetError(tQSL_ADIF_Error)); } return buf; } if (err == TQSL_CABRILLO_ERROR) { buf[0] = 0; if (strlen(tQSL_ErrorFile) > 0) { snprintf(buf, sizeof buf, "%s: %s", tQSL_ErrorFile, tqsl_cabrilloGetError(tQSL_Cabrillo_Error)); tQSL_ErrorFile[0] = '\0'; } else { snprintf(buf, sizeof buf, "%s", tqsl_cabrilloGetError(tQSL_Cabrillo_Error)); } return buf; } if (err == TQSL_OPENSSL_VERSION_ERROR) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L unsigned long SSLver = OpenSSL_version_num(); #else long SSLver = SSLeay(); #endif snprintf(buf, sizeof buf, "Incompatible OpenSSL Library version %d.%d.%d; expected %d.%d.%d", static_cast(SSLver >> 28) & 0xff, static_cast(SSLver >> 20) & 0xff, static_cast(SSLver >> 12) & 0xff, static_cast(OPENSSL_VERSION_NUMBER >> 28) & 0xff, static_cast(OPENSSL_VERSION_NUMBER >> 20) & 0xff, static_cast(OPENSSL_VERSION_NUMBER >> 12) & 0xff); return buf; } if (err == TQSL_CERT_NOT_FOUND && tQSL_ImportCall[0] != '\0') { snprintf(buf, sizeof buf, "The private key for callsign %s serial %ld is not present on this computer; you can obtain it by loading a .tbk or .p12 file", tQSL_ImportCall, tQSL_ImportSerial); tQSL_ImportCall[0] = '\0'; return buf; } adjusted_err = (err - TQSL_ERROR_ENUM_BASE) & ~0x1000; if (adjusted_err < 0 || adjusted_err >= static_cast(sizeof error_strings / sizeof error_strings[0])) { snprintf(buf, sizeof buf, "Invalid error code: %d", err); return buf; } if (err == TQSL_CERT_MISMATCH || err == TQSL_LOCATION_MISMATCH) { const char *fld, *cert, *qso; fld = strtok(tQSL_CustomError, "|"); cert = strtok(NULL, "|"); qso = strtok(NULL, "|"); if (qso == NULL) { // Nothing in the cert qso = cert; cert = "none"; } snprintf(buf, sizeof buf, "%s\nThe %s '%s' has value '%s' while QSO has '%s'", error_strings[adjusted_err], err == TQSL_LOCATION_MISMATCH ? "Station Location" : "Callsign Certificate", fld, cert, qso); return buf; } if (err == (TQSL_LOCATION_MISMATCH | 0x1000)) { const char *fld, *val; fld = strtok(tQSL_CustomError, "|"); val = strtok(NULL, "|"); snprintf(buf, sizeof buf, "This log has invalid QSO information.\nThe log being signed has '%s' set to value '%s' which is not valid", fld, val); return buf; } if (err == (TQSL_CERT_NOT_FOUND | 0x1000)) { const char *call, *ent; err = TQSL_CERT_NOT_FOUND; call = strtok(tQSL_CustomError, "|"); ent = strtok(NULL, "|"); snprintf(buf, sizeof buf, "There is no valid callsign certificate for %s in entity %s available. This QSO cannot be signed", call, ent); return buf; } return error_strings[adjusted_err]; } DLLEXPORT const char* CALLCONVENTION tqsl_getErrorString() { const char *cp; cp = tqsl_getErrorString_v(tQSL_Error); tQSL_Error = TQSL_NO_ERROR; tQSL_Errno = 0; tQSL_ErrorFile[0] = 0; tQSL_CustomError[0] = 0; return cp; } DLLEXPORT int CALLCONVENTION tqsl_encodeBase64(const unsigned char *data, int datalen, char *output, int outputlen) { BIO *bio = NULL, *bio64 = NULL; int n; char *memp; int rval = 1; if (data == NULL || output == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_encodeBase64", "arg err data=0x%lx, output=0x%lx", data, output); return rval; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_encodeBase64", "BIO_new err %s", tqsl_openssl_error()); goto err; } if ((bio64 = BIO_new(BIO_f_base64())) == NULL) { tqslTrace("tqsl_encodeBase64", "BIO_new64 err %s", tqsl_openssl_error()); goto err; } bio = BIO_push(bio64, bio); if (BIO_write(bio, data, datalen) < 1) { tqslTrace("tqsl_encodeBase64", "BIO_write err %s", tqsl_openssl_error()); goto err; } if (BIO_flush(bio) != 1) { tqslTrace("tqsl_encodeBase64", "BIO_flush err %s", tqsl_openssl_error()); goto err; } n = BIO_get_mem_data(bio, &memp); if (n > outputlen-1) { tqslTrace("tqsl_encodeBase64", "buffer has %d, avail %d", n, outputlen); tQSL_Error = TQSL_BUFFER_ERROR; goto end; } memcpy(output, memp, n); output[n] = 0; BIO_free_all(bio); bio = NULL; rval = 0; goto end; err: tQSL_Error = TQSL_OPENSSL_ERROR; end: if (bio != NULL) BIO_free_all(bio); return rval; } DLLEXPORT int CALLCONVENTION tqsl_decodeBase64(const char *input, unsigned char *data, int *datalen) { BIO *bio = NULL, *bio64 = NULL; int n; int rval = 1; if (input == NULL || data == NULL || datalen == NULL) { tqslTrace("tqsl_decodeBase64", "arg error input=0x%lx, data=0x%lx, datalen=0x%lx", input, data, datalen); tQSL_Error = TQSL_ARGUMENT_ERROR; return rval; } if ((bio = BIO_new_mem_buf(const_cast(input), strlen(input))) == NULL) { tqslTrace("tqsl_decodeBase64", "BIO_new_mem_buf err %s", tqsl_openssl_error()); goto err; } BIO_set_mem_eof_return(bio, 0); if ((bio64 = BIO_new(BIO_f_base64())) == NULL) { tqslTrace("tqsl_decodeBase64", "BIO_new err %s", tqsl_openssl_error()); goto err; } bio = BIO_push(bio64, bio); n = BIO_read(bio, data, *datalen); if (n < 0) { tqslTrace("tqsl_decodeBase64", "BIO_read error %s", tqsl_openssl_error()); goto err; } if (BIO_ctrl_pending(bio) != 0) { tqslTrace("tqsl_decodeBase64", "ctrl_pending err %s", tqsl_openssl_error()); tQSL_Error = TQSL_BUFFER_ERROR; goto end; } *datalen = n; rval = 0; goto end; err: tQSL_Error = TQSL_OPENSSL_ERROR; end: if (bio != NULL) BIO_free_all(bio); return rval; } /* Convert a tQSL_Date field to an ISO-format date string */ DLLEXPORT char* CALLCONVENTION tqsl_convertDateToText(const tQSL_Date *date, char *buf, int bufsiz) { char lbuf[10]; int len; char *cp = buf; int bufleft = bufsiz-1; if (date == NULL || buf == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; if (buf) buf[0] = '\0'; return NULL; } if (date->year < 1 || date->year > 9999 || date->month < 1 || date->month > 12 || date->day < 1 || date->day > 31) { buf[0] = '\0'; return NULL; } len = snprintf(lbuf, sizeof lbuf, "%04d-", date->year); strncpy(cp, lbuf, bufleft); cp += len; bufleft -= len; len = snprintf(lbuf, sizeof lbuf, "%02d-", date->month); if (bufleft > 0) strncpy(cp, lbuf, bufleft); cp += len; bufleft -= len; len = snprintf(lbuf, sizeof lbuf, "%02d", date->day); if (bufleft > 0) strncpy(cp, lbuf, bufleft); bufleft -= len; if (bufleft < 0) return NULL; buf[bufsiz-1] = '\0'; return buf; } DLLEXPORT int CALLCONVENTION tqsl_isDateValid(const tQSL_Date *d) { static int mon_days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (d == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 0; } if (d->year < 1 || d->year > 9999) return 0; if (d->month < 1 || d->month > 12) return 0; if (d->day < 1 || d->day > 31) return 0; mon_days[2] = ((d->year % 4) == 0 && ((d->year % 100) != 0 || (d->year % 400) == 0)) ? 29 : 28; if (d->day > mon_days[d->month]) return 0; return 1; } DLLEXPORT int CALLCONVENTION tqsl_isDateNull(const tQSL_Date *d) { if (d == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } return (d->year == 0 && d->month == 0 && d->day == 0) ? 1 : 0; } /* Convert a tQSL_Time field to an ISO-format date string */ DLLEXPORT char* CALLCONVENTION tqsl_convertTimeToText(const tQSL_Time *time, char *buf, int bufsiz) { char lbuf[10]; int len; char *cp = buf; int bufleft = bufsiz-1; if (time == NULL || buf == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return NULL; } if (!tqsl_isTimeValid(time)) return NULL; len = snprintf(lbuf, sizeof lbuf, "%02d:", time->hour); strncpy(cp, lbuf, bufleft); cp += len; bufleft -= len; len = snprintf(lbuf, sizeof lbuf, "%02d:", time->minute); if (bufleft > 0) strncpy(cp, lbuf, bufleft); cp += len; bufleft -= len; len = snprintf(lbuf, sizeof lbuf, "%02d", time->second); if (bufleft > 0) strncpy(cp, lbuf, bufleft); cp += len; bufleft -= len; if (bufleft > 0) strncpy(cp, "Z", bufleft); bufleft -= 1; if (bufleft < 0) return NULL; buf[bufsiz-1] = '\0'; return buf; } DLLEXPORT int CALLCONVENTION tqsl_isTimeValid(const tQSL_Time *t) { if (t == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 0; } if (t->hour < 0 || t->hour > 23) return 0; if (t->minute < 0 || t->minute > 59) return 0; if (t->second < 0 || t->second > 59) return 0; return 1; } /* Compare two tQSL_Date values, returning -1, 0, 1 */ DLLEXPORT int CALLCONVENTION tqsl_compareDates(const tQSL_Date *a, const tQSL_Date *b) { if (a == NULL || b == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (a->year < b->year) return -1; if (a->year > b->year) return 1; if (a->month < b->month) return -1; if (a->month > b->month) return 1; if (a->day < b->day) return -1; if (a->day > b->day) return 1; return 0; } // Return the number of days for a given year/month (January=1) static int days_per_month(int year, int month) { switch (month) { case 2: if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) { return 29; } else { return 28; } case 4: case 6: case 9: case 11: return 30; default: return 31; } return 0; } // Return the julian day number for a given date. // One-based year/month/day static int julian_day(int year, int month, int day) { int jday = 0; for (int mon = 1; mon < month; mon ++) { jday += days_per_month(year, mon); } jday += day; return jday; } /* Calculate the difference between two tQSL_Date values */ DLLEXPORT int CALLCONVENTION tqsl_subtractDates(const tQSL_Date *a, const tQSL_Date *b, int *diff) { if (a == NULL || b == NULL || diff == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tQSL_Date first = *a; tQSL_Date last = *b; int mult = 1; // Ensure that the first is earliest if (tqsl_compareDates(&last, &first) < 0) { first = *b; last = *a; mult = -1; } int delta = 0; for (; first.year < last.year; first.year++) { int fday = julian_day(first.year, first.month, first.day); int fend = julian_day(first.year, 12, 31); delta += (fend - fday + 1); // days until next 1 Jan first.month = 1; first.day = 1; } // Now the years are the same - calculate delta int fjulian = julian_day(first.year, first.month, first.day); int ljulian = julian_day(last.year, last.month, last.day); delta += (ljulian - fjulian); *diff = (delta * mult); // Swap sign if necessary return 0; } /* Fill a tQSL_Date struct with the date from a text string */ DLLEXPORT int CALLCONVENTION tqsl_initDate(tQSL_Date *date, const char *str) { const char *cp; if (date == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (str == NULL) { date->year = date->month = date->day = 0; return 0; } if ((cp = strchr(str, '-')) != NULL) { /* Parse YYYY-MM-DD */ date->year = strtol(str, NULL, 10); cp++; date->month = strtol(cp, NULL, 10); cp = strchr(cp, '-'); if (cp == NULL) goto err; cp++; date->day = strtol(cp, NULL, 10); } else if (strlen(str) == 8) { /* Parse YYYYMMDD */ char frag[10]; strncpy(frag, str, 4); frag[4] = 0; date->year = strtol(frag, NULL, 10); strncpy(frag, str+4, 2); frag[2] = 0; date->month = strtol(frag, NULL, 10); date->day = strtol(str+6, NULL, 10); } else { /* Invalid ISO date string */ goto err; } if (date->year < 1 || date->year > 9999) goto err; if (date->month < 1 || date->month > 12) goto err; if (date->day < 1 || date->day > 31) goto err; return 0; err: tQSL_Error = TQSL_INVALID_DATE; return 1; } /* Fill a tQSL_Time struct with the time from a text string */ DLLEXPORT int CALLCONVENTION tqsl_initTime(tQSL_Time *time, const char *str) { const char *cp; int parts[3]; int i; if (time == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } time->hour = time->minute = time->second = 0; if (str == NULL) return 0; if (strlen(str) < 3) { tQSL_Error = TQSL_INVALID_TIME; return 1; } parts[0] = parts[1] = parts[2] = 0; for (i = 0, cp = str; i < static_cast(sizeof parts / sizeof parts[0]); i++) { if (strlen(cp) < 2) break; if (!isdigit(*cp) || !isdigit(*(cp+1))) goto err; if (i == 0 && strlen(str) == 3) { // Special case: HMM -- no colons, one-digit hour parts[i] = *cp - '0'; ++cp; } else { parts[i] = (*cp - '0') * 10 + *(cp+1) - '0'; cp += 2; } if (*cp == ':') cp++; } if (parts[0] < 0 || parts[0] > 23) goto err; if (parts[1] < 0 || parts[1] > 59) goto err; if (parts[2] < 0 || parts[2] > 59) goto err; time->hour = parts[0]; time->minute = parts[1]; time->second = parts[2]; return 0; err: tQSL_Error = TQSL_INVALID_TIME; return 1; } DLLEXPORT int CALLCONVENTION tqsl_getVersion(int *major, int *minor) { if (major) *major = TQSLLIB_VERSION_MAJOR; if (minor) *minor = TQSLLIB_VERSION_MINOR; return 0; } #ifdef _WIN32 DLLEXPORT wchar_t* CALLCONVENTION utf8_to_wchar(const char* str) { wchar_t* buffer; int needed = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0, 0); buffer = static_cast(malloc(needed*sizeof(wchar_t) + 4)); if (!buffer) return NULL; MultiByteToWideChar(CP_UTF8, 0, str, -1, &buffer[0], needed); return buffer; } DLLEXPORT char* CALLCONVENTION wchar_to_utf8(const wchar_t* str, bool forceUTF8) { char* buffer; int needed = WideCharToMultiByte(forceUTF8 ? CP_UTF8 : CP_ACP, 0, str, -1, 0, 0, NULL, NULL); buffer = static_cast(malloc(needed + 2)); if (!buffer) return NULL; WideCharToMultiByte(forceUTF8 ? CP_UTF8 : CP_ACP, 0, str, -1, &buffer[0], needed, NULL, NULL); return buffer; } DLLEXPORT void CALLCONVENTION free_wchar(wchar_t* ptr) { free(ptr); } #endif DLLEXPORT void CALLCONVENTION tqslTrace(const char *name, const char *format, ...) { va_list ap; if (!tQSL_DiagFile) return; time_t t = time(0); char timebuf[50]; strncpy(timebuf, ctime(&t), sizeof timebuf); timebuf[strlen(timebuf) - 1] = '\0'; // Strip the newline if (!format) { fprintf(tQSL_DiagFile, "%s %s\r\n", timebuf, name); fflush(tQSL_DiagFile); return; } else { if (name) { fprintf(tQSL_DiagFile, "%s %s: ", timebuf, name); } } va_start(ap, format); vfprintf(tQSL_DiagFile, format, ap); va_end(ap); fprintf(tQSL_DiagFile, "\r\n"); fflush(tQSL_DiagFile); } DLLEXPORT void CALLCONVENTION tqsl_closeDiagFile(void) { if (tQSL_DiagFile) fclose(tQSL_DiagFile); tQSL_DiagFile = NULL; } DLLEXPORT int CALLCONVENTION tqsl_diagFileOpen(void) { return tQSL_DiagFile != NULL; } DLLEXPORT int CALLCONVENTION tqsl_openDiagFile(const char *fname) { #ifdef _WIN32 wchar_t* lfn = utf8_to_wchar(fname); tQSL_DiagFile = _wfopen(lfn, L"wb"); free_wchar(lfn); #else tQSL_DiagFile = fopen(fname, "wb"); #endif return (tQSL_DiagFile == NULL); } const char* tqsl_openssl_error(void) { static char buf[256]; unsigned long openssl_err; openssl_err = ERR_peek_error(); if (openssl_err) ERR_error_string_n(openssl_err, buf, sizeof buf); else strncpy(buf, "[error code not available]", sizeof buf); return buf; } tqsl-2.7.2/src/tqsllib-doc.h0000644000175000017500000000264414534122221015662 0ustar rmurphyrmurphy/*************************************************************************** tqsllib-doc.h - description ------------------- begin : Tue Jun 4 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ /** \mainpage * * The TrustedQSL library API is divided into several groups: * * \li \ref CertStuff - Request, load and retrieve digital certificates * \li \ref Data - Manage station-location data and produce signed data records * \li \ref Convert - Convert and sign ADIF and Cabrillo log files * \li \ref Util - Functions to operate on objects, set system parameters, and report errors * \li \ref Sign - Low-level digital signing * \li \ref ADIF - Low-level parsing and creation of ADIF files * \li \ref Cabrillo - Low-level parsing of Cabrillo files. * * Most of the library functions return an integer value that is * zero if there is no error and 1 if there is an error. The specific * error can be determined by examining #tQSL_Error and, possibly, * #tQSL_ADIF_Error, #tQSL_Cabrillo_Error, #tQSL_ErrorFile and * #tQSL_CustomError. The tqsl_getErrorString() and tqsl_getErrorString_v() * functions can be used to get error text strings. * */ tqsl-2.7.2/src/tqslexc.h0000644000175000017500000000173114534122221015124 0ustar rmurphyrmurphy/*************************************************************************** tqslexc.h - description ------------------- begin : Sat Dec 14 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef __tqslexc_h #define __tqslexc_h #include #include #include "tqsllib.h" using std::exception; using std::string; class myexc : public exception { public: explicit myexc(const string& err) : exception() { _err = err; } myexc(const myexc& x) { _err = x._err; } virtual const char *what() const throw () { return _err.c_str(); } virtual ~myexc() throw() {} private: string _err; }; class tqslexc : public myexc { public: tqslexc() : myexc(tqsl_getErrorString()) {} }; #endif // __tqslexc_h tqsl-2.7.2/src/tqslerrno.h0000644000175000017500000000616114534122221015474 0ustar rmurphyrmurphy/*************************************************************************** tqslerrno.h - description ------------------- begin : Tue May 28 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef __TQSLERRNO_H #define __TQSLERRNO_H /** \file * #tQSL_Error values */ #define TQSL_NO_ERROR 0 ///< No error #define TQSL_SYSTEM_ERROR 1 ///< System Error #define TQSL_OPENSSL_ERROR 2 ///< Error in OpenSSL calls #define TQSL_ADIF_ERROR 3 ///< ADIF Errors #define TQSL_CUSTOM_ERROR 4 ///< Custom errors - output to tQSL_CustomError #define TQSL_CABRILLO_ERROR 5 ///< Cabrillo handler error #define TQSL_OPENSSL_VERSION_ERROR 6 ///< OpenSSL version obsolete #define TQSL_ERROR_ENUM_BASE 16 ///< Base for enumerated errors #define TQSL_ALLOC_ERROR 16 ///< Memory allocation error #define TQSL_RANDOM_ERROR 17 ///< Error initializing random number generator #define TQSL_ARGUMENT_ERROR 18 ///< Invalid arguments #define TQSL_OPERATOR_ABORT 19 ///< Aborted by operator #define TQSL_NOKEY_ERROR 20 ///< No key available #define TQSL_BUFFER_ERROR 21 ///< Insufficient buffer space #define TQSL_INVALID_DATE 22 ///< Date string invalid #define TQSL_SIGNINIT_ERROR 23 ///< Error initializing signing routine #define TQSL_PASSWORD_ERROR 24 ///< Invalid password #define TQSL_EXPECTED_NAME 25 ///< Name expected but not supplied #define TQSL_NAME_EXISTS 26 ///< Entity name exists already #define TQSL_NAME_NOT_FOUND 27 ///< Entity name does not exist #define TQSL_INVALID_TIME 28 ///< Time format is invalid #define TQSL_CERT_DATE_MISMATCH 29 ///< Certificate date mismatch #define TQSL_PROVIDER_NOT_FOUND 30 ///< Certificate provider unknown #define TQSL_CERT_KEY_ONLY 31 ///< No signed public key is installed #define TQSL_CONFIG_ERROR 32 ///< There is an error in the configuration file #define TQSL_CERT_NOT_FOUND 33 ///< The certificate could not be found #define TQSL_PKCS12_ERROR 34 ///< There is an error parsing the .p12 file #define TQSL_CERT_TYPE_ERROR 35 ///< The certificate type is invalid #define TQSL_DATE_OUT_OF_RANGE 36 ///< The date is out of the valid range #define TQSL_DUPLICATE_QSO 37 ///< This QSO is already uploaded #define TQSL_DB_ERROR 38 ///< The dupe database could not be accessed #define TQSL_LOCATION_NOT_FOUND 39 ///< The station location is invalid #define TQSL_CALL_NOT_FOUND 40 ///< The callsign could not be located #define TQSL_CONFIG_SYNTAX_ERROR 41 ///< The config file has a syntax error #define TQSL_FILE_SYSTEM_ERROR 42 ///< There was a file system I/O error #define TQSL_FILE_SYNTAX_ERROR 43 ///< The file format is invalid #define TQSL_CERT_ERROR 44 ///< Callsign certificate could not be installed #define TQSL_CERT_MISMATCH 45 ///< Callsign Certificate does not match QSO details #define TQSL_LOCATION_MISMATCH 46 ///< Station Location does not match QSO details #define TQSL_NEW_UPLOAD_DB 47 ///< New upload database created, try to re-load it #endif /* __TQSLERRNO_H */ tqsl-2.7.2/src/tqslconvert.h0000644000175000017500000002072614534122221016032 0ustar rmurphyrmurphy/*************************************************************************** convert.h - description ------------------- begin : Sun Nov 17 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef __tqslconvert_h #define __tqslconvert_h #include "tqsllib.h" /** \file * tQSL library converter functions. */ /** \defgroup Convert Converter API * * The Converter API provides the capability of converting Cabrillo * and ADIF files to GABBI output. */ /** @{ */ typedef void * tQSL_Converter; //!< Opaque converter type used by applications //!< to access conversion functions //!< #ifdef __cplusplus extern "C" { #endif /** Create a simple converter object * * Allocates resources for converting logs and processing duplicate records. */ DLLEXPORT int CALLCONVENTION tqsl_beginConverter(tQSL_Converter *convp); /** Initiates the conversion process for an ADIF file. * * \c certs and \c ncerts define a set of certificates that are available to the * converter for signing records. Typically, this list will be obtained by * calling tqsl_selectCertificates(). * * tqsl_endConverter() should be called to free the resources when the conversion * is finished. */ DLLEXPORT int CALLCONVENTION tqsl_beginADIFConverter(tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc); /** Initiates the conversion process for a Cabrillo file. * * \c certs and \c ncerts define a set of certificates that are available to the * converter for signing records. Typically, this list will be obtained by * calling tqsl_selectCertificates(). * * tqsl_endConverter() should be called to free the resources when the conversion * is finished. */ DLLEXPORT int CALLCONVENTION tqsl_beginCabrilloConverter(tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc); /** End the conversion process by freeing the used resources. */ DLLEXPORT int CALLCONVENTION tqsl_endConverter(tQSL_Converter *conv); /** Configure the converter to allow (allow != 0) or disallow (allow == 0) * nonamateur call signs in the CALL field. (Note: the test for * validity is fairly trivial and will allow some nonamateur calls to * get through, but it does catch most common errors.) * * \c allow defaults to 0 when tqsl_beginADIFConverter or * tqsl_beginCabrilloConverter is called. */ DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowBadCall(tQSL_Converter conv, int allow); #define TQSL_LOC_IGNORE 0 ///< Ignore MY_ ADIF fields #define TQSL_LOC_REPORT 1 ///< Report on MY_ ADIF fields not matching cert/location #define TQSL_LOC_UPDATE 2 ///< Update Cert/Loc to track MY_ ADIF fields /** Configure the converter's handing of QTH fields in an adif input file * * \c allow defaults to 0 when tqsl_beginADIFConverter or * tqsl_beginCabrilloConverter is called. */ DLLEXPORT int CALLCONVENTION tqsl_setConverterQTHDetails(tQSL_Converter conv, int logverify); /** Configure the converter to allow (allow != 0) or disallow (allow == 0) * duplicate QSOs in a signed log. * Duplicate detection is done using QSO details, location details, and * certificate serial number. * * \c allow defaults to 1 for backwards compatibility when tqsl_beginADIFConverter or * tqsl_beginCabrilloConverter is called. */ DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowDuplicates(tQSL_Converter convp, int ignore); /** Configure the converter to ignore (ignore != 0) or include (ignore == 0) * seconds in times when detecting duplicate QSOs in a signed log. * Duplicate detection is done using QSO details, location details, and * certificate serial number. * * \c ignore defaults to 0. */ DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreSeconds(tQSL_Converter convp, int ignore); /** Configure the converter to ignore (ignore != 0) or include (ignore == 0) * callsigns in ADIF logs, * * \c ignore defaults to 0. */ DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreCallsigns(tQSL_Converter convp, int ignore); /** Specify the name of the application using the conversion library. * This is output in a header record in the exported log file. * Call this before calling tqsl_getConverterGABBI. * * \c app is a c string containing the application name. */ DLLEXPORT int CALLCONVENTION tqsl_setConverterAppName(tQSL_Converter convp, const char *app); /** Roll back insertions into the duplicates database. * * This is called when cancelling creating a log, and causes any records * added to the duplicates database to be removed so re-processing that * log does not cause the records to be mis-marked as duplicates. */ DLLEXPORT int CALLCONVENTION tqsl_converterRollBack(tQSL_Converter convp); /** Commits insertions into the duplicates database. * * This is called when a log is created normally and without issue, and so * the presumption is that we are "done" with these QSOs. */ DLLEXPORT int CALLCONVENTION tqsl_converterCommit(tQSL_Converter convp); /** Bulk read the duplicate DB records * * This is called to retrieve the QSO records from the dupe database. * It returns the key/value pair upon each call. * Return -1 for end of file, 0 for success, 1 for errors. */ DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecords(tQSL_Converter convp, char *key, char *data, int keylen); /** Bulk read the duplicate DB records * * This is called to retrieve the QSO records from the dupe database. * It returns the key/value pair upon each call. * Return -1 for end of file, 0 for success, 1 for errors. * V2 expects a 256 byte buffer for the "data" string. */ DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecordsV2(tQSL_Converter convp, char *key, char *data, int keylen); /** Bulk write duplicate DB records * * This is called to store a QSO record into the dupe database. * * Return -1 for duplicate insertion, 0 for success, 1 for errors. */ DLLEXPORT int CALLCONVENTION tqsl_putDuplicateRecord(tQSL_Converter convp, const char *key, const char *data, int keylen); /** Set QSO date filtering in the converter. * * If \c start points to a valid date, QSOs prior to that date will be ignored * by the converter. Similarly, if \c end points to a valid date, QSOs after * that date will be ignored. Either or both may be NULL (or point to an * invalid date) to disable date filtering for the respective range. */ DLLEXPORT int CALLCONVENTION tqsl_setADIFConverterDateFilter(tQSL_Converter conv, tQSL_Date *start, tQSL_Date *end); /** This is the main converter function. It returns a single GABBI * record. * * Returns the NULL pointer on error or EOF. (Test tQSL_Error to determine which.) * * tQSL_Error is set to TQSL_DATE_OUT_OF_RANGE if QSO date range checking * is active and the QSO date is outside the specified range. * This is a non-fatal error. * * tQSL_Error is set to TQSL_DUPLICATE_QSO if the QSO has already been * processed on the current computer. * * tQSL_Error is set to TQSL_NEW_UPLOAD_DB if a new uploads database was * created. This allows TQSL to attempt to re-load the QSOs from the most recent * automatic backup (if it exists). * * N.B. On systems that distinguish text-mode files from binary-mode files, * notably Windows, the GABBI records should be written in binary mode. * * N.B. If the selected certificate has not been initialized for signing via * tqsl_beginSigning(), this function will return a TQSL_SIGNINIT_ERROR. * The cert that caused the error can be obtained via tqsl_getConverterCert(), * initialized for signing, and then this function can be called again. No * data records will be lost in this process. */ DLLEXPORT const char* CALLCONVENTION tqsl_getConverterGABBI(tQSL_Converter conv); /** Get the certificate used to sign the most recent QSO record. */ DLLEXPORT int CALLCONVENTION tqsl_getConverterCert(tQSL_Converter conv, tQSL_Cert *certp); /** Get the input-file line number last read by the converter, starting * at line 1. */ DLLEXPORT int CALLCONVENTION tqsl_getConverterLine(tQSL_Converter conv, int *lineno); /** Get the text of the last record read by the converter. * * Returns NULL on error. */ DLLEXPORT const char* CALLCONVENTION tqsl_getConverterRecordText(tQSL_Converter conv); /** @} */ #ifdef __cplusplus } #endif #endif /* __tqslconvert_h */ tqsl-2.7.2/src/tqslconvert.cpp0000644000175000017500000020016114534122221016356 0ustar rmurphyrmurphy/*************************************************************************** tqslconvert.cpp - description ------------------- begin : Sun Nov 17 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #define TQSLLIB_DEF #include "tqsllib.h" #include "tqslconvert.h" #include #include #include #include #include "tqslerrno.h" #include #include #include #include #include #include #include #include #include //#include #ifndef _WIN32 #include #include #else #include #include "windirent.h" #endif #include "winstrdefs.h" using std::set; using std::string; using std::vector; using std::sort; using std::map; static bool checkCallSign(const string& call); namespace tqsllib { class TQSL_CONVERTER { public: TQSL_CONVERTER(); ~TQSL_CONVERTER(); void clearRec(); int sentinel; // FILE *file; tQSL_ADIF adif; tQSL_Cabrillo cab; tQSL_Cert *certs; int ncerts; tQSL_Location loc; TQSL_QSO_RECORD rec; bool rec_done; int cert_idx; int next_cert_uid; int cert_uid; int loc_uid; bool need_station_rec; int *cert_uids; bool allow_bad_calls; set modes; set bands; set propmodes; set satellites; string rec_text; tQSL_Date start, end; int location_handling; bool db_open; sqlite3 *seendb; sqlite3_stmt *bulk_read; bool txn; char *dbpath; FILE* errfile; char serial[512]; char callsign[64]; bool allow_dupes; bool ignore_secs; bool ignore_calls; bool need_ident_rec; char *appName; int dxcc; bool newstation; map taglines; int err_tag_line; }; #if !defined(__APPLE__) && !defined(_WIN32) && !defined(__clang__) #pragma GCC diagnostic ignored "-Wformat-truncation" #endif inline TQSL_CONVERTER::TQSL_CONVERTER() : sentinel(0x4445) { // file = 0; adif = 0; cab = 0; cert_idx = -1; dxcc = -1; loc_uid = 0; cert_uid = 0; next_cert_uid = 1; cert_uids = NULL; need_station_rec = false; rec_done = true; allow_bad_calls = false; location_handling = TQSL_LOC_UPDATE; allow_dupes = true; //by default, don't change existing behavior (also helps with commit) ignore_secs = false; // Use full time ignore_calls = false; // Use calls in adif file memset(&rec, 0, sizeof rec); memset(&start, 0, sizeof start); memset(&end, 0, sizeof end); db_open = false; seendb = NULL; bulk_read = NULL; txn = false; dbpath = NULL; errfile = NULL; memset(&serial, 0, sizeof serial); memset(&callsign, 0, sizeof callsign); appName = NULL; need_ident_rec = true; err_tag_line = 0; // Init the band data const char *val; int n = 0; tqsl_getNumBand(&n); for (int i = 0; i < n; i++) { val = 0; tqsl_getBand(i, &val, 0, 0, 0); if (val) bands.insert(val); } // Init the mode data n = 0; tqsl_getNumMode(&n); for (int i = 0; i < n; i++) { val = 0; tqsl_getMode(i, &val, 0); if (val) modes.insert(val); } // Init the propagation mode data n = 0; tqsl_getNumPropagationMode(&n); for (int i = 0; i < n; i++) { val = 0; tqsl_getPropagationMode(i, &val, 0); if (val) propmodes.insert(val); } // Init the satellite data n = 0; tqsl_getNumSatellite(&n); for (int i = 0; i < n; i++) { val = 0; tqsl_getSatellite(i, &val, 0, 0, 0); if (val) satellites.insert(val); } } inline TQSL_CONVERTER::~TQSL_CONVERTER() { clearRec(); // if (file) // fclose(file); tqsl_endADIF(&adif); if (cert_uids) delete[] cert_uids; sentinel = 0; } inline void TQSL_CONVERTER::clearRec() { memset(&rec, 0, sizeof rec); rec_text = ""; err_tag_line = 0; } #define CAST_TQSL_CONVERTER(x) ((tqsllib::TQSL_CONVERTER *)(x)) } // namespace tqsllib using tqsllib::TQSL_CONVERTER; template static void add_to_container(const char *str, size_t len, void *data) { Container *cont = static_cast(data); cont->push_back(string(str, len)); } typedef void(*split_fn)(const char *, size_t, void *); static void split(const char *str, char sep, split_fn fun, void *data) { unsigned int start = 0, stop; for (stop = 0; str[stop]; stop++) { if (str[stop] == sep) { fun(str + start, stop - start, data); start = stop + 1; } } fun(str + start, stop - start, data); } template static void splitStr(const string& str, Container& cont, char delim = ' ') { split(str.c_str(), delim, static_cast(add_to_container), &cont); } static char * fix_freq(const char *in) { static char out[128]; const char *p = in; bool decimal = false; char *o = out; while (*p) { if (*p == '.') { if (decimal) { p++; continue; } decimal = true; } *o++ = *p++; } *o = '\0'; return out; } static char * tqsl_strtoupper(char *str) { for (char *cp = str; *cp != '\0'; cp++) *cp = toupper(*cp); return str; } static TQSL_CONVERTER * check_conv(tQSL_Converter conv) { if (tqsl_init()) return 0; if (conv == 0 || CAST_TQSL_CONVERTER(conv)->sentinel != 0x4445) return 0; return CAST_TQSL_CONVERTER(conv); } static tqsl_adifFieldDefinitions adif_qso_record_fields[] = { { "CALL", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_CALLSIGN_MAX, 0, 0, NULL }, { "BAND", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_BAND_MAX, 0, 0, NULL }, { "MODE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_MODE_MAX, 0, 0, NULL }, { "SUBMODE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_MODE_MAX, 0, 0, NULL }, { "QSO_DATE", "", TQSL_ADIF_RANGE_TYPE_NONE, 10, 0, 0, NULL }, { "TIME_ON", "", TQSL_ADIF_RANGE_TYPE_NONE, 10, 0, 0, NULL }, { "FREQ", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_FREQ_MAX, 0, 0, NULL }, { "FREQ_RX", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_FREQ_MAX, 0, 0, NULL }, { "BAND_RX", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_BAND_MAX, 0, 0, NULL }, { "SAT_NAME", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_SATNAME_MAX, 0, 0, NULL }, { "PROP_MODE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_PROPMODE_MAX, 0, 0, NULL }, /* Fields specifying contents of the location for a QSO */ { "MY_CNTY", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_CNTY_MAX, 0, 0, NULL }, { "MY_COUNTRY", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_COUNTRY_MAX, 0, 0, NULL }, { "MY_CQ_ZONE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_ZONE_MAX, 0, 0, NULL }, { "MY_DXCC", "", TQSL_ADIF_RANGE_TYPE_NONE, 10, 0, 0, NULL }, { "MY_GRIDSQUARE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_GRID_MAX, 0, 0, NULL }, { "MY_IOTA", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_IOTA_MAX, 0, 0, NULL }, { "MY_ITU_ZONE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_ZONE_MAX, 0, 0, NULL }, { "MY_STATE", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_STATE_MAX, 0, 0, NULL }, { "MY_VUCC_GRIDS", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_GRID_MAX, 0, 0, NULL }, // Operator - make it long as some people use it as a name { "OPERATOR", "", TQSL_ADIF_RANGE_TYPE_NONE, 100, 0, 0, NULL }, { "STATION_CALLSIGN", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_CALLSIGN_MAX, 0, 0, NULL }, #ifdef USE_OWNER_CALLSIGN { "OWNER_CALLSIGN", "", TQSL_ADIF_RANGE_TYPE_NONE, TQSL_CALLSIGN_MAX, 0, 0, NULL }, #endif { "eor", "", TQSL_ADIF_RANGE_TYPE_NONE, 0, 0, 0, NULL }, { "", "", TQSL_ADIF_RANGE_TYPE_NONE, 0, 0, 0, NULL }, // Correction from JJ1BDX }; static void close_db(TQSL_CONVERTER *conv) { tqslTrace("close_db", NULL); if (conv->txn) { if (SQLITE_OK != sqlite3_exec(conv->seendb, "END;", NULL, NULL, NULL)) { tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tqslTrace("close_db", "Error ending transaction: %s", tQSL_CustomError); } conv->txn = false; } if (conv->db_open) { if (SQLITE_OK != sqlite3_close(conv->seendb)) { tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tqslTrace("close_db", "Error closing database: %s", tQSL_CustomError); } // close files and clean up converters, if any if (conv->adif) tqsl_endADIF(&conv->adif); if (conv->cab) tqsl_endCabrillo(&conv->cab); if (conv->errfile) fclose(conv->errfile); conv->errfile = NULL; } conv->db_open = false; return; } DLLEXPORT int CALLCONVENTION tqsl_beginConverter(tQSL_Converter *convp) { tqslTrace("tqsl_beginConverter", NULL); if (tqsl_init()) return 0; if (!convp) { tqslTrace("tqsl_beginConverter", "convp=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_CONVERTER *conv = new TQSL_CONVERTER(); *convp = conv; return 0; } DLLEXPORT int CALLCONVENTION tqsl_beginADIFConverter(tQSL_Converter *convp, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc) { tqslTrace("tqsl_beginADIFConverter", NULL); if (tqsl_init()) return 0; if (!convp || !filename) { tqslTrace("tqsl_beginADIFConverter", "arg err convp=0x%lx filename=0x%lx certs=0x%lx", convp, filename, certs); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tQSL_ADIF adif; if (tqsl_beginADIF(&adif, filename)) { tqslTrace("tqsl_beginADIFConverter", "tqsl_beginADIF fail %d", tQSL_Error); return 1; } TQSL_CONVERTER *conv = new TQSL_CONVERTER(); conv->adif = adif; conv->certs = certs; conv->ncerts = ncerts; if (ncerts > 0) { conv->cert_uids = new int[ncerts]; for (int i = 0; i < ncerts; i++) conv->cert_uids[i] = -1; } conv->loc = loc; *convp = conv; tqsl_getLocationCallSign(loc, conv->callsign, sizeof conv->callsign); tqsl_getLocationDXCCEntity(loc, &conv->dxcc); return 0; } DLLEXPORT int CALLCONVENTION tqsl_beginCabrilloConverter(tQSL_Converter *convp, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc) { tqslTrace("tqsl_beginCabrilloConverter", NULL); if (tqsl_init()) return 0; if (!convp || !filename) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_beginCabrilloConverter", "arg error convp=0x%lx, filename=0x%lx, certs=0x%lx", convp, filename, certs); return 1; } tQSL_Cabrillo cab; if (tqsl_beginCabrillo(&cab, filename)) { tqslTrace("tqsl_beginCabrilloConverter", "tqsl_beginCabrillo fail %d", tQSL_Error); return 1; } TQSL_CONVERTER *conv = new TQSL_CONVERTER(); conv->cab = cab; conv->certs = certs; conv->ncerts = ncerts; if (ncerts > 0) { conv->cert_uids = new int[ncerts]; for (int i = 0; i < ncerts; i++) conv->cert_uids[i] = -1; } conv->loc = loc; *convp = conv; tqsl_getLocationCallSign(loc, conv->callsign, sizeof conv->callsign); tqsl_getLocationDXCCEntity(loc, &conv->dxcc); return 0; } /* * Get a dupes db record by key. * Return: * 0 = Retrieved OK * 1 = No record * -1 = Error */ static int get_dbrec(sqlite3 *db, const char *key, char **result) { int rc; sqlite3_stmt *pstmt; rc = sqlite3_prepare_v2(db, "SELECT * from QSOs where tContact = ?;", 256, &pstmt, NULL); if (SQLITE_OK != rc) { return -1; } rc = sqlite3_bind_text(pstmt, 1, key, strlen(key), NULL); if (SQLITE_OK != rc) { sqlite3_finalize(pstmt); return -1; } rc = sqlite3_step(pstmt); if (SQLITE_DONE == rc) { // No record matches sqlite3_finalize(pstmt); return 1; } if (SQLITE_ROW != rc) { sqlite3_finalize(pstmt); return -1; } *result = strdup(reinterpret_cast(sqlite3_column_text(pstmt, 1))); sqlite3_finalize(pstmt); pstmt = NULL; return 0; } static int put_dbrec(sqlite3 *db, const char *key, const char *data) { int rc; sqlite3_stmt *pstmt; rc = sqlite3_prepare_v2(db, "INSERT OR IGNORE INTO QSOs VALUES(?, ?);", 256, &pstmt, NULL); if (SQLITE_OK != rc) { return -1; } rc = sqlite3_bind_text(pstmt, 1, key, strlen(key), NULL); if (SQLITE_OK != rc) { sqlite3_finalize(pstmt); return -1; } rc = sqlite3_bind_text(pstmt, 2, data, strlen(reinterpret_cast(data)), NULL); if (SQLITE_OK != rc) { return -1; } rc = sqlite3_step(pstmt); if (SQLITE_DONE == rc) { sqlite3_finalize(pstmt); return 0; } sqlite3_finalize(pstmt); return -1; } static int del_dbrec(sqlite3 *db, const char *key) { int rc; sqlite3_stmt *pstmt; rc = sqlite3_prepare_v2(db, "DELETE QSOs WHERE tContact = ?;", 256, &pstmt, NULL); if (SQLITE_OK != rc) { return -1; } rc = sqlite3_bind_text(pstmt, 1, key, strlen(key), NULL); if (SQLITE_OK != rc) { sqlite3_finalize(pstmt); return -1; } rc = sqlite3_step(pstmt); if (SQLITE_DONE == rc) { sqlite3_finalize(pstmt); return 0; } sqlite3_finalize(pstmt); return -1; } DLLEXPORT int CALLCONVENTION tqsl_endConverter(tQSL_Converter *convp) { tqslTrace("tqsl_endConverter", NULL); if (!convp || CAST_TQSL_CONVERTER(*convp) == 0) return 0; TQSL_CONVERTER* conv; if ((conv = check_conv(*convp))) { if (conv->txn) { sqlite3_exec(conv->seendb, "ROLLBACK;", NULL, NULL, NULL); conv->txn = false; } if (conv->db_open) { close_db(conv); } conv->db_open = false; // close files and clean up converters, if any if (conv->adif) tqsl_endADIF(&conv->adif); if (conv->cab) tqsl_endCabrillo(&conv->cab); if (conv->dbpath) free(conv->dbpath); if (conv->errfile) fclose(conv->errfile); conv->errfile = NULL; } if (conv->appName) free(conv->appName); if (CAST_TQSL_CONVERTER(*convp)->sentinel == 0x4445) delete CAST_TQSL_CONVERTER(*convp); *convp = 0; return 0; } static unsigned char * adif_allocate(size_t size) { return new unsigned char[size]; } static int find_matching_cert(TQSL_CONVERTER *conv, int targetdxcc, bool *anyfound) { int i; *anyfound = false; for (i = 0; i < conv->ncerts; i++) { tQSL_Date cdate; char call[256]; int dxcc; if (tqsl_getCertificateCallSign(conv->certs[i], call, sizeof call)) return -1; if (strcasecmp(conv->callsign, call)) // Not for this call continue; if (tqsl_getCertificateDXCCEntity(conv->certs[i], &dxcc)) return -1; if (dxcc != targetdxcc) continue; // Not for this call and DXCC *anyfound = true; if (tqsl_getCertificateQSONotBeforeDate(conv->certs[i], &cdate)) continue; if (tqsl_compareDates(&(conv->rec.date), &cdate) < 0) continue; if (tqsl_getCertificateQSONotAfterDate(conv->certs[i], &cdate)) continue; if (tqsl_compareDates(&(conv->rec.date), &cdate) > 0) continue; return i; } return -1; } static const char *notypes[] = { "D", "T", "M", "C", "N", "S", "B", "E", "L", "" }; // "C" is ADIF 1.0 for "S"; also "I" and "G" in ADIX static const char * tqsl_infer_band(const char* infreq) { char *oldlocale = setlocale(LC_NUMERIC, "C"); double freq = atof(infreq); setlocale(LC_NUMERIC, oldlocale); double freq_khz = freq * 1000.0; int nband = 0; tqsl_getNumBand(&nband); for (int i = 0; i < nband; i++) { const char *name; const char *spectrum; int low, high; if (tqsl_getBand(i, &name, &spectrum, &low, &high)) break; bool match = false; if (!strcmp(spectrum, "HF")) { // Allow for cases where loggers that don't log the // real frequency. if (low == 10100) low = 10000; else if (low == 18068) low = 18000; else if (low == 24890) low = 24000; if (freq_khz >= low && freq_khz <= high) { match = true; } } else { if (freq >= low && freq <= high) match = true; if (freq >= low && high == 0) match = true; } if (match) return name; } return ""; } DLLEXPORT int CALLCONVENTION tqsl_setADIFConverterDateFilter(tQSL_Converter convp, tQSL_Date *start, tQSL_Date *end) { TQSL_CONVERTER *conv; tqslTrace("tqsl_setADIFConverterDateFilter", NULL); if (!(conv = check_conv(convp))) return 1; if (start == NULL) conv->start.year = conv->start.month = conv->start.day = 0; else conv->start = *start; if (end == NULL) conv->end.year = conv->end.month = conv->end.day = 0; else conv->end = *end; return 0; } // Remove the dupes db files static void remove_db(const char *path) { tqslTrace("remove_db", "path=%s", path); #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); _WDIR *dir = _wopendir(wpath); free_wchar(wpath); #else DIR *dir = opendir(path); #endif if (dir != NULL) { #ifdef _WIN32 struct _wdirent *ent = NULL; while ((ent = _wreaddir(dir)) != NULL) { if (!wcscmp(ent->d_name, L"data.mdb") || !wcscmp(ent->d_name, L"lock.mdb") || !wcscmp(ent->d_name, L"uploaded.db") || !wcscmp(ent->d_name, L"uploaded.db-shm") || !wcscmp(ent->d_name, L"uploaded.db-wal")) { #else struct dirent *ent = NULL; while ((ent = readdir(dir)) != NULL) { if (!strcmp(ent->d_name, "data.mdb") || !strcmp(ent->d_name, "lock.mdb") || !strcmp(ent->d_name, "uploaded.db") || !strcmp(ent->d_name, "uploaded.db-shm") || !strcmp(ent->d_name, "uploaded.db-wal")) { #endif string fname = path; int rstat; #ifdef _WIN32 char dname[TQSL_MAX_PATH_LEN]; wcstombs(dname, ent->d_name, TQSL_MAX_PATH_LEN); fname = fname + "/" + dname; wchar_t* wfname = utf8_to_wchar(fname.c_str()); tqslTrace("remove_db", "unlinking %s", fname.c_str()); rstat = _wunlink(wfname); free_wchar(wfname); #else fname = fname + "/" + ent->d_name; tqslTrace("remove_db", "unlinking %s", fname.c_str()); rstat = unlink(fname.c_str()); #endif if (rstat < 0) { tqslTrace("remove_db", "can't unlink %s: %s", fname.c_str(), strerror(errno)); } } } #ifdef _WIN32 _wclosedir(dir); #else closedir(dir); #endif } return; } // Open the uploaded database static bool open_db(TQSL_CONVERTER *conv, bool readonly) { bool dbinit_cleanup = false; bool dblocked = false; int dbret; bool triedRemove = false; bool triedDelete = false; conv->dbpath = strdup(tQSL_BaseDir); #ifndef _WIN32 // Clean up junk in that directory DIR *dir = opendir(conv->dbpath); if (dir != NULL) { struct dirent *ent; while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; struct stat s; // If it's a symlink pointing to itself, remove it. string fname = conv->dbpath; fname += "/"; fname += ent->d_name; if (stat(fname.c_str(), &s)) { if (errno == ELOOP) { #ifdef _WIN32 _wunlink(ConvertFromUtf8ToUtf16(fname.c_str())); #else unlink(fname.c_str()); #endif } } } closedir(dir); } #endif string logpath = conv->dbpath; #ifdef _WIN32 logpath += "\\dberr.log"; wchar_t* wlogpath = utf8_to_wchar(logpath.c_str()); conv->errfile = _wfopen(wlogpath, L"wb"); free_wchar(wlogpath); #else logpath += "/dberr.log"; conv->errfile = fopen(logpath.c_str(), "wb"); #endif reopen: while(1) { // Open the database string dbfilename = conv->dbpath; #ifdef _WIN32 dbfilename += "\\uploaded.db"; #else dbfilename += "/uploaded.db"; #endif tqslTrace("open_db", "Opening the database at %s", dbfilename.c_str()); if ((dbret = sqlite3_open_v2(dbfilename.c_str(), &conv->seendb, SQLITE_OPEN_READWRITE, NULL)) != SQLITE_OK) { /* // Tried looking for ENOENT here, but that's not returned. CANTOPEN doesn't have any detail provided. */ if (SQLITE_CANTOPEN == dbret) { tqslTrace("open_db", "DB not found, making a new one"); dbret = sqlite3_open_v2(dbfilename.c_str(), &conv->seendb, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL); if (SQLITE_OK == dbret) { const char *sql = "DROP TABLE IF EXISTS QSOs;" "CREATE TABLE QSOs(tContact TEXT, QTH TEXT);" "CREATE UNIQUE INDEX IF NOT EXISTS tc ON QSOs(tContact);"; char *err_msg; dbret = sqlite3_exec(conv->seendb, sql, 0, 0, &err_msg); if (SQLITE_OK != dbret) { tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "DB Error %s - %s", sqlite3_errmsg(conv->seendb), err_msg); tqslTrace("open_db", "Error creating table: %s", tQSL_CustomError); break; } else { close_db(conv); tQSL_Error = TQSL_NEW_UPLOAD_DB; return false; } } // Fall through so this doesn't repeat dbinit_cleanup = true; break; } // can't open the db if (!triedRemove) { tqslTrace("open_db", "can't open, removing %s errno %d", sqlite3_errmsg(conv->seendb), errno); remove_db(conv->dbpath); triedRemove = true; continue; } tqslTrace("open_db", "create failed with %s errno %d", sqlite3_errmsg(conv->seendb), errno); if (conv->errfile) fprintf(conv->errfile, "create failed with %s errno %d", sqlite3_errmsg(conv->seendb), errno); dbinit_cleanup = true; break; } else { // Opened OK. Let's make a database table just in case const char *sql = "CREATE TABLE IF NOT EXISTS QSOs(tContact TEXT, QTH TEXT);" "CREATE UNIQUE INDEX IF NOT EXISTS tc ON QSOs(tContact);"; char *err_msg; dbret = sqlite3_exec(conv->seendb, sql, 0, 0, &err_msg); if (SQLITE_OK != dbret) { if (SQLITE_BUSY == dbret) { dbinit_cleanup = true; dblocked = true; break; } // Something is just not right. if (!triedRemove) { tqslTrace("open_db", "can't create tables, error %s - %s errno %d", err_msg, sqlite3_errmsg(conv->seendb), errno); sqlite3_close(conv->seendb); remove_db(conv->dbpath); triedRemove = true; continue; } } // is it really a DB? Try an get dbret = sqlite3_exec(conv->seendb, "SELECT * FROM QSOs LIMIT 1;", NULL, NULL, NULL); if (SQLITE_OK == dbret) { sqlite3_exec(conv->seendb, "PRAGMA journal_mode=WAL;", NULL, NULL, NULL); sqlite3_exec(conv->seendb, "CREATE UNIQUE INDEX IF NOT EXISTS tc ON QSOs(tContact);", NULL, NULL, NULL); break; // All OK } if (SQLITE_BUSY == dbret) { dbinit_cleanup = true; dblocked = true; break; } // probably SQLITE_NOTADB here. Kill it. if (!triedRemove) { tqslTrace("open_db", "can't open, removing %s errno %d", sqlite3_errmsg(conv->seendb), errno); sqlite3_close(conv->seendb); remove_db(conv->dbpath); triedRemove = true; continue; } dbinit_cleanup = true; break; } } if (dbinit_cleanup) { tqslTrace("open_db", "DB open failed, triedDelete=%d", triedDelete); tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; if (dblocked) { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "dblocked"); } else { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "%s: %s", sqlite3_errmsg(conv->seendb), strerror(errno)); } tqslTrace("open_db", "Error opening db: %s", tQSL_CustomError); conv->txn = false; if (conv->db_open) { close_db(conv); } if (conv->errfile) fclose(conv->errfile); conv->errfile = NULL; // Handle case where the database is just broken if ((SQLITE_NOTADB == dbret) && !triedDelete) { tqslTrace("open_db", "Not a database file. Removing db"); remove_db(conv->dbpath); triedDelete = true; goto reopen; } conv->db_open = false; return false; } if (!readonly) { conv->txn = true; dbret = sqlite3_exec(conv->seendb, "BEGIN;", NULL, NULL, NULL); if (SQLITE_OK != dbret) { tqslTrace("open_db", "Can't start transaction!"); } } conv->db_open = true; return true; } static const char* get_ident_rec(TQSL_CONVERTER *conv) { int major = 0, minor = 0, config_major = 0, config_minor = 0; tqsl_getVersion(&major, &minor); tqsl_getConfigVersion(&config_major, &config_minor); char temp[512]; static char ident[512]; snprintf(temp, sizeof temp, "%s Lib: V%d.%d Config: V%d.%d AllowDupes: %s", conv->appName ? conv->appName : "Unknown", major, minor, config_major, config_minor, conv->allow_dupes ? "true" : "false"); temp[sizeof temp - 1] = '\0'; int len = strlen(temp); snprintf(ident, sizeof ident, "%s\n", len, temp); ident[sizeof ident - 1] = '\0'; conv->need_ident_rec = false; return ident; } static const char* get_station_rec(TQSL_CONVERTER *conv) { conv->need_station_rec = false; const char *tStation = tqsl_getGABBItSTATION(conv->loc, conv->loc_uid, conv->cert_uid); tqsl_getCertificateSerialExt(conv->certs[conv->cert_idx], conv->serial, sizeof conv->serial); tqsl_getCertificateCallSign(conv->certs[conv->cert_idx], conv->callsign, sizeof conv->callsign); tqsl_getCertificateDXCCEntity(conv->certs[conv->cert_idx], &conv->dxcc); return tStation; } static bool set_tagline(TQSL_CONVERTER *conv, const char *tag) { if (conv->taglines.find(tag) != conv->taglines.end()) { conv->err_tag_line = conv->taglines[tag]; return true; } return false; } static void parse_adif_qso(TQSL_CONVERTER *conv, int *saveErr, TQSL_ADIF_GET_FIELD_ERROR *stat) { int cstat = 0; conv->taglines.clear(); conv->err_tag_line = 0; while (1) { tqsl_adifFieldResults result; conv->taglines[result.name] = result.line_no; if (tqsl_getADIFField(conv->adif, &result, stat, adif_qso_record_fields, notypes, adif_allocate)) break; if (*stat != TQSL_ADIF_GET_FIELD_SUCCESS && *stat != TQSL_ADIF_GET_FIELD_NO_NAME_MATCH) break; if (!strcasecmp(result.name, "eor")) break; char *resdata = reinterpret_cast(result.data); // Strip leading whitespace if (resdata) { while (isspace(*resdata)) resdata++; // Strip trailing whitespace char *end = resdata + strlen(resdata) - 1; while (isspace(*end)) *end-- = '\0'; } if (!strcasecmp(result.name, "CALL") && resdata) { tqsl_strtoupper(resdata); conv->rec.callsign_set = true; strncpy(conv->rec.callsign, resdata, sizeof conv->rec.callsign); } else if (!strcasecmp(result.name, "BAND") && resdata) { conv->rec.band_set = true; strncpy(conv->rec.band, resdata, sizeof conv->rec.band); } else if (!strcasecmp(result.name, "MODE") && resdata) { conv->rec.mode_set = true; strncpy(conv->rec.mode, resdata, sizeof conv->rec.mode); } else if (!strcasecmp(result.name, "SUBMODE") && resdata) { strncpy(conv->rec.submode, resdata, sizeof conv->rec.submode); } else if (!strcasecmp(result.name, "FREQ") && resdata) { conv->rec.band_set = true; strncpy(conv->rec.freq, fix_freq(resdata), sizeof conv->rec.freq); if (atof(conv->rec.freq) == 0.0) conv->rec.freq[0] = '\0'; } else if (!strcasecmp(result.name, "FREQ_RX") && resdata) { strncpy(conv->rec.rxfreq, fix_freq(resdata), sizeof conv->rec.rxfreq); if (atof(conv->rec.rxfreq) == 0.0) conv->rec.rxfreq[0] = '\0'; } else if (!strcasecmp(result.name, "BAND_RX") && resdata) { strncpy(conv->rec.rxband, resdata, sizeof conv->rec.rxband); } else if (!strcasecmp(result.name, "SAT_NAME") && resdata) { // Two-Line Elements (TLEs) call this AO-07, LoTW wants AO-7. if (!strcasecmp(resdata, "AO-07")) strncpy(conv->rec.satname, "AO-7", sizeof conv->rec.satname); else strncpy(conv->rec.satname, resdata, sizeof conv->rec.satname); } else if (!strcasecmp(result.name, "PROP_MODE") && resdata) { strncpy(conv->rec.propmode, resdata, sizeof conv->rec.propmode); } else if (!strcasecmp(result.name, "QSO_DATE") && resdata) { conv->rec.date_set = true; cstat = tqsl_initDate(&(conv->rec.date), resdata); if (cstat) *saveErr = tQSL_Error; } else if (!strcasecmp(result.name, "TIME_ON") && resdata) { conv->rec.time_set = true; cstat = tqsl_initTime(&(conv->rec.time), resdata); if (cstat) *saveErr = tQSL_Error; if (conv->ignore_secs) conv->rec.time.second = 0; } else if (!strcasecmp(result.name, "MY_CNTY") && resdata) { char *p = strstr(resdata, ","); // Find the comma in "VA,Fairfax" if (p) { *p++ = '\0'; strncpy(conv->rec.my_cnty_state, resdata, sizeof conv->rec.my_cnty_state); while (isspace(*p)) p++; // Skip spaces and comma strncpy(conv->rec.my_county, p, sizeof conv->rec.my_county); } else { strncpy(conv->rec.my_county, resdata, sizeof conv->rec.my_county); } } else if (!strcasecmp(result.name, "MY_COUNTRY") && resdata) { strncpy(conv->rec.my_country, resdata, sizeof conv->rec.my_country); } else if (!strcasecmp(result.name, "MY_CQ_ZONE") && resdata) { char *endptr; long zone = strtol(resdata, &endptr, 10); if (*endptr == '\0') { // If the conversion was correct snprintf(conv->rec.my_cq_zone, sizeof conv->rec.my_cq_zone, "%ld", zone); } else { // It wasn't a valid number strncpy(conv->rec.my_cq_zone, resdata, sizeof conv->rec.my_cq_zone); } } else if (!strcasecmp(result.name, "MY_DXCC") && resdata) { conv->rec.my_dxcc = strtol(resdata, NULL, 10); } else if (!strcasecmp(result.name, "MY_GRIDSQUARE") && resdata) { strncpy(conv->rec.my_gridsquare, resdata, sizeof conv->rec.my_gridsquare); } else if (!strcasecmp(result.name, "MY_IOTA") && resdata) { strncpy(conv->rec.my_iota, resdata, sizeof conv->rec.my_iota); } else if (!strcasecmp(result.name, "MY_ITU_ZONE") && resdata) { char *endptr; long zone = strtol(resdata, &endptr, 10); if (*endptr == '\0') { // If the conversion was correct snprintf(conv->rec.my_itu_zone, sizeof conv->rec.my_itu_zone, "%ld", zone); } else { // It wasn't a valid number strncpy(conv->rec.my_itu_zone, resdata, sizeof conv->rec.my_itu_zone); } } else if (!strcasecmp(result.name, "MY_STATE") && resdata) { strncpy(conv->rec.my_state, resdata, sizeof conv->rec.my_state); } else if (!strcasecmp(result.name, "MY_VUCC_GRIDS") && resdata) { strncpy(conv->rec.my_vucc_grids, resdata, sizeof conv->rec.my_vucc_grids); } else if (!strcasecmp(result.name, "OPERATOR") && resdata) { // Only use the OPERATOR field if it looks like a callsign tqsl_strtoupper(resdata); string op(resdata); if (!conv->ignore_calls && checkCallSign(op)) { strncpy(conv->rec.my_operator, resdata, sizeof conv->rec.my_operator); conv->rec.my_operator[TQSL_CALLSIGN_MAX] = '\0'; } #ifdef USE_OWNER_CALLSIGN } else if (!strcasecmp(result.name, "OWNER_CALLSIGN") && resdata) { // Only use the OWNER_CALLSIGN field if it looks like a callsign tqsl_strtoupper(resdata); string op(resdata); if (!conv->ignore_calls && checkCallSign(op)) { strncpy(conv->rec.my_owner, resdata, sizeof conv->rec.my_owner); } #endif } else if (!strcasecmp(result.name, "STATION_CALLSIGN") && resdata) { // Only use the STATION_CALLSIGN field if it looks like a callsign tqsl_strtoupper(resdata); string op(resdata); if (!conv->ignore_calls && checkCallSign(op)) { strncpy(conv->rec.my_call, resdata, sizeof conv->rec.my_call); } } else { tqslTrace("parse_adif_qso", "Unknown ADIF field %s", result.name); } if (*stat == TQSL_ADIF_GET_FIELD_SUCCESS) { conv->rec_text += string(reinterpret_cast(result.name)) + ": "; if (resdata) conv->rec_text += string(resdata); conv->rec_text += "\n"; } if (result.data) delete[] result.data; } return; } static int check_station(TQSL_CONVERTER *conv, const char *field, char *my, size_t len, const char *errfmt, bool update) { // // UPDATE is a boolean that when a change is made, that change // is propagated to the downstream values. STATE -> COUNTY and STATE->ZONES // char val[256]; char label[256]; bool provinceFixed = false; bool oblastFixed = false; // CA_PROVINCE can be QC but TQSL lookup expects PQ if (!strcasecmp(field, "CA_PROVINCE") && !strcasecmp(my, "QC")) { provinceFixed = true; strncpy(my, "PQ", len); } // RU_OBLAST can be YR but TQSL lookup expects JA if (!strcasecmp(field, "RU_OBLAST") && !strcasecmp(my, "YR")) { oblastFixed = true; strncpy(my, "JA", len); } // RU_OBLAST can be YN but TQSL lookup expects JN if (!strcasecmp(field, "RU_OBLAST") && !strcasecmp(my, "YN")) { oblastFixed = true; strncpy(my, "JN", len); } if (my[0] && !tqsl_getLocationField(conv->loc, field, val, sizeof val) && !tqsl_getLocationFieldLabel(conv->loc, field, label, sizeof label)) { if (!strcasecmp(my, label)) { // Label is correct, ADIF is not strncpy(my, val, len); // So use the value } if (strcasecmp(my, val)) { if (conv->location_handling == TQSL_LOC_UPDATE) { int res = tqsl_setLocationField(conv->loc, field, my); // -1 means trying to set a value that is not in the enumeration if (res == -1) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, errfmt, my, val); tQSL_Error = TQSL_LOCATION_MISMATCH | 0x1000; set_tagline(conv, field); return 1; } // -2 means that the label matched, so use that if (res == -2) { strncpy(my, tQSL_CustomError, len); } if (update) tqsl_updateStationLocationCapture(conv->loc); conv->newstation = true; } else if (strlen(val) > 0) { conv->rec_done = true; if (provinceFixed) { strncpy(my, "QC", len); } if (oblastFixed) { strncpy(my, "YR", len); } snprintf(tQSL_CustomError, sizeof tQSL_CustomError, errfmt, val, my); tQSL_Error = TQSL_LOCATION_MISMATCH; set_tagline(conv, field); return 1; } else { tqsl_setLocationField(conv->loc, field, my); if (update) tqsl_updateStationLocationCapture(conv->loc); conv->newstation = true; } } } return 0; // OK } DLLEXPORT const char* CALLCONVENTION tqsl_getConverterGABBI(tQSL_Converter convp) { TQSL_CONVERTER *conv; char signdata[1024]; int cstat = 0; if (!(conv = check_conv(convp))) return 0; if (conv->need_ident_rec) { return get_ident_rec(conv); } if (!conv->allow_dupes && !conv->db_open) { if (!open_db(conv, false)) { // If can't open dupes DB return 0; } } TQSL_ADIF_GET_FIELD_ERROR stat; if (conv->rec_done) { conv->rec_done = false; conv->clearRec(); int saveErr = 0; if (conv->adif) { parse_adif_qso(conv, &saveErr, &stat); if (saveErr) { tQSL_Error = saveErr; conv->rec_done = true; return 0; } if (stat == TQSL_ADIF_GET_FIELD_EOF) return 0; if (stat != TQSL_ADIF_GET_FIELD_SUCCESS) { tQSL_ADIF_Error = stat; tQSL_Error = TQSL_ADIF_ERROR; return 0; } conv->err_tag_line = 0; // ADIF record is complete. See if we need to infer the BAND fields. if (conv->rec.band[0] == 0) strncpy(conv->rec.band, tqsl_infer_band(conv->rec.freq), sizeof conv->rec.band); if (conv->rec.rxband[0] == 0) strncpy(conv->rec.rxband, tqsl_infer_band(conv->rec.rxfreq), sizeof conv->rec.rxband); // Normalize the DXCC country if (conv->rec.my_country[0] != 0) { int num_dxcc = 0; tqsl_getNumDXCCEntity(&num_dxcc); const char *entity; int ent_num; for (int i = 0; i < num_dxcc; i++) { tqsl_getDXCCEntity(i, &ent_num, &entity); if (strcasecmp(entity, conv->rec.my_country) == 0) { // Consistent DXCC ? if (conv->rec.my_dxcc == 0) { conv->rec.my_dxcc = ent_num; } else { // MY_DXCC and MY_COUNTRY do not match. Report this. if (conv->rec.my_dxcc != ent_num) { conv->rec_done = true; const char *d1; tqsl_getDXCCEntityName(conv->rec.my_dxcc, &d1); snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "DXCC Entity|%s (%d)|%s (%d)", d1, conv->rec.my_dxcc, conv->rec.my_country, i); tQSL_Error = TQSL_CERT_MISMATCH; return 0; } } break; } } } // Normalize the grids if (conv->rec.my_vucc_grids[0] != 0) { strncpy(conv->rec.my_gridsquare, conv->rec.my_vucc_grids, TQSL_GRID_MAX); } // Normalize callsign // Priority - STATION_CALLSIGN, then OPERATOR, then OWNER_CALLSIGN // my_call has STATION_CALLSIGN already. if (!conv->ignore_calls && conv->rec.my_call[0] == '\0' && conv->rec.my_operator[0] != 0) { // OPERATOR set strncpy(conv->rec.my_call, conv->rec.my_operator, TQSL_CALLSIGN_MAX); } #ifdef USE_OWNER_CALLSIGN if (!conv->ignore_calls && conv->rec.my_call[0] == '\0' && conv->rec.my_owner[0] != 0) { // OWNER_CALLSIGN set strncpy(conv->rec.my_call, conv->rec.my_owner, TQSL_CALLSIGN_MAX); } #endif if (conv->location_handling == TQSL_LOC_UPDATE && conv->rec.my_call[0] != '\0') { // If any of these strncpy(conv->callsign, conv->rec.my_call, sizeof conv->callsign); // got a callsign } } else if (conv->cab) { TQSL_CABRILLO_ERROR_TYPE stat; do { tqsl_cabrilloField field; if (tqsl_getCabrilloField(conv->cab, &field, &stat)) return 0; if (stat == TQSL_CABRILLO_NO_ERROR || stat == TQSL_CABRILLO_EOR) { // Field found if (!strcasecmp(field.name, "CALL")) { conv->rec.callsign_set = true; strncpy(conv->rec.callsign, field.value, sizeof conv->rec.callsign); } else if (!strcasecmp(field.name, "BAND")) { conv->rec.band_set = true; strncpy(conv->rec.band, field.value, sizeof conv->rec.band); } else if (!strcasecmp(field.name, "MODE")) { conv->rec.mode_set = true; strncpy(conv->rec.mode, field.value, sizeof conv->rec.mode); } else if (!strcasecmp(field.name, "FREQ")) { conv->rec.band_set = true; strncpy(conv->rec.freq, field.value, sizeof conv->rec.freq); } else if (!strcasecmp(field.name, "QSO_DATE")) { conv->rec.date_set = true; cstat = tqsl_initDate(&(conv->rec.date), field.value); if (cstat) saveErr = tQSL_Error; } else if (!strcasecmp(field.name, "TIME_ON")) { conv->rec.time_set = true; cstat = tqsl_initTime(&(conv->rec.time), field.value); if (conv->ignore_secs) conv->rec.time.second = 0; if (cstat) saveErr = tQSL_Error; } else if (!conv->ignore_calls && !strcasecmp(field.name, "MYCALL")) { strncpy(conv->rec.my_call, field.value, sizeof conv->rec.my_call); tqsl_strtoupper(conv->rec.my_call); } if (conv->rec_text != "") conv->rec_text += "\n"; conv->rec_text += string(field.name) + ": " + field.value; } } while (stat == TQSL_CABRILLO_NO_ERROR); if (saveErr) tQSL_Error = saveErr; if (saveErr || stat != TQSL_CABRILLO_EOR) { conv->rec_done = true; return 0; } } else { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "Converter not initialized", sizeof tQSL_CustomError); tqslTrace("tqsl_getConverterGABBI", "Converter not initialized"); return 0; } } // Does the QSO have the basic required elements? if (!conv->rec.callsign_set) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid contact - QSO does not specify a Callsign"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (!conv->rec.band_set) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid contact - QSO does not specify a band or frequency"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (!conv->rec.mode_set) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid contact - QSO does not specify a mode"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (!conv->rec.date_set) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid contact - QSO does not specify a date"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (!conv->rec.time_set) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid contact - QSO does not specify a time"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } // Check QSO date against user-specified date range. if (tqsl_isDateValid(&(conv->rec.date))) { if (tqsl_isDateValid(&(conv->start)) && tqsl_compareDates(&(conv->rec.date), &(conv->start)) < 0) { conv->rec_done = true; tQSL_Error = TQSL_DATE_OUT_OF_RANGE; set_tagline(conv, "QSO_DATE"); return 0; } if (tqsl_isDateValid(&(conv->end)) && tqsl_compareDates(&(conv->rec.date), &(conv->end)) > 0) { conv->rec_done = true; tQSL_Error = TQSL_DATE_OUT_OF_RANGE; set_tagline(conv, "QSO_DATE"); return 0; } } // Do field value mapping tqsl_strtoupper(conv->rec.callsign); if (!conv->allow_bad_calls) { if (!checkCallSign(conv->rec.callsign)) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid amateur CALL (%s)", conv->rec.callsign); set_tagline(conv, "CALL"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } } tqsl_strtoupper(conv->rec.band); tqsl_strtoupper(conv->rec.rxband); tqsl_strtoupper(conv->rec.mode); tqsl_strtoupper(conv->rec.submode); char val[256]; val[0] = '\0'; // Try to find the GABBI mode several ways. if (conv->rec.submode[0] != '\0') { char modeSub[256]; strncpy(modeSub, conv->rec.mode, sizeof modeSub); size_t left = sizeof modeSub - strlen(modeSub); strncat(modeSub, "%", left); left = sizeof modeSub - strlen(modeSub); strncat(modeSub, conv->rec.submode, left); if (tqsl_getADIFMode(modeSub, val, sizeof val)) { // mode%submode lookup failed // Try just the submode. if (tqsl_getADIFMode(conv->rec.submode, val, sizeof val)) { // bare submode failed if (tqsl_getADIFMode(conv->rec.mode, val, sizeof val)) { val[0] = '\0'; } } } } else { // Just a mode, no submode. Look that up. tqsl_getADIFMode(conv->rec.mode, val, sizeof val); } if (val[0] != '\0') strncpy(conv->rec.mode, val, sizeof conv->rec.mode); // Check field validities if (conv->modes.find(conv->rec.mode) == conv->modes.end()) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid MODE (%s)", conv->rec.mode); set_tagline(conv, "MODE"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (conv->bands.find(conv->rec.band) == conv->bands.end()) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid BAND (%s)", conv->rec.band); set_tagline(conv, "BAND"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (conv->rec.rxband[0] && (conv->bands.find(conv->rec.rxband) == conv->bands.end())) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid RX BAND (%s)", conv->rec.rxband); set_tagline(conv, "BAND_RX"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (conv->rec.freq[0] && strcmp(conv->rec.band, "SUBMM") && strcmp(conv->rec.band, tqsl_infer_band(conv->rec.freq))) { // Have a BAND and FREQ. // Frequency is not in that band - ignore it. conv->rec.freq[0] = '\0'; } if (conv->rec.rxfreq[0] && strcmp(conv->rec.rxband, "SUBMM") && strcmp(conv->rec.rxband, tqsl_infer_band(conv->rec.rxfreq))) { // Have a RX_BAND and RX_FREQ. Frequency is not in that band - ignore it. conv->rec.rxfreq[0] = '\0'; } if (conv->rec.propmode[0] != '\0' && conv->propmodes.find(conv->rec.propmode) == conv->propmodes.end()) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid PROP_MODE (%s)", conv->rec.propmode); set_tagline(conv, "PROP_MODE"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (conv->rec.satname[0] != '\0' && conv->satellites.find(conv->rec.satname) == conv->satellites.end()) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Invalid SAT_NAME (%s)", conv->rec.satname); set_tagline(conv, "SAT_NAME"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (!strcmp(conv->rec.propmode, "SAT") && conv->rec.satname[0] == '\0') { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "PROP_MODE = 'SAT' but no SAT_NAME"); set_tagline(conv, "PROP_MODE"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } if (strcmp(conv->rec.propmode, "SAT") && conv->rec.satname[0] != '\0') { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "SAT_NAME set but PROP_MODE is not 'SAT'"); set_tagline(conv, "SAT_NAME"); tQSL_Error = TQSL_CUSTOM_ERROR; return 0; } // Check cert if (conv->location_handling != TQSL_LOC_UPDATE && conv->ncerts <= 0) { conv->rec_done = true; tQSL_Error = TQSL_CERT_NOT_FOUND; return 0; } if (conv->location_handling == TQSL_LOC_UPDATE) { // Is the call right? if (conv->rec.my_call[0]) { strncpy(conv->callsign, conv->rec.my_call, sizeof conv->callsign); } } // For check-only case, need to check callsign now. if (conv->location_handling == TQSL_LOC_REPORT) { // Is the call right? if (conv->rec.my_call[0]) { // Update case handled above when switching certs if (strcmp(conv->rec.my_call, conv->callsign)) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Callsign|%s|%s", conv->callsign, conv->rec.my_call); if (!set_tagline(conv, "STATION_CALLSIGN")) set_tagline(conv, "OPERATOR"); tQSL_Error = TQSL_CERT_MISMATCH; return 0; } } } // Lookup cert - start with conv->dxcc int targetdxcc = conv->dxcc; // If we're in update mode, use the DXCC from the log if (conv->location_handling == TQSL_LOC_UPDATE) { if (conv->rec.my_dxcc != 0) { targetdxcc = conv->rec.my_dxcc; } } bool anyfound; int cidx = find_matching_cert(conv, targetdxcc, &anyfound); if (cidx < 0) { conv->rec_done = true; const char *entName; tqsl_getDXCCEntityName(targetdxcc, &entName); snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "%s|%s", conv->callsign, entName); tQSL_Error = TQSL_CERT_NOT_FOUND | 0x1000; if (anyfound) { tQSL_Error = TQSL_CERT_DATE_MISMATCH; set_tagline(conv, "QSO_DATE"); } if (conv->location_handling == TQSL_LOC_UPDATE) { if (conv->rec.my_call[0]) { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "%s|%s", conv->rec.my_call, entName); } } return 0; } if (cidx != conv->cert_idx) { // Switching certs if (conv->dxcc != -1) { conv->dxcc = targetdxcc; tqsl_setLocationCallSign(conv->loc, conv->callsign, conv->dxcc); // Set callsign and DXCC tqsl_setStationLocationCapturePage(conv->loc, 1); // Update to relevant fields tqsl_updateStationLocationCapture(conv->loc); } conv->cert_idx = cidx; if (conv->cert_uids[conv->cert_idx] == -1) { // Need to output tCERT, tSTATION conv->need_station_rec = true; // Need a new station record conv->cert_uid = conv->cert_uids[conv->cert_idx] = conv->next_cert_uid; conv->next_cert_uid++; return tqsl_getGABBItCERT(conv->certs[conv->cert_idx], conv->cert_uid); } else { conv->cert_uid = conv->cert_uids[conv->cert_idx]; } } if (conv->location_handling != TQSL_LOC_IGNORE) { // Care about MY_* fields // At this point, conv->certs[conv->cert_idx] has the certificate // conv->loc has the location. // First, refresh the certificate data tqsl_getCertificateSerialExt(conv->certs[conv->cert_idx], conv->serial, sizeof conv->serial); tqsl_getCertificateCallSign(conv->certs[conv->cert_idx], conv->callsign, sizeof conv->callsign); tqsl_getCertificateDXCCEntity(conv->certs[conv->cert_idx], &conv->dxcc); // Is the call right? if (conv->rec.my_call[0]) { // Update case handled above when switching certs if (strcmp(conv->rec.my_call, conv->callsign)) { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Callsign|%s|%s", conv->callsign, conv->rec.my_call); if (!set_tagline(conv, "STATION_CALLSIGN")) set_tagline(conv, "OPERATOR"); tQSL_Error = TQSL_CERT_MISMATCH; return 0; } } // Is the DXCC right? if (conv->rec.my_dxcc) { if (conv->rec.my_dxcc != conv->dxcc) { if (conv->location_handling == TQSL_LOC_UPDATE) { // Care about MY_* fields tqsl_setLocationField(conv->loc, "CALL", conv->callsign); tqsl_updateStationLocationCapture(conv->loc); } else { conv->rec_done = true; const char *d1, *d2; tqsl_getDXCCEntityName(conv->dxcc, &d1); tqsl_getDXCCEntityName(conv->rec.my_dxcc, &d2); snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "DXCC Entity|%s (%d)|%s (%d)", d1, conv->dxcc, d2, conv->rec.my_dxcc); set_tagline(conv, "MY_DXCC"); tQSL_Error = TQSL_CERT_MISMATCH; return 0; } } } conv->newstation = false; /* * Gridsquare handling - if the four-character grid matches the station loc * then don't complain; this is common for FT8/FT4 which have four char grids * and we don't want to reject every WSJT-X QSO just because the station * location has a higher precision grid. Similarly, if the Station Location has * a six-character grid and the log has 8, then just compare 6 for report mode. */ tqsl_getLocationField(conv->loc, "GRIDSQUARE", val, sizeof val); if (conv->rec.my_gridsquare[0] && !tqsl_getLocationField(conv->loc, "GRIDSQUARE", val, sizeof val)) { bool okgrid = true; unsigned int stnLen = strlen(val); unsigned int logLen = strlen(conv->rec.my_gridsquare); unsigned int compareLen = (stnLen < logLen ? stnLen : logLen); if (strstr(val, ",") || strstr(conv->rec.my_gridsquare, ",")) { // If it's a corner/edge vectorstngrids; vectorqsogrids; splitStr(val, stngrids, ','); splitStr(conv->rec.my_gridsquare, qsogrids, ','); size_t nstn = stngrids.size(); size_t nqso = qsogrids.size(); if (nstn != nqso) { okgrid = false; } else { sort(stngrids.begin(), stngrids.end()); sort(qsogrids.begin(), qsogrids.end()); for (size_t i = 0; i < nstn; i++) { if (stngrids[i] != qsogrids[i]) { compareLen = 99; // Doesn't match, so error out if appropriate break; } } compareLen = 0; // Matches. } } if (conv->location_handling == TQSL_LOC_UPDATE) { okgrid = (strcasecmp(conv->rec.my_gridsquare, val) == 0); } else { okgrid = (compareLen == 0 || strncasecmp(conv->rec.my_gridsquare, val, compareLen) == 0); } if (!okgrid) { if (conv->location_handling == TQSL_LOC_UPDATE) { tqsl_setLocationField(conv->loc, "GRIDSQUARE", conv->rec.my_gridsquare); conv->newstation = true; } else { if (val[0] == '\0') { // If station location has an empty grid tqsl_setLocationField(conv->loc, "GRIDSQUARE", conv->rec.my_gridsquare); conv->newstation = true; } else { conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Gridsquare|%s|%s", val, conv->rec.my_gridsquare); set_tagline(conv, "GRIDSQUARE"); tQSL_Error = TQSL_LOCATION_MISMATCH; return 0; } } } } switch (conv->dxcc) { case 6: // Alaska case 110: // Hawaii case 291: // Cont US if (check_station(conv, "US_STATE", conv->rec.my_state, sizeof conv->rec.my_state, "US State|%s|%s", true)) return 0; if (check_station(conv, "US_COUNTY", conv->rec.my_county, sizeof conv->rec.my_county, "US County|%s|%s", false)) return 0; break; case 1: // Canada if (check_station(conv, "CA_PROVINCE", conv->rec.my_state, sizeof conv->rec.my_state, "CA Province|%s|%s", true)) return 0; break; case 15: // Asiatic Russia case 54: // European Russia case 61: // FJL case 125: // Juan Fernandez case 151: // Malyj Vysotskij if (check_station(conv, "RU_OBLAST", conv->rec.my_state, sizeof conv->rec.my_state, "RU Oblast|%s|%s", true)) return 0; break; case 318: // China if (check_station(conv, "CN_PROVINCE", conv->rec.my_state, sizeof conv->rec.my_state, "CN Province|%s|%s", true)) return 0; break; case 150: // Australia if (check_station(conv, "AU_STATE", conv->rec.my_state, sizeof conv->rec.my_state, "AU State|%s|%s", true)) return 0; break; case 339: // Japan if (check_station(conv, "JA_PREFECTURE", conv->rec.my_state, sizeof conv->rec.my_state, "JA Prefecture|%s|%s", true)) return 0; if (check_station(conv, "JA_CITY_GUN_KU", conv->rec.my_county, sizeof conv->rec.my_county, "JA City/Gun/Ku|%s|%s", false)) return 0; break; case 5: // Finland if (check_station(conv, "FI_KUNTA", conv->rec.my_state, sizeof conv->rec.my_state, "FI Kunta|%s|%s", true)) return 0; break; } if (check_station(conv, "ITUZ", conv->rec.my_itu_zone, sizeof conv->rec.my_itu_zone, "ITU Zone|%s|%s", false)) return 0; if (check_station(conv, "CQZ", conv->rec.my_cq_zone, sizeof conv->rec.my_cq_zone, "CQ Zone|%s|%s", false)) return 0; if (check_station(conv, "IOTA", conv->rec.my_iota, sizeof conv->rec.my_iota, "IOTA|%s|%s", false)) return 0; if (conv->rec.my_cnty_state[0] != '\0') { char locstate[5]; tqsl_getLocationField(conv->loc, "US_STATE", locstate, sizeof locstate); if (strcasecmp(conv->rec.my_cnty_state, locstate)) { // County does not match state conv->rec_done = true; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "US County State|%s|%s", conv->rec.my_cnty_state, locstate); set_tagline(conv, "US_STATE"); tQSL_Error = TQSL_LOCATION_MISMATCH | 0x1000; return 0; } } if (conv->newstation) { conv->newstation = false; conv->loc_uid++; return get_station_rec(conv); } } // if ignoring MY_ fields if (conv->need_station_rec) { conv->loc_uid++; return get_station_rec(conv); } const char *grec = tqsl_getGABBItCONTACTData(conv->certs[conv->cert_idx], conv->loc, &(conv->rec), conv->loc_uid, signdata, sizeof(signdata)); if (grec) { conv->rec_done = true; if (!conv->allow_dupes) { char stnloc[128]; unsigned char qso[128]; if (tqsl_getLocationStationDetails(conv->loc, stnloc, sizeof stnloc)) { stnloc[0] = '\0'; } if (tqsl_getLocationQSODetails(conv->loc, reinterpret_cast (qso), sizeof qso)) { qso[0] = '\0'; } // Old-style Lookup uses signdata and cert serial number // append signing key serial strncat(signdata, conv->serial, sizeof(signdata) - strlen(signdata)-1); // Updated dupe database entry. Key is formed from // local callsign concatenated with the QSO details char dupekey[128]; snprintf(dupekey, sizeof dupekey, "%s%s", conv->callsign, qso); char * dupedata = NULL; int rc = get_dbrec(conv->seendb, signdata, &dupedata); if (rc == 0) { if (dupedata) free(dupedata); //lookup was successful; thus this is a duplicate. tqslTrace("tqsl_getConverterGABBI", "Duplicate QSO signdata=%s", signdata); tQSL_Error = TQSL_DUPLICATE_QSO; tQSL_CustomError[0] = '\0'; // delete the old record del_dbrec(conv->seendb, signdata); // Update this to the current format int dbput_err = put_dbrec(conv->seendb, dupekey, stnloc); if (0 != dbput_err) { strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); if (SQLITE_NOTADB == dbput_err) { close_db(conv); remove_db(conv->dbpath); free(conv->dbpath); } tQSL_Error = TQSL_DB_ERROR; return 0; } return 0; } else if (rc < 0) { //non-zero return, but not "not found" - thus error strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); if (SQLITE_NOTADB == rc) { // This isn't a database close_db(conv); remove_db(conv->dbpath); free(conv->dbpath); } tQSL_Error = TQSL_DB_ERROR; return 0; // could be more specific but there's very little the user can do at this point anyway } rc = get_dbrec(conv->seendb, dupekey, &dupedata); if (rc == 0) { //lookup was successful; thus this is a duplicate. tqslTrace("tqsl_getConverterGABBI", "Duplicate QSO dupekey=%s", dupekey); tQSL_Error = TQSL_DUPLICATE_QSO; // Save the original and new station location details so those can be provided // with an error by the caller // here dupedata = "GRIDSQUARE: ML01OX", stnloc "GRIDSQUARE: MLO2oa". // Station loc details like "CQZ: 5, GRIDSQUARE: FM18ju, ITUZ: 8, US_COUNTY: Fairfax, US_STATE: VA" // If the same, it's just a dupe. if (!strcmp(dupedata, stnloc)) { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "%s|%s", dupedata, stnloc); free(dupedata); return 0; } // Strip spaces string olds = dupedata; size_t found = olds.find(' '); while (found != string::npos) { olds.replace(found, 1, ""); found = olds.find(' '); } string news = stnloc; found = news.find(' '); while (found != string::npos) { news.replace(found, 1, ""); found = news.find(' '); } // Iterate the previous and current station locations. vectoroldstn; vectorqsostn; splitStr(olds, oldstn, ','); splitStr(news, qsostn, ','); // What we have now is the vectors having "GRIDSQUARE:ML10X" in each entry. Look for changes. bool changed = false; for (size_t i = 0; i < oldstn.size(); i++) { size_t cp = oldstn[i].find(":"); string key = oldstn[i].substr(0, cp+1); for (size_t j = 0; j < qsostn.size(); j++) { cp = qsostn[j].find(":"); string qsokey = qsostn[j].substr(0, cp+1); // Finally - is the key the same? if (key == qsokey) { if (oldstn[i] != qsostn[j] && key != oldstn[i]) { changed = true; } break; } } if (changed) break; } if (changed) { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "%s|%s", dupedata, stnloc); free(dupedata); return 0; } free(dupedata); // This is a valid update, delete the old one and let it update. del_dbrec(conv->seendb, dupekey); } else if (rc < 0) { //non-zero return, but not "not found" - thus error strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); if (SQLITE_NOTADB == rc) { // Not a database close_db(conv); remove_db(conv->dbpath); free(conv->dbpath); } tQSL_Error = TQSL_DB_ERROR; return 0; // could be more specific but there's very little the user can do at this point anyway } int dbput_err; dbput_err = put_dbrec(conv->seendb, dupekey, reinterpret_cast(stnloc)); if (0 != dbput_err) { strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); if (SQLITE_NOTADB == dbput_err) { close_db(conv); remove_db(conv->dbpath); free(conv->dbpath); } tQSL_Error = TQSL_DB_ERROR; return 0; } } } return grec; } // NOLINT(readability/fn_size) DLLEXPORT int CALLCONVENTION tqsl_getConverterCert(tQSL_Converter convp, tQSL_Cert *certp) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; if (certp == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *certp = conv->certs[conv->cert_idx]; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getConverterLine(tQSL_Converter convp, int *lineno) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; if (lineno == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (conv->err_tag_line) { *lineno = conv->err_tag_line; return 0; } if (conv->cab) return tqsl_getCabrilloLine(conv->cab, lineno); else if (conv->adif) return tqsl_getADIFLine(conv->adif, lineno); *lineno = 0; return 0; } DLLEXPORT const char* CALLCONVENTION tqsl_getConverterRecordText(tQSL_Converter convp) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 0; return conv->rec_text.c_str(); } DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowBadCall(tQSL_Converter convp, int allow) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; conv->allow_bad_calls = (allow != 0); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowDuplicates(tQSL_Converter convp, int allow) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; conv->allow_dupes = (allow != 0); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreSeconds(tQSL_Converter convp, int ignore) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; conv->ignore_secs = (ignore != 0); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreCallsigns(tQSL_Converter convp, int ignore) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; conv->ignore_calls = (ignore != 0); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setConverterAppName(tQSL_Converter convp, const char *app) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; if (!app) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } conv->appName = strdup(app); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setConverterQTHDetails(tQSL_Converter convp, int logverify) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; conv->location_handling = logverify; return 0; } DLLEXPORT int CALLCONVENTION tqsl_converterRollBack(tQSL_Converter convp) { TQSL_CONVERTER *conv; tqslTrace("tqsl_converterRollBack", NULL); if (!(conv = check_conv(convp))) return 1; if (!conv->db_open) return 0; if (conv->txn) sqlite3_exec(conv->seendb, "ROLLBACK;", NULL, NULL, NULL); conv->txn = false; return 0; } DLLEXPORT int CALLCONVENTION tqsl_converterCommit(tQSL_Converter convp) { TQSL_CONVERTER *conv; tqslTrace("tqsl_converterCommit", NULL); if (!(conv = check_conv(convp))) return 1; if (!conv->db_open) return 0; if (conv->txn) sqlite3_exec(conv->seendb, "COMMIT;", NULL, NULL, NULL); conv->txn = false; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecords(tQSL_Converter convp, char *key, char *data, int keylen) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; if (!conv->db_open) { if (!open_db(conv, true)) { // If can't open dupes DB return 1; } } // First time setup if (conv->bulk_read == NULL) { int rc = sqlite3_prepare_v2(conv->seendb, "SELECT * from QSOs;", 256, &conv->bulk_read, NULL); if (SQLITE_OK != rc) { return 1; } } // Get a record int rc = sqlite3_step(conv->bulk_read); if (SQLITE_DONE == rc) { sqlite3_finalize(conv->bulk_read); conv->bulk_read = NULL; return -1; // No more } if (SQLITE_ROW != rc) { fprintf(stderr, "SQL error in step: %s\n", sqlite3_errmsg(conv->seendb)); sqlite3_finalize(conv->bulk_read); conv->bulk_read = NULL; return 1; } const unsigned char* result = sqlite3_column_text(conv->bulk_read, 1); if (!result) { strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; return 1; } strncpy(data, reinterpret_cast(result), keylen); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecordsV2(tQSL_Converter convp, char *key, char *data, int keylen) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 1; if (!conv->db_open) { if (!open_db(conv, true)) { // If can't open dupes DB return 1; } } if (!conv->bulk_read) { int rc = sqlite3_prepare_v2(conv->seendb, "SELECT * from QSOs;", 256, &conv->bulk_read, NULL); if (SQLITE_OK != rc) { return 1; } } // Get a record int rc = sqlite3_step(conv->bulk_read); if (SQLITE_DONE == rc) { sqlite3_finalize(conv->bulk_read); return -1; // No more } if (SQLITE_ROW != rc) { sqlite3_finalize(conv->bulk_read); strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; return 1; } const unsigned char* rkey = sqlite3_column_text(conv->bulk_read, 0); if (!rkey) { strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; return 1; } const unsigned char* rdata = sqlite3_column_text(conv->bulk_read, 1); if (!rdata) { strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; return 1; } strncpy(key, reinterpret_cast(rkey), keylen); strncpy(data, reinterpret_cast(rdata), keylen); return 0; } DLLEXPORT int CALLCONVENTION tqsl_putDuplicateRecord(tQSL_Converter convp, const char *key, const char *data, int keylen) { TQSL_CONVERTER *conv; if (!(conv = check_conv(convp))) return 0; if (!conv->db_open) { if (!open_db(conv, false)) { // If can't open dupes DB return 0; // Head back - possibly new DB created } } if (key == NULL || data == NULL || keylen <= 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; close_db(conv); // The initial probe for a good dupes database uses this return 0; } int status = put_dbrec(conv->seendb, key, data); if (0 != status) { strncpy(tQSL_CustomError, sqlite3_errmsg(conv->seendb), sizeof tQSL_CustomError); tQSL_Error = TQSL_DB_ERROR; tQSL_Errno = errno; return 1; } return 0; } static bool hasValidCallSignChars(const string& call) { // Check for invalid characters if (call.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/") != string::npos) return false; // Need at least one letter if (call.find_first_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ") == string::npos) return false; // Need at least one number if (call.find_first_of("0123456789") == string::npos) return false; // Invalid callsign patterns // Starting with 0, Q // 1x other than 1A, 1M, 1S string first = call.substr(0, 1); string second = call.substr(1, 1); if (first == "0" || first == "Q" || #ifdef MARK_C7_4Y_INVALID (first == "C" && second == "7") || (first == "4" && second == "Y") || #endif (first == "1" && second != "A" && second != "M" && second != "S")) return false; return true; } static bool checkCallSign(const string& call) { if (!hasValidCallSignChars(call)) return false; if (call.length() < 3) return false; string::size_type idx, newidx; for (idx = 0; idx != string::npos; idx = newidx+1) { string s; newidx = call.find('/', idx); if (newidx == string::npos) s = call.substr(idx); else s = call.substr(idx, newidx - idx); if (s.length() == 0) return false; // Leading or trailing '/' is bad, bad! if (newidx == string::npos) break; } return true; } DLLEXPORT void CALLCONVENTION tqsl_removeUploadDatabase(void) { char *path = strdup(tQSL_BaseDir); remove_db(path); free(path); return; } tqsl-2.7.2/src/station_loc.cpp0000644000175000017500000000552314534122221016315 0ustar rmurphyrmurphy/*************************************************************************** station_loc.cpp - description ------------------- begin : Sat Dec 14 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "sysconfig.h" #endif #include #include #include #include #include "tqsllib.h" #include "tqslexc.h" using std::string; using std::ios; using std::cerr; using std::cout; using std::endl; int usage() { cerr << "Usage: station_loc callsign [dxcc]" << endl; exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { try { string call, dxcc; if (argc < 2) usage(); call = argv[1]; if (argc > 2) dxcc = argv[2]; if (tqsl_init()) throw tqslexc(); tQSL_Location loc; if (tqsl_initStationLocationCapture(&loc)) throw tqslexc(); if (tqsl_setStationLocationCapturePage(loc, 1)) throw tqslexc(); // We know that the first field of page 1 is always call and the 2nd is DXCC int nfield; tqsl_getNumLocationFieldListItems(loc, 0, &nfield); int i; for (i = 0; i < nfield; i++) { char buf[256]; if (tqsl_getLocationFieldListItem(loc, 0, i, buf, sizeof buf)) throw tqslexc(); if (!strcasecmp(buf, call.c_str())) break; } if (i == nfield) throw myexc(string("Can't init station location for call = ") + call); if (tqsl_setLocationFieldIndex(loc, 0, i)) throw tqslexc(); if (tqsl_updateStationLocationCapture(loc)) throw tqslexc(); if (dxcc != "") { int nfield; tqsl_getNumLocationFieldListItems(loc, 1, &nfield); //cerr << nfield << endl; for (i = 0; i < nfield; i++) { char buf[256]; if (tqsl_setLocationFieldIndex(loc, 1, i)) throw tqslexc(); if (tqsl_getLocationFieldCharData(loc, 1, buf, sizeof buf)) throw tqslexc(); //cerr << buf << endl; if (!strcasecmp(buf, dxcc.c_str())) break; } if (i == nfield) throw myexc(string("Can't init location for DXCC = ") + dxcc); if (tqsl_setLocationFieldIndex(loc, 1, i)) throw tqslexc(); } int dxcc_idx; if (tqsl_getLocationFieldIndex(loc, 1, &dxcc_idx)) throw tqslexc(); char buf[256]; if (tqsl_getLocationFieldListItem(loc, 1, dxcc_idx, buf, sizeof buf)) throw tqslexc(); string lname = call + "_auto"; if (tqsl_setStationLocationCaptureName(loc, lname.c_str())) throw tqslexc(); if (tqsl_saveStationLocationCapture(loc, 1)) throw tqslexc(); tqsl_endStationLocationCapture(&loc); cout << "Wrote station location for " << call << " - " << buf << endl; } catch(exception& x) { cerr << "Aborted: " << x.what() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } tqsl-2.7.2/src/openssl_cert.h0000644000175000017500000001157714534122221016152 0ustar rmurphyrmurphy/*************************************************************************** openssl_cert.h - description ------------------- begin : Tue May 14 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef OPENSSL_CERT_H #define OPENSSL_CERT_H /** \file * OpenSSL X509 certificate interface functions. */ #include #if (OPENSSL_VERSION_NUMBER == 0x10000003L) /* broken header file - fix by override */ #define i2d_ASN1_SET i2d_ASN1_SET_buggy #define d2i_ASN1_SET d2i_ASN1_SET_buggy #define ASN1_seq_unpack ASN1_seq_unpack_buggy #define ASN1_seq_pack ASN1_seq_pack_buggy #include #undef i2d_ASN1_SET #undef d2i_ASN1_SET #undef ASN1_seq_unpack #undef ASN1_seq_pack #ifdef __cplusplus extern "C" { #endif int i2d_ASN1_SET(void *a, unsigned char **pp, i2d_of_void *i2d, int ex_tag, int ex_class, int is_set); void *d2i_ASN1_SET(void *a, const unsigned char **pp, long length, d2i_of_void *d2i, void (*free_func)(void*), int ex_tag, // NOLINT(readability/casting) int ex_class); void *ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i, void (*free_func)(void* dummy)); unsigned char *ASN1_seq_pack(void *safes, i2d_of_void *i2d, unsigned char **buf, int *len); #ifdef __cplusplus } #endif #endif /* buggy openssl header */ #include #undef CLIENT_STATIC #ifndef LOTW_SERVER #define CLIENT_STATIC static #else #define CLIENT_STATIC #endif typedef STACK_OF(X509) TQSL_X509_STACK; typedef struct { char *name_buf; int name_buf_size; char *value_buf; int value_buf_size; } TQSL_X509_NAME_ITEM; namespace tqsllib { typedef enum { ROOTCERT = 0, CACERT, USERCERT } certtype; int tqsl_import_cert(const char *cert, certtype type, int(*cb)(int, const char *, void *), void *); int tqsl_get_pem_serial(const char *pem, long *serial); } // namespace tqsllib #if defined(LOTW_SERVER) || defined(OPENSSL_CERT_SOURCE) #ifdef __cplusplus extern "C" { #endif /// Loads a stack of certificates from the caller-supplied BIO /** See the OpenSSL documentation for background on BIO operations. * * Returns a pointer to an OpenSSL X509 stack, as used by * tqsl_ssl_verify_cert() */ CLIENT_STATIC TQSL_X509_STACK *tqsl_ssl_load_certs_from_BIO(BIO *in); /// Loads a stack of certificates from a file /** See tqsl_ssl_load_certs_from_BIO() */ CLIENT_STATIC TQSL_X509_STACK *tqsl_ssl_load_certs_from_file(const char *filename); /// Verifies a certificate using stacks of certificates /** The user supplies the X509 certificate to verify (the test certificate) * along with two stacks of certificates. The \c cacerts stack is a list * of certificates, one of which was used to sign the test certificate. * The \c rootcerts are considered "trusted." One of them must have been used * to sign either the test certificate itself or the CA cert that signed * the test certificate. * * Returns NULL if the test certificate is valid, otherwise returns an error message. */ CLIENT_STATIC const char *tqsl_ssl_verify_cert(X509 *cert, TQSL_X509_STACK *cacerts, TQSL_X509_STACK *rootcerts, int purpose, int (*cb)(int ok, X509_STORE_CTX *ctx), TQSL_X509_STACK **chain = 0); /// Retrieve a name entry from an X509 name object by name CLIENT_STATIC int tqsl_get_name_entry(X509_NAME *name, const char *obj_name, TQSL_X509_NAME_ITEM *name_item); /// Retrieve a name entry from an X509 cert's subject name by name CLIENT_STATIC int tqsl_cert_get_subject_name_entry(X509 *cert, const char *obj_name, TQSL_X509_NAME_ITEM *name_item); /// Convert an ASN date CLIENT_STATIC int tqsl_get_asn1_date(const ASN1_TIME *tm, tQSL_Date *date); /// Filter a list (stack) of certs based on (optional) call sign, qso date and issuer criteria /** Returns a (possibly empty) stack of certificates that match the criteria. Returns NULL * on error. * * The returned stack contains \em copies of the certs from the input stack. The input * stack is not altered. */ CLIENT_STATIC TQSL_X509_STACK *tqsl_filter_cert_list(TQSL_X509_STACK *sk, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int isvalid); CLIENT_STATIC EVP_PKEY *tqsl_new_rsa_key(int nbits); CLIENT_STATIC int tqsl_store_cert(const char *pem, X509 *cert, const char *certfile, int type, bool force, int (*cb)(int, const char *, void *), void *); CLIENT_STATIC int tqsl_write_adif_field(FILE *fp, const char *fieldname, char type, const unsigned char *value, int len); CLIENT_STATIC int tqsl_bio_write_adif_field(BIO *bio, const char *fieldname, char type, const unsigned char *value, int len); #ifdef __cplusplus } #endif #endif /* defined(LOTW_SERVER) || defined(OPENSSL_CERT_SOURCE) */ #endif /* OPENSSL_CERT_H */ tqsl-2.7.2/src/openssl_cert.cpp0000644000175000017500000054615414534122221016511 0ustar rmurphyrmurphy/*************************************************************************** openssl_cert.c - description ------------------- begin : Tue May 14 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ /* Routines to massage X.509 certs for tQSL. See openssl_cert.h for overview */ /* 2004-04-10 Fixed tqsl_add_bag_attribute error for OpenSSL > 0.96 (Thanks to Kenji, JJ1BDX for the fix) */ /* Portions liberally copied from OpenSSL's apps source code */ /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #define OPENSSL_CERT_SOURCE #define TQSLLIB_DEF #include #include #include #include #include #include #include #ifdef _WIN32 #include #define MKDIR(x, y) _wmkdir(x) #else #define MKDIR(x, y) mkdir(x, y) #include #include #endif #define OPENSSL_SUPPRESS_DEPRECATED // Suppress warnings for deprecated functions #include #if OPENSSL_VERSION_MAJOR >= 3 #include #include #endif #include #include #undef X509_NAME //http://www.mail-archive.com/openssl-users@openssl.org/msg59116.html #include #include #include #include #include #include #include /* Ugly workaround for Openssl 1.0 bug per: * http://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=2123 */ #if (OPENSSL_VERSION_NUMBER == 0x10000003L) #define i2d_ASN1_SET i2d_ASN1_SET_buggy #define d2i_ASN1_SET d2i_ASN1_SET_buggy #define ASN1_seq_unpack ASN1_seq_unpack_buggy #define ASN1_seq_pack ASN1_seq_pack_buggy #include #undef i2d_ASN1_SET #undef d2i_ASN1_SET #undef ASN1_seq_unpack #undef ASN1_seq_pack #ifdef __cplusplus extern "C" { #endif int i2d_ASN1_SET(void *a, unsigned char **pp, i2d_of_void *i2d, int ex_tag, int ex_class, int is_set); void *d2i_ASN1_SET(void *a, const unsigned char **pp, long length, d2i_of_void *d2i, void (*free_func)(void* p), int ex_tag, int ex_class); void *ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i, void (*free_func)(void* dummy)); unsigned char *ASN1_seq_pack(void *safes, i2d_of_void *i2d, unsigned char **buf, int *len); #ifdef __cplusplus } #endif #endif // OpenSSL v1.0 // Work with OpenSSL 1.1.0 and later #if OPENSSL_VERSION_NUMBER >= 0x10100000L #ifndef M_PKCS12_bag_type # define M_PKCS12_bag_type PKCS12_bag_type #endif #ifndef M_PKCS12_cert_bag_type # define M_PKCS12_cert_bag_type PKCS12_cert_bag_type #endif #ifndef M_PKCS12_crl_bag_type # define M_PKCS12_crl_bag_type PKCS12_cert_bag_type #endif #ifndef M_PKCS12_certbag2x509 # define M_PKCS12_certbag2x509 PKCS12_SAFEBAG_get1_cert #endif #ifndef M_PKCS12_decrypt_skey # define M_PKCS12_decrypt_skey PKCS12_decrypt_skey #endif #ifndef M_PKCS12_unpack_authsafes # define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes #endif #ifndef M_PKCS12_pack_authsafes # define M_PKCS12_pack_authsafes PKCS12_pack_authsafes #endif #ifndef PKCS12_get_attr # define PKCS12_get_attr PKCS12_SAFEBAG_get0_attr #endif #ifndef PKCS12_bag_type # define PKCS12_bag_type PKCS12_SAFEBAG_get_nid #endif #ifndef PKCS12_cert_bag_type # define PKCS12_cert_bag_type PKCS12_SAFEBAG_get_bag_nid #endif #if !defined(PKCS12_x5092certbag) && !defined(LIBRESSL_VERSION_NUMBER) # define PKCS12_x5092certbag PKCS12_SAFEBAG_create_cert #endif #ifndef PKCS12_x509crl2certbag # define PKCS12_x509crl2certbag PKCS12_SAFEBAG_create_crl #endif #ifndef X509_STORE_CTX_trusted_stack # define X509_STORE_CTX_trusted_stack X509_STORE_CTX_set0_trusted_stack #endif #ifndef X509_get_notAfter # define X509_get_notAfter X509_get0_notAfter #endif #ifndef X509_get_notBefore # define X509_get_notBefore X509_get0_notBefore #endif #if !defined (PKCS12_MAKE_SHKEYBAG) && !defined(LIBRESSL_VERSION_NUMBER) # define PKCS12_MAKE_SHKEYBAG PKCS12_SAFEBAG_create_pkcs8_encrypt #endif #ifndef X509_V_FLAG_CB_ISSUER_CHECK # define X509_V_FLAG_CB_ISSUER_CHECK 0x0 #endif #else # define ASN1_STRING_get0_data ASN1_STRING_data #endif #include #include #include #include #include #include #include "tqsllib.h" #include "tqslerrno.h" #include "xml.h" #include "winstrdefs.h" #ifdef _MSC_VER //is a visual studio compiler #include "windirent.h" #endif #define tqsl_malloc malloc #define tqsl_realloc realloc #define tqsl_calloc calloc #define tqsl_free free #define TQSL_OBJ_TO_API(x) (reinterpret_cast((x))) #define TQSL_API_TO_OBJ(x, type) ((type)(x)) #define TQSL_API_TO_CERT(x) TQSL_API_TO_OBJ((x), tqsl_cert *) #include "openssl_cert.h" using std::vector; using std::map; using std::set; using std::string; using std::ofstream; using std::ios; using std::endl; using std::exception; using tqsllib::XMLElement; using tqsllib::XMLElementList; #ifdef _WIN32 #define TQSL_OPEN_READ L"rb" #define TQSL_OPEN_WRITE L"wb" #define TQSL_OPEN_APPEND L"ab" #else #define TQSL_OPEN_READ "r" #define TQSL_OPEN_WRITE "w" #define TQSL_OPEN_APPEND "a" #endif #if (OPENSSL_VERSION_NUMBER & 0xfffff000) >= 0x10000000L #define uni2asc OPENSSL_uni2asc #define asc2uni OPENSSL_asc2uni #endif static char *tqsl_trim(char *buf); static int tqsl_check_parm(const char *p, const char *parmName); static TQSL_CERT_REQ *tqsl_copy_cert_req(TQSL_CERT_REQ *userreq); static TQSL_CERT_REQ *tqsl_free_cert_req(TQSL_CERT_REQ *req, int seterr); static char *tqsl_make_key_path(const char *callsign, char *path, int size); static int tqsl_make_key_list(vector< map > & keys); static int tqsl_find_matching_key(X509 *cert, EVP_PKEY **keyp, TQSL_CERT_REQ **crq, const char *password, int (*cb)(char *, int, void *), void *); static char *tqsl_make_cert_path(const char *filename, char *path, int size); static char *tqsl_make_backup_path(const char *filename, char *path, int size); static int tqsl_get_cert_ext(X509 *cert, const char *ext, unsigned char *userbuf, int *buflen, int *crit); CLIENT_STATIC int tqsl_get_asn1_date(const ASN1_TIME *tm, tQSL_Date *date); static char *tqsl_sign_base64_data(tQSL_Cert cert, char *b64data); static int fixed_password_callback(char *buf, int bufsiz, int verify, void *userdata); static int prompted_password_callback(char *buf, int bufsiz, int verify, void *userfunc); static int tqsl_check_crq_field(tQSL_Cert cert, char *buf, int bufsiz); static bool safe_strncpy(char *dest, const char *src, int size); static int tqsl_ssl_error_is_nofile(); static int tqsl_unlock_key(const char *pem, EVP_PKEY **keyp, const char *password, int (*cb)(char *, int, void *), void *); static int tqsl_replace_key(const char *callsign, const char *path, map& newfields, int (*cb)(int, const char *, void *), void *userdata); static int tqsl_self_signed_is_ok(int ok, X509_STORE_CTX *ctx); static int tqsl_expired_is_ok(int ok, X509_STORE_CTX *ctx); static int tqsl_clear_deleted(const char *callsign, const char *path, EVP_PKEY *cert_key); static int tqsl_key_exists(const char *callsign, EVP_PKEY *cert_key); static int tqsl_open_key_file(const char *path); static int tqsl_read_key(map& fields); static void tqsl_close_key_file(void); extern const char* tqsl_openssl_error(void); /* Private data structures */ typedef struct { long id; X509 *cert; EVP_PKEY *key; TQSL_CERT_REQ *crq; char *pubkey; char *privkey; unsigned char keyonly; } tqsl_cert; typedef struct { long id; X509 *cert; } tqsl_crq; static tqsl_cert * tqsl_cert_new(); static void tqsl_cert_free(tqsl_cert *p); static int tqsl_cert_check(tqsl_cert *p, bool needcert = true); struct tqsl_loadcert_handler { int type; int (*func)(const char *pem, X509 *x, int(*cb)(int type, const char *, void *), void *); }; static int tqsl_handle_root_cert(const char *, X509 *, int (*cb)(int, const char *, void *), void *); static int tqsl_handle_ca_cert(const char *, X509 *, int (*cb)(int, const char *, void *), void *); static int tqsl_handle_user_cert(const char *, X509 *, int (*cb)(int, const char *, void *), void *); static struct tqsl_loadcert_handler tqsl_loadcert_handlers[] = { { TQSL_CERT_CB_ROOT, &tqsl_handle_root_cert }, { TQSL_CERT_CB_CA, &tqsl_handle_ca_cert }, { TQSL_CERT_CB_USER, &tqsl_handle_user_cert } }; static const char *notypes[] = { "" }; /* static tqsl_adifFieldDefinitions tqsl_cert_file_fields[] = { { "TQSL_CERT", "", TQSL_ADIF_RANGE_TYPE_NONE, 0, 0, 0, NULL, NULL }, { "TQSL_CERT_USER", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, &tqsl_load_user_cert }, { "TQSL_CERT_CA", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, &tqsl_load_ca_cert }, { "TQSL_CERT_ROOT", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, &tqsl_load_root_cert }, }; */ static unsigned char tqsl_static_buf[2001]; static char ImportCall[256]; #if !defined(__APPLE__) && !defined(_WIN32) && !defined(__clang__) #pragma GCC diagnostic ignored "-Wformat-truncation" #endif static unsigned char * tqsl_static_alloc(size_t size) { if (size > sizeof tqsl_static_buf) return NULL; strncpy(reinterpret_cast(tqsl_static_buf), "", sizeof tqsl_static_buf); return tqsl_static_buf; } namespace tqsllib { int tqsl_import_cert(const char *data, certtype type, int(*cb)(int, const char *, void *), void *userdata) { BIO *bio; X509 *cert; int stat; struct tqsl_loadcert_handler *handler = &(tqsl_loadcert_handlers[type]); /* This is a certificate, supposedly. Let's make sure */ tqslTrace("tqsl_import_cert", NULL); bio = BIO_new_mem_buf(reinterpret_cast(const_cast(data)), strlen(data)); if (bio == NULL) { tqslTrace("tqsl_import_cert", "BIO mem buf error %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); BIO_free(bio); if (cert == NULL) { tqslTrace("tqsl_import_cert", "BIO read error, err=%s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } /* It's a certificate. Let's try to add it. Any errors will be * reported via the callback (if any) but will not be fatal unless * the callback says so. */ ImportCall[0] = '\0'; tQSL_ImportSerial = 0; stat = (*(handler->func))(data, cert, cb, userdata); X509_free(cert); if (stat) { if (tQSL_Error == TQSL_CERT_ERROR) { return 1; } if (cb != NULL) { stat = (*cb)(handler->type | TQSL_CERT_CB_RESULT | TQSL_CERT_CB_ERROR, tqsl_getErrorString_v(tQSL_Error), userdata); if (stat) { tqslTrace("tqsl_import_cert", "import error %d", tQSL_Error); return 1; } else { tqslTrace("tqsl_import_cert", "import error. Handler suppressed."); } } else { /* No callback -- any errors are fatal */ tqslTrace("tqsl_import_cert", "import error %d", tQSL_Error); return 1; } return stat; } strncpy(tQSL_ImportCall, ImportCall, sizeof tQSL_ImportCall); return 0; } int tqsl_get_pem_serial(const char *pem, long *serial) { BIO *bio; X509 *cert; tqslTrace("tqsl_get_pem_serial", NULL); if (tqsl_init()) return 1; if (pem == NULL || serial == NULL) { tqslTrace("tqsl_get_pem_serial", "arg error pem=0x%lx, serial=0x%lx", pem, serial); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } bio = BIO_new_mem_buf(reinterpret_cast(const_cast(pem)), strlen(pem)); if (bio == NULL) { tqslTrace("tqsl_get_pem_serial", "mem buf error %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); BIO_free(bio); if (cert == NULL) { tqslTrace("tqsl_get_pem_serial", "cert read error %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } *serial = ASN1_INTEGER_get(X509_get_serialNumber(cert)); return 0; } } // namespace tqsllib /********** PUBLIC API FUNCTIONS ***********/ DLLEXPORT int CALLCONVENTION tqsl_createCertRequest(const char *filename, TQSL_CERT_REQ *userreq, int (*pwcb)(char *pwbuf, int pwsize, void *), void *userdata) { TQSL_CERT_REQ *req = NULL; EVP_PKEY *key = NULL; X509_REQ *xr = NULL; X509_NAME *subj = NULL; int nid, len; int rval = 1; FILE *out = NULL; BIO *bio = NULL; const EVP_MD *digest = NULL; char buf[200]; char path[TQSL_MAX_PATH_LEN]; char *cp; const EVP_CIPHER *cipher = NULL; char *password; const char *type; tqslTrace("tqsl_createCertRequest", NULL); if (tqsl_init()) return 1; if (filename == NULL || userreq == NULL) { tqslTrace("tqsl_createCertRequest", "arg error filename=0x%lx, userreq=0x%lx", filename, userreq); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (userreq->signer != NULL && (!tqsl_cert_check(TQSL_API_TO_CERT(userreq->signer)) || TQSL_API_TO_CERT(userreq->signer)->key == NULL)) { tqslTrace("tqsl_createCertRequest", "arg error signer/key"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if ((req = tqsl_copy_cert_req(userreq)) == NULL) { tqslTrace("tqsl_createCertRequest", "Error copying %d", tQSL_Error); goto end; } /* Check parameters for validity */ tqsl_trim(req->providerName); tqsl_trim(req->providerUnit); tqsl_trim(req->name); if (tqsl_check_parm(req->name, "Name")) { tqslTrace("tqsl_createCertRequest", "check_parm Name"); goto end; } tqsl_trim(req->callSign); if (tqsl_check_parm(req->callSign, "Call Sign")) { tqslTrace("tqsl_createCertRequest", "check_parm Call Sign"); goto end; } tqsl_trim(req->address1); if (tqsl_check_parm(req->address1, "Address")) { tqslTrace("tqsl_createCertRequest", "check_parm Address1"); goto end; } tqsl_trim(req->address2); tqsl_trim(req->city); if (tqsl_check_parm(req->city, "City")) { tqslTrace("tqsl_createCertRequest", "check_parm City"); goto end; } tqsl_trim(req->state); tqsl_trim(req->country); if (tqsl_check_parm(req->country, "Country")) { tqslTrace("tqsl_createCertRequest", "check_parm Country"); goto end; } tqsl_trim(req->postalCode); tqsl_trim(req->emailAddress); if (tqsl_check_parm(req->emailAddress, "Email address")) { tqslTrace("tqsl_createCertRequest", "check_parm email"); goto end; } if ((cp = strchr(req->emailAddress, '@')) == NULL || strchr(cp, '.') == NULL) { strncpy(tQSL_CustomError, "Invalid email address", sizeof tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; tqslTrace("tqsl_createCertRequest", "check_parm email: %s %s", req->emailAddress, tQSL_CustomError); goto end; } if (!tqsl_isDateValid(&(req->qsoNotBefore))) { strncpy(tQSL_CustomError, "Invalid date (qsoNotBefore)", sizeof tQSL_CustomError); tqslTrace("tqsl_createCertRequest", "check_parm not before: %s %s", req->qsoNotBefore, tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; goto end; } if (!tqsl_isDateNull(&(req->qsoNotAfter))) { if (!tqsl_isDateValid(&(req->qsoNotAfter))) { strncpy(tQSL_CustomError, "Invalid date (qsoNotAfter)", sizeof tQSL_CustomError); tqslTrace("tqsl_createCertRequest", "check_parm not after: %s %s", req->qsoNotAfter, tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; goto end; } if (tqsl_compareDates(&(req->qsoNotAfter), &(req->qsoNotBefore)) < 0) { strncpy(tQSL_CustomError, "qsoNotAfter date is earlier than qsoNotBefore", sizeof tQSL_CustomError); tqslTrace("tqsl_createCertRequest", "check_parm not after: %s %s", req->qsoNotAfter, tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; goto end; } } /* Try opening the output stream */ #ifdef _WIN32 wchar_t* wfilename = utf8_to_wchar(filename); if ((out = _wfopen(wfilename, TQSL_OPEN_WRITE)) == NULL) { free_wchar(wfilename); #else if ((out = fopen(filename, TQSL_OPEN_WRITE)) == NULL) { #endif strncpy(tQSL_ErrorFile, filename, sizeof tQSL_ErrorFile); tqslTrace("tqsl_createCertRequest", "Open file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; goto end; } #ifdef _WIN32 free_wchar(wfilename); #endif if (fputs("\ntQSL certificate request\n\n", out) == EOF) { strncpy(tQSL_ErrorFile, filename, sizeof tQSL_ErrorFile); tqslTrace("tqsl_createCertRequest", "Write request file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; goto end; } tqsl_write_adif_field(out, "eoh", 0, NULL, 0); type = (req->signer != NULL) ? (req->renew ? "TQSL_CRQ_RENEWAL" : "TQSL_CRQ_ADDITIONAL") : "TQSL_CRQ_NEW"; int libmaj, libmin, configmaj, configmin; tqsl_getVersion(&libmaj, &libmin); tqsl_getConfigVersion(&configmaj, &configmin); snprintf(buf, sizeof buf, "TQSL: %d.%d.%d, Lib: V%d.%d, Config: %d.%d", TQSL_VERSION_MAJOR, TQSL_VERSION_MINOR, TQSL_VERSION_UPDATE, libmaj, libmin, configmaj, configmin); tqsl_write_adif_field(out, "TQSL_IDENT", 0, (unsigned char *)buf, -1); tqsl_write_adif_field(out, type, 0, NULL, 0); tqsl_write_adif_field(out, "TQSL_CRQ_PROVIDER", 0, (unsigned char *)req->providerName, -1); tqsl_write_adif_field(out, "TQSL_CRQ_PROVIDER_UNIT", 0, (unsigned char *)req->providerUnit, -1); tqsl_write_adif_field(out, "TQSL_CRQ_EMAIL", 0, (unsigned char *)req->emailAddress, -1); tqsl_write_adif_field(out, "TQSL_CRQ_NAME", 0, (unsigned char *)req->name, -1); tqsl_write_adif_field(out, "TQSL_CRQ_ADDRESS1", 0, (unsigned char *)req->address1, -1); tqsl_write_adif_field(out, "TQSL_CRQ_ADDRESS2", 0, (unsigned char *)req->address2, -1); tqsl_write_adif_field(out, "TQSL_CRQ_CITY", 0, (unsigned char *)req->city, -1); tqsl_write_adif_field(out, "TQSL_CRQ_STATE", 0, (unsigned char *)req->state, -1); tqsl_write_adif_field(out, "TQSL_CRQ_POSTAL", 0, (unsigned char *)req->postalCode, -1); tqsl_write_adif_field(out, "TQSL_CRQ_COUNTRY", 0, (unsigned char *)req->country, -1); snprintf(buf, sizeof buf, "%d", req->dxccEntity); tqsl_write_adif_field(out, "TQSL_CRQ_DXCC_ENTITY", 0, (unsigned char *)buf, -1); tqsl_convertDateToText(&(req->qsoNotBefore), buf, sizeof buf); tqsl_write_adif_field(out, "TQSL_CRQ_QSO_NOT_BEFORE", 0, (unsigned char *)buf, -1); if (!tqsl_isDateNull(&(req->qsoNotAfter))) { tqsl_convertDateToText(&(req->qsoNotAfter), buf, sizeof buf); tqsl_write_adif_field(out, "TQSL_CRQ_QSO_NOT_AFTER", 0, (unsigned char *)buf, -1); } /* Generate a new key pair */ if ((key = tqsl_new_rsa_key(1024)) == NULL) { tqslTrace("tqsl_createCertRequest", "key create error %d", tQSL_Error); goto end; } /* Make the X.509 certificate request */ if ((xr = X509_REQ_new()) == NULL) { tqslTrace("tqsl_createCertRequest", "req create error %s", tqsl_openssl_error()); goto err; } if (!X509_REQ_set_version(xr, 0L)) { tqslTrace("tqsl_createCertRequest", "version set error %s", tqsl_openssl_error()); goto err; } subj = X509_REQ_get_subject_name(xr); nid = OBJ_txt2nid("AROcallsign"); if (nid != NID_undef) X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, (unsigned char *)req->callSign, -1, -1, 0); nid = OBJ_txt2nid("commonName"); if (nid != NID_undef) X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, (unsigned char *)req->name, -1, -1, 0); nid = OBJ_txt2nid("emailAddress"); if (nid != NID_undef) X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, (unsigned char *)req->emailAddress, -1, -1, 0); X509_REQ_set_pubkey(xr, key); if ((digest = EVP_sha256()) == NULL) { tqslTrace("tqsl_createCertRequest", "evp_sha256 error %s", tqsl_openssl_error()); goto err; } if (!X509_REQ_sign(xr, key, digest)) { tqslTrace("tqsl_createCertRequest", "req_sign error %s", tqsl_openssl_error()); goto err; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_createCertRequest", "bio_new error %s", tqsl_openssl_error()); goto err; } if (!PEM_write_bio_X509_REQ(bio, xr)) { tqslTrace("tqsl_createCertRequest", "write_bio error %s", tqsl_openssl_error()); goto err; } len = static_cast(BIO_get_mem_data(bio, &cp)); tqsl_write_adif_field(out, "TQSL_CRQ_REQUEST", 0, (unsigned char *)cp, len); if (req->signer != NULL) { char *b64; char ibuf[256]; if ((b64 = tqsl_sign_base64_data(req->signer, cp)) == NULL) { fclose(out); tqslTrace("tqsl_createCertRequest", "tqsl_sign_base64 error %s", tqsl_openssl_error()); goto end; } tqsl_write_adif_field(out, "TQSL_CRQ_SIGNATURE", 0, (unsigned char *)b64, -1); tqsl_getCertificateIssuer(req->signer, ibuf, sizeof ibuf); tqsl_write_adif_field(out, "TQSL_CRQ_SIGNATURE_CERT_ISSUER", 0, (unsigned char *)ibuf, -1); snprintf(ibuf, sizeof ibuf, "%ld", ASN1_INTEGER_get(X509_get_serialNumber(TQSL_API_TO_CERT(req->signer)->cert))); tqsl_write_adif_field(out, "TQSL_CRQ_SIGNATURE_CERT_SERIAL", 0, (unsigned char *)ibuf, -1); } BIO_free(bio); bio = NULL; tqsl_write_adif_field(out, "eor", 0, NULL, 0); if (fclose(out) == EOF) { strncpy(tQSL_ErrorFile, filename, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_createCertRequest", "write error %d", errno); goto end; } out = NULL; /* Write the key to the key store */ if (!tqsl_make_key_path(req->callSign, path, sizeof path)) { tqslTrace("tqsl_createCertRequest", "make_key_path error %d", errno); goto end; } #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); if ((out = _wfopen(wpath, TQSL_OPEN_APPEND)) == NULL) { free_wchar(wpath); #else if ((out = fopen(path, TQSL_OPEN_APPEND)) == NULL) { #endif strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_createCertRequest", "opening file error %s", strerror(errno)); goto end; } #ifdef _WIN32 free_wchar(wpath); #endif tqsl_write_adif_field(out, "TQSL_CRQ_PROVIDER", 0, (unsigned char *)req->providerName, -1); tqsl_write_adif_field(out, "TQSL_CRQ_PROVIDER_UNIT", 0, (unsigned char *)req->providerUnit, -1); tqsl_write_adif_field(out, "TQSL_CRQ_EMAIL", 0, (unsigned char *)req->emailAddress, -1); tqsl_write_adif_field(out, "TQSL_CRQ_ADDRESS1", 0, (unsigned char *)req->address1, -1); tqsl_write_adif_field(out, "TQSL_CRQ_ADDRESS2", 0, (unsigned char *)req->address2, -1); tqsl_write_adif_field(out, "TQSL_CRQ_CITY", 0, (unsigned char *)req->city, -1); tqsl_write_adif_field(out, "TQSL_CRQ_STATE", 0, (unsigned char *)req->state, -1); tqsl_write_adif_field(out, "TQSL_CRQ_POSTAL", 0, (unsigned char *)req->postalCode, -1); tqsl_write_adif_field(out, "TQSL_CRQ_COUNTRY", 0, (unsigned char *)req->country, -1); tqsl_write_adif_field(out, "CALLSIGN", 0, (unsigned char *)req->callSign, -1); snprintf(buf, sizeof buf, "%d", req->dxccEntity); tqsl_write_adif_field(out, "TQSL_CRQ_DXCC_ENTITY", 0, (unsigned char *)buf, -1); tqsl_convertDateToText(&(req->qsoNotBefore), buf, sizeof buf); tqsl_write_adif_field(out, "TQSL_CRQ_QSO_NOT_BEFORE", 0, (unsigned char *)buf, -1); if (!tqsl_isDateNull(&(req->qsoNotAfter))) { tqsl_convertDateToText(&(req->qsoNotAfter), buf, sizeof buf); tqsl_write_adif_field(out, "TQSL_CRQ_QSO_NOT_AFTER", 0, (unsigned char *)buf, -1); } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_createCertRequest", "bio_new error %s", tqsl_openssl_error()); goto err; } password = const_cast(req->password); if (password == NULL && pwcb != NULL) { if ((*pwcb)(buf, TQSL_MAX_PW_LENGTH, userdata)) { tqslTrace("tqsl_createCertRequest", "password abort"); tQSL_Error = TQSL_OPERATOR_ABORT; goto end; } password = buf; } if (password != NULL && *password != '\0') { if ((cipher = EVP_des_ede3_cbc()) == NULL) { tqslTrace("tqsl_createCertRequest", "password error"); goto err; } len = strlen(password); } else { password = NULL; len = 0; } if (!PEM_write_bio_PrivateKey(bio, key, cipher, (unsigned char *)password, len, NULL, NULL)) { tqslTrace("tqsl_createCertRequest", "write priv key error %s", tqsl_openssl_error()); goto err; } len = static_cast(BIO_get_mem_data(bio, &cp)); tqsl_write_adif_field(out, "PRIVATE_KEY", 0, (unsigned char *)cp, len); BIO_free(bio); if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_createCertRequest", "bio_new error %s", tqsl_openssl_error()); goto err; } if (!PEM_write_bio_PUBKEY(bio, key)) { tqslTrace("tqsl_createCertRequest", "write pubkey %s", tqsl_openssl_error()); goto err; } len = static_cast(BIO_get_mem_data(bio, &cp)); tqsl_write_adif_field(out, "PUBLIC_KEY", 0, (unsigned char *)cp, len); BIO_free(bio); bio = NULL; tqsl_write_adif_field(out, "eor", 0, NULL, 0); if (fclose(out) == EOF) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_createCertRequest", "write file error %s", strerror(tQSL_Errno)); goto end; } out = NULL; rval = 0; goto end; err: tQSL_Error = TQSL_OPENSSL_ERROR; end: if (bio != NULL) BIO_free(bio); if (out != NULL) fclose(out); if (xr != NULL) X509_REQ_free(xr); if (key != NULL) EVP_PKEY_free(key); if (req != NULL) tqsl_free_cert_req(req, 0); return rval; } DLLEXPORT int CALLCONVENTION tqsl_getSelectedCertificate(tQSL_Cert *cert, const tQSL_Cert **certlist, int idx) { tqslTrace("tqsl_getSelectedCertificate", NULL); if (tqsl_init()) return 1; if (certlist == NULL || cert == NULL || idx < 0) { tqslTrace("tqsl_getSelectedCertificate", "arg error certlist=0x%lx, cert=0x%lx, idx=%d", certlist, cert, idx); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *cert = (*certlist)[idx]; return 0; } DLLEXPORT int CALLCONVENTION tqsl_isCertificateExpired(tQSL_Cert cert, int *status) { tqslTrace("tqsl_isCertificateExpired", NULL); if (tqsl_init()) return 1; if (cert == NULL || status == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_isCertificateExpired", "arg error cert=0x%lx status=0x%lx", cert, status); tQSL_Error = TQSL_ARGUMENT_ERROR; if (status) *status = false; return 1; } int keyonly; if (tqsl_getCertificateKeyOnly(cert, &keyonly) == 0 && keyonly) { *status = false; return 0; } long serial = 0; tqsl_getCertificateSerial(cert, &serial); int sts = tqsl_getCertificateStatus(serial); if (sts == TQSL_CERT_STATUS_EXP || sts == TQSL_CERT_STATUS_INV) { *status = true; return 0; } *status = false; /* Check for expired */ time_t t = time(0); struct tm *tm = gmtime(&t); tQSL_Date d; d.year = tm->tm_year + 1900; d.month = tm->tm_mon + 1; d.day = tm->tm_mday; const ASN1_TIME *ctm; if ((ctm = X509_get_notAfter(TQSL_API_TO_CERT(cert)->cert)) == NULL) { *status = true; return 0; } else { tQSL_Date cert_na; tqsl_get_asn1_date(ctm, &cert_na); if (tqsl_compareDates(&cert_na, &d) < 0) { *status = true; return 0; } } return 0; } static TQSL_X509_STACK *xcerts = NULL; DLLEXPORT int CALLCONVENTION tqsl_isCertificateSuperceded(tQSL_Cert cert, int *status) { char path[TQSL_MAX_PATH_LEN]; int i; X509 *x = NULL; char *cp; vector< map > keylist; vector< map >::iterator it; set superceded_certs; int len; bool superceded = false; char buf[256]; tqslTrace("tqsl_isCertificateSuperceded", NULL); if (tqsl_init()) return 1; if (cert == NULL || status == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_isCertificateSuperceded", "arg error cert=0x%lx, status=0x%lx", cert, status); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *status = false; int keyonly; if (tqsl_getCertificateKeyOnly(cert, &keyonly) == 0 && keyonly) { return 0; } long serial = 0; tqsl_getCertificateSerial(cert, &serial); if (tqsl_getCertificateStatus(serial) == TQSL_CERT_STATUS_SUP) { *status = true; tqslTrace("tqsl_isCertificateSuperceded", "returning true"); return 0; } /* Get the certs from the cert store */ tqsl_make_cert_path("user", path, sizeof path); if (xcerts == NULL) xcerts = tqsl_ssl_load_certs_from_file(path); if (xcerts == NULL) { if (tQSL_Error == TQSL_OPENSSL_ERROR) { tqslTrace("tqsl_isCertificateSuperceded", "openssl error loading certs %d", tQSL_Error); return 1; } } /* Make a list of superceded certs */ for (i = 0; i < sk_X509_num(xcerts); i++) { x = sk_X509_value(xcerts, i); len = sizeof buf-1; if (!tqsl_get_cert_ext(x, "supercededCertificate", (unsigned char *)buf, &len, NULL)) { buf[len] = 0; string sup = buf; superceded_certs.insert(sup); /* Fix - the extension as inserted by ARRL * reads ".../Email=lotw@arrl.org", not * the expected ".../emailAddress=". * save both forms in case this gets * changed at the LoTW site */ size_t pos = sup.find("/Email"); if (pos != string::npos) { sup.replace(pos, 6, "/emailAddress"); superceded_certs.insert(sup); } } } // "supercededCertificate" extension is ; cp = X509_NAME_oneline(X509_get_issuer_name(TQSL_API_TO_CERT(cert)->cert), buf, sizeof(buf)); if (cp == NULL) { superceded = false; tqslTrace("tqsl_isCertificateSuperceded", "returning false"); } else { string sup = buf; sup += ";"; long serial = 0; tqsl_getCertificateSerial(cert, &serial); snprintf(buf, sizeof buf, "%ld", serial); sup += buf; if (superceded_certs.find(sup) != superceded_certs.end()) { tqslTrace("tqsl_isCertificateSuperceded", "returning true"); superceded = true; } } *status = superceded; return 0; } DLLEXPORT int CALLCONVENTION tqsl_selectCertificates(tQSL_Cert **certlist, int *ncerts, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flags) { int withkeys = flags & TQSL_SELECT_CERT_WITHKEYS; TQSL_X509_STACK *selcerts = NULL; char path[TQSL_MAX_PATH_LEN]; int i; X509 *x; int rval = 1; tqsl_cert *cp; TQSL_CERT_REQ *crq; BIO *bio = NULL; EVP_PKEY *pubkey = NULL; EVP_PKEY *curkey = NULL; vector< map > keylist; vector< map >::iterator it; bool keyerror = false; int savedError; int savedErrno; tqslTrace("tqsl_selectCertificates", "callsign=%s, dxcc=%d, flags=%d", callsign ? callsign : "NULL", dxcc, flags); if (tqsl_init()) return 1; if (ncerts == NULL) { tqslTrace("tqsl_selectCertificates", "arg error ncerts=0x%lx", ncerts); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *ncerts = 0; if (certlist) *certlist = NULL; /* Convert the dates to tQSL_Date objects */ if (date && !tqsl_isDateNull(date) && !tqsl_isDateValid(date)) { tqslTrace("tqsl_selectCertificates", "arg error - bad date"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } /* Get the certs from the cert store */ tqsl_make_cert_path("user", path, sizeof path); if (xcerts == NULL) xcerts = tqsl_ssl_load_certs_from_file(path); if (xcerts == NULL) { if (tQSL_Error == TQSL_OPENSSL_ERROR) { tqslTrace("tqsl_selectCertificates", "openssl error"); return 1; } else if (tQSL_Error != TQSL_SYSTEM_ERROR || tQSL_Errno != ENOENT) { // No file tqslTrace("tqsl_selectCertificates", "other error %d", tQSL_Error); return 1; } } else { selcerts = tqsl_filter_cert_list(xcerts, callsign, dxcc, date, issuer, flags); } // Get a list of keys and find any unmatched (no cert) ones if (withkeys) { if (tqsl_make_key_list(keylist)) { keyerror = true; // Remember that an error occurred savedError = tQSL_Error; // but allow the rest of the certs to load savedErrno = tQSL_Errno; tqslTrace("tqsl_selectCertificates", "make_key_list error %d %d", tQSL_Error, tQSL_Errno); } if (xcerts != NULL) { for (i = 0; i < sk_X509_num(xcerts); i++) { x = sk_X509_value(xcerts, i); if ((pubkey = X509_get_pubkey(x)) == NULL) { tqslTrace("tqsl_selectCertificates", "can't get pubkey"); goto err; } for (it = keylist.begin(); it != keylist.end(); it++) { int match = 0; /* Compare the keys */ string& keystr = (*it)["PUBLIC_KEY"]; if ((bio = BIO_new_mem_buf(static_cast(const_cast(keystr.c_str())), keystr.length())) == NULL) { tqslTrace("tqsl_selectCertifcates", "bio_new error %s", tqsl_openssl_error()); goto err; } if ((curkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { tqslTrace("tqsl_selectCertificates", "pem_read_bio err %s", tqsl_openssl_error()); goto err; } BIO_free(bio); bio = NULL; if (EVP_PKEY_cmp(curkey, pubkey) == 1) match = 1; EVP_PKEY_free(curkey); curkey = NULL; if (match) { // Remove matched key from list keylist.erase(it); break; } } EVP_PKEY_free(pubkey); pubkey = NULL; } } // Filter keylist for (it = keylist.begin(); it != keylist.end(); ) { if ((*it)["TQSL_CRQ_PROVIDER"] == "") it = keylist.erase(it); else if (callsign && (*it)["CALLSIGN"] != callsign) it = keylist.erase(it); else if (dxcc && strtol((*it)["TQSL_CRQ_DXCC_ENTITY"].c_str(), NULL, 10) != dxcc) it = keylist.erase(it); else if (issuer && (*it)["TQSL_CRQ_PROVIDER"] != issuer->organizationName) it = keylist.erase(it); else if (issuer && (*it)["TQSL_CRQ_PROVIDER_UNIT"] != issuer->organizationalUnitName) it = keylist.erase(it); else it++; } } //cerr << keylist.size() << " unmatched keys" << endl; *ncerts = (selcerts ? sk_X509_num(selcerts) : 0) + keylist.size(); tqslTrace("tqsl_selectCertificates", "ncerts=%d", *ncerts); if (certlist == NULL) // Only want certificate count goto end; *certlist = reinterpret_cast(tqsl_calloc(*ncerts, sizeof(tQSL_Cert))); if (selcerts != NULL) { for (i = 0; i < sk_X509_num(selcerts); i++) { x = sk_X509_value(selcerts, i); if ((cp = tqsl_cert_new()) == NULL) { tqslTrace("tqsl_selectCertificates", "error making new cert - %s", tqsl_openssl_error()); goto end; } cp->cert = X509_dup(x); (*certlist)[i] = TQSL_OBJ_TO_API(cp); } } else { i = 0; } for (it = keylist.begin(); it != keylist.end(); it++) { if ((cp = tqsl_cert_new()) == NULL) { tqslTrace("tqsl_selectCertificates", "error making new cert - %s", tqsl_openssl_error()); goto end; } crq = reinterpret_cast(tqsl_calloc(1, sizeof(TQSL_CERT_REQ))); if (crq != NULL) { tQSL_Error = TQSL_BUFFER_ERROR; if (!safe_strncpy(crq->providerName, (*it)["TQSL_CRQ_PROVIDER"].c_str(), sizeof crq->providerName)) goto end; if (!safe_strncpy(crq->providerUnit, (*it)["TQSL_CRQ_PROVIDER_UNIT"].c_str(), sizeof crq->providerUnit)) goto end; if (!safe_strncpy(crq->callSign, (*it)["CALLSIGN"].c_str(), sizeof crq->callSign)) goto end; if (!safe_strncpy(crq->name, (*it)["TQSL_CRQ_NAME"].c_str(), sizeof crq->name)) goto end; if (!safe_strncpy(crq->emailAddress, (*it)["TQSL_CRQ_EMAIL"].c_str(), sizeof crq->emailAddress)) goto end; if (!safe_strncpy(crq->address1, (*it)["TQSL_CRQ_ADDRESS1"].c_str(), sizeof crq->address1)) goto end; if (!safe_strncpy(crq->address2, (*it)["TQSL_CRQ_ADDRESS2"].c_str(), sizeof crq->address2)) goto end; if (!safe_strncpy(crq->city, (*it)["TQSL_CRQ_CITY"].c_str(), sizeof crq->city)) goto end; if (!safe_strncpy(crq->state, (*it)["TQSL_CRQ_STATE"].c_str(), sizeof crq->state)) goto end; if (!safe_strncpy(crq->postalCode, (*it)["TQSL_CRQ_POSTAL"].c_str(), sizeof crq->postalCode)) goto end; if (!safe_strncpy(crq->country, (*it)["TQSL_CRQ_COUNTRY"].c_str(), sizeof crq->country)) goto end; crq->dxccEntity = strtol((*it)["TQSL_CRQ_DXCC_ENTITY"].c_str(), NULL, 10); tqsl_initDate(&(crq->qsoNotBefore), (*it)["TQSL_CRQ_QSO_NOT_BEFORE"].c_str()); tqsl_initDate(&(crq->qsoNotAfter), (*it)["TQSL_CRQ_QSO_NOT_AFTER"].c_str()); tQSL_Error = 0; } cp->crq = crq; int len = strlen((*it)["PUBLIC_KEY"].c_str()); if (len) { cp->pubkey = new char[len+1]; strncpy(cp->pubkey, (*it)["PUBLIC_KEY"].c_str(), len+1); } len = strlen((*it)["PRIVATE_KEY"].c_str()); if (len) { cp->privkey = new char[len+1]; strncpy(cp->privkey, (*it)["PRIVATE_KEY"].c_str(), len+1); } cp->keyonly = 1; (*certlist)[i++] = TQSL_OBJ_TO_API(cp); } if (keyerror) { // If an error happened with private key scan tQSL_Error = savedError; // Restore the error status from that tQSL_Errno = savedErrno; rval = 1; } else { rval = 0; } goto end; err: tQSL_Error = TQSL_OPENSSL_ERROR; end: if (selcerts != NULL) sk_X509_free(selcerts); if (bio != NULL) BIO_free(bio); if (pubkey != NULL) EVP_PKEY_free(pubkey); if (curkey != NULL) EVP_PKEY_free(curkey); return rval; } DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates(tQSL_Cert **certlist, int *ncerts, const char *type) { TQSL_X509_STACK *cacerts = NULL; int rval = 1; char path[TQSL_MAX_PATH_LEN]; int i; X509 *x; tqsl_cert *cp; vector< map > keylist; vector< map >::iterator it; tqslTrace("tqsl_selectCACertificates", NULL); if (tqsl_init()) return 1; if (certlist == NULL || ncerts == NULL) { tqslTrace("tqsl_selectCACertificates", "arg error certlist=0x%lx, ncerts=0x%lx", certlist, ncerts); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } /* Get the certs from the cert store */ tqsl_make_cert_path(type, path, sizeof path); cacerts = tqsl_ssl_load_certs_from_file(path); if (cacerts == NULL) { if (tQSL_Error == TQSL_OPENSSL_ERROR) { tqslTrace("tqsl_selectCACertificates", "cacerts openssl error"); return 1; } } *ncerts = (cacerts ? sk_X509_num(cacerts) : 0) + keylist.size(); *certlist = reinterpret_cast(tqsl_calloc(*ncerts, sizeof(tQSL_Cert))); if (cacerts != NULL) { for (i = 0; i < sk_X509_num(cacerts); i++) { x = sk_X509_value(cacerts, i); if ((cp = tqsl_cert_new()) == NULL) { tqslTrace("tqsl_selectCACertificates", "cert_new error %s", tqsl_openssl_error()); goto end; } cp->cert = X509_dup(x); (*certlist)[i] = TQSL_OBJ_TO_API(cp); } } rval = 0; end: if (cacerts != NULL) sk_X509_free(cacerts); return rval; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateKeyOnly(tQSL_Cert cert, int *keyonly) { tqslTrace("tqsl_getCertificateKeyOnly", "cert=0x%lx, keyonly=0x%lx", cert, keyonly); if (tqsl_init()) return 1; if (cert == NULL || keyonly == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateKeyOnly", "arg error"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *keyonly = TQSL_API_TO_CERT(cert)->keyonly; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateEncoded(tQSL_Cert cert, char *buf, int bufsiz) { BIO *bio = NULL; int len; char *cp; int rval = 1; tqslTrace("tqsl_getCertificateEncoded", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateEncoded", "arg error cert=0x%lx, buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_getCertificateEncoded", "bio_new err %s", tqsl_openssl_error()); goto err; } if (!PEM_write_bio_X509(bio, TQSL_API_TO_CERT(cert)->cert)) { tqslTrace("tqsl_getCertificateEncoded", "pem_write_bio err %s", tqsl_openssl_error()); goto err; } len = static_cast(BIO_get_mem_data(bio, &cp)); if (len < bufsiz) { memcpy(buf, cp, len); buf[len] = 0; } else { tqslTrace("tqsl_getCertificateEncoded", "buffer error %d needed %d there", len, bufsiz); tQSL_Error = TQSL_BUFFER_ERROR; goto end; } rval = 0; goto end; err: tQSL_Error = TQSL_OPENSSL_ERROR; end: if (bio != NULL) BIO_free(bio); return rval; } DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded(tQSL_Cert cert, char *buf, int bufsiz) { BIO *b64 = NULL; BIO *bio = NULL; BIO *out = NULL; char callsign[40]; long len; char *cp; vector< map > keylist; vector< map >::iterator it; EVP_PKEY *pubkey = NULL; EVP_PKEY *curkey = NULL; tqslTrace("tqsl_getKeyEncoded", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getKeyEncoded", "arg error cert=0x%lx, buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tQSL_Error = TQSL_OPENSSL_ERROR; // If it's 'keyonly', then there's no public key - use the one in the cert. if (TQSL_API_TO_CERT(cert)->keyonly) { if (TQSL_API_TO_CERT(cert)->privkey == 0) { tqslTrace("tqsl_getKeyEncoded", "arg error no private key"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(callsign, TQSL_API_TO_CERT(cert)->crq->callSign, sizeof callsign); b64 = BIO_new(BIO_f_base64()); out = BIO_new(BIO_s_mem()); out = BIO_push(b64, out); tQSL_Error = TQSL_SYSTEM_ERROR; if (tqsl_bio_write_adif_field(out, "CALLSIGN", 0, (const unsigned char *)callsign, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "PRIVATE_KEY", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->privkey, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "PUBLIC_KEY", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->pubkey, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } char numbuf[10]; snprintf(numbuf, sizeof numbuf, "%d", TQSL_API_TO_CERT(cert)->crq->dxccEntity); if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_DXCC_ENTITY", 0, (const unsigned char *)numbuf, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_PROVIDER", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->providerName, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_PROVIDER_UNIT", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->providerUnit, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_EMAIL", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->emailAddress, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_ADDRESS1", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->address1, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_ADDRESS2", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->address2, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_CITY", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->city, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_STATE", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->state, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_POSTAL", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->postalCode, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_COUNTRY", 0, (const unsigned char *)TQSL_API_TO_CERT(cert)->crq->country, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); return 1; } char datebuf[20]; tqsl_convertDateToText(&(TQSL_API_TO_CERT(cert)->crq->qsoNotAfter), datebuf, sizeof datebuf); if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_QSO_NOT_AFTER", 0, (const unsigned char *)datebuf, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } tqsl_convertDateToText(&(TQSL_API_TO_CERT(cert)->crq->qsoNotBefore), datebuf, sizeof datebuf); if (tqsl_bio_write_adif_field(out, "TQSL_CRQ_QSO_NOT_BEFORE", 0, (const unsigned char *)datebuf, -1)) { tqslTrace("tqsl_getKeyEncoded", "write_adif_field error %d", tQSL_Error); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } tqsl_bio_write_adif_field(out, "eor", 0, NULL, 0); if (BIO_flush(out) != 1) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "Error encoding certificate", sizeof tQSL_CustomError); BIO_free_all(out); tqslTrace("tqsl_getKeyEncoded", "BIO_flush error %s", tqsl_openssl_error()); return 1; } len = BIO_get_mem_data(out, &cp); if (len > bufsiz) { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Private key buffer size %d is too small - %ld needed", bufsiz, len); BIO_free_all(out); tqslTrace("tqsl_getKeyEncoded", "buffer size err: %s", tQSL_CustomError); return 1; } memcpy(buf, cp, len); buf[len] = '\0'; BIO_free_all(out); return 0; } if (tqsl_getCertificateCallSign(cert, callsign, sizeof callsign)) { tqslTrace("tqsl_getKeyEncoded", "Error getting callsign %d", tQSL_Error); return 1; } if (tqsl_make_key_list(keylist)) { tqslTrace("tqsl_getKeyEncoded", "Error making keylist %d", tQSL_Error); tQSL_Error = TQSL_SYSTEM_ERROR; return 1; } if ((pubkey = X509_get_pubkey(TQSL_API_TO_CERT(cert)->cert)) == 0) { tqslTrace("tqsl_getKeyEncoded", "Error getting pubkey %d", tQSL_Error); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } // Find the matching private key for (it = keylist.begin(); it != keylist.end(); it++) { string& keystr = (*it)["PUBLIC_KEY"]; if ((bio = BIO_new_mem_buf(static_cast(const_cast(keystr.c_str())), keystr.length())) == NULL) { tqslTrace("tqsl_getKeyEncoded", "Error getting buffer %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } if ((curkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { BIO_free(bio); tqslTrace("tqsl_getKeyEncoded", "Error reading PUBKEY %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } BIO_free(bio); bio = NULL; if (EVP_PKEY_cmp(curkey, pubkey) == 1) { // This is the matching private key. Let's feed it back. EVP_PKEY_free(curkey); curkey = NULL; EVP_PKEY_free(pubkey); pubkey = NULL; b64 = BIO_new(BIO_f_base64()); out = BIO_new(BIO_s_mem()); out = BIO_push(b64, out); map::iterator mit; for (mit = it->begin(); mit != it->end(); mit++) { if (tqsl_bio_write_adif_field(out, mit->first.c_str(), 0, (const unsigned char *)mit->second.c_str(), -1)) { tQSL_Error = TQSL_SYSTEM_ERROR; tqslTrace("tqsl_getKeyEncoded", "Error writing field %s", tqsl_openssl_error()); return 1; } } tqsl_bio_write_adif_field(out, "eor", 0, NULL, 0); if (BIO_flush(out) != 1) { tQSL_Error = TQSL_CUSTOM_ERROR; tqslTrace("tqsl_getKeyEncoded", "Error flushing write %s", tqsl_openssl_error()); strncpy(tQSL_CustomError, "Error encoding certificate", sizeof tQSL_CustomError); BIO_free_all(out); return 1; } len = BIO_get_mem_data(out, &cp); if (len > bufsiz) { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Private key buffer size %d is too small - %ld needed", bufsiz, len); tqslTrace("tqsl_getKeyEncoded", "Buffer err %s", tQSL_CustomError); BIO_free_all(out); return 1; } memcpy(buf, cp, len); buf[len] = '\0'; BIO_free_all(out); return 0; } else { EVP_PKEY_free(curkey); curkey = NULL; } } if (pubkey != NULL) EVP_PKEY_free(pubkey); tqslTrace("tqsl_getKeyEncoded", "private key not found"); tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Private key not found for callsign %s", callsign); return 1; // Private key not found } DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded(const char *callsign, const char *type, const char *keybuf, const char *certbuf) { BIO *in = NULL; BIO *b64 = NULL; BIO *pub = NULL; X509 *cert; char path[TQSL_MAX_PATH_LEN]; char temppath[TQSL_MAX_PATH_LEN]; char biobuf[4096]; int cb = 0; map fields; void* userdata = NULL; tqslTrace("tqsl_importKeyPairEncoded", NULL); if (tqsl_init()) return 1; if (certbuf == NULL || type == NULL) { tqslTrace("tqsl_importKeyPairEncoded", "arg error certbuf=0x%lx, type=0x%lx", certbuf, type); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (strcmp(type, "user") == 0) { if (keybuf == NULL) { tqslTrace("tqsl_importKeyPairEncoded", "arg error user cert keybuf null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } cb = TQSL_CERT_CB_USER; } else if (strcmp(type, "root") == 0) { cb = TQSL_CERT_CB_ROOT; } else if (strcmp(type, "authorities") == 0) { cb = TQSL_CERT_CB_CA; } else { tqslTrace("tqsl_importKeyPairEncoded", "arg error type unknown"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (keybuf) { if (!tqsl_make_key_path(callsign, path, sizeof path)) { goto noprv; } in = BIO_new_mem_buf(static_cast(const_cast(keybuf)), strlen(keybuf)); if (in == NULL) { goto noprv; } b64 = BIO_new(BIO_f_base64()); in = BIO_push(b64, in); size_t bloblen; bloblen = BIO_read(in, biobuf, strlen(keybuf)); biobuf[bloblen] = '\0'; strncpy(temppath, tQSL_BaseDir, sizeof temppath); FILE *temp = NULL; #ifdef _WIN32 strncat(temppath, "\\pk.tmp", sizeof temppath - strlen(temppath) -1); wchar_t* wpath = utf8_to_wchar(temppath); if ((temp = _wfopen(wpath, TQSL_OPEN_WRITE)) == NULL) { free_wchar(wpath); #else strncat(temppath, "/pk.tmp", sizeof temppath - strlen(temppath) -1); if ((temp = fopen(temppath, TQSL_OPEN_WRITE)) == NULL) { #endif strncpy(tQSL_ErrorFile, temppath, sizeof tQSL_ErrorFile); tqslTrace("tqsl_importKeyPairEncoded", "Open file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; return 1; } #ifdef _WIN32 free_wchar(wpath); #endif if (fputs(biobuf, temp) == EOF) { strncpy(tQSL_ErrorFile, temppath, sizeof tQSL_ErrorFile); tqslTrace("tqsl_importKeyPairEncoded", "Write request file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; return 1; } if (fclose(temp) == EOF) { strncpy(tQSL_ErrorFile, temppath, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_importKeyPairEncoded", "write error %d", errno); return 1; } // Now is there a private key already with this serial? char *pubkey = strstr(biobuf, "-----BEGIN PUBLIC KEY-----"); char *endpub = strstr(biobuf, "-----END PUBLIC KEY-----"); int publen = endpub - pubkey + strlen("-----END PUBLIC KEY-----"); if (pubkey) { EVP_PKEY *new_key = NULL; if ((pub = BIO_new_mem_buf(reinterpret_cast(pubkey), publen)) == NULL) { goto noprv; } if ((new_key = PEM_read_bio_PUBKEY(pub, NULL, NULL, NULL)) == NULL) { goto noprv; } BIO_free(pub); pub = 0; if (!tqsl_key_exists(callsign, new_key)) { // Populate fields from the temp file if (!tqsl_open_key_file(temppath)) { if (!tqsl_read_key(fields)) { tqsl_replace_key(callsign, path, fields, NULL, userdata); } tqsl_close_key_file(); } } BIO_free_all(in); } } // Import of private key noprv: if (strlen(certbuf) == 0) // Keyonly 'certificates' return 0; // Now process the certificate in = BIO_new_mem_buf(static_cast(const_cast(certbuf)), strlen(certbuf)); if (in == NULL) { tqslTrace("tqsl_importKeyPairEncoded", "cert new_mem_buf err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } cert = PEM_read_bio_X509(in, NULL, NULL, NULL); BIO_free(in); if (cert == NULL) { tqslTrace("tqsl_importKeyPairEncoded", "read_bio_x509 err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } int ret = tqsl_store_cert(certbuf, cert, type, cb, true, NULL, NULL); // it's OK if installing the cert gets a dupe if (ret != 0 && tQSL_Error == TQSL_CERT_ERROR) { ret = 0; } return ret; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateCallSign(tQSL_Cert cert, char *buf, int bufsiz) { char nbuf[40]; TQSL_X509_NAME_ITEM item; tqslTrace("tqsl_getCertificateCallSign", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateCallSign", "arg err cert=0x%lx buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly && TQSL_API_TO_CERT(cert)->crq) { // Handle the key-only case if (bufsiz <= static_cast(strlen(TQSL_API_TO_CERT(cert)->crq->callSign))) { tqslTrace("tqsl_getCertificateCallSign", "bufsiz=%d, needed=%d", bufsiz, static_cast(strlen(TQSL_API_TO_CERT(cert)->crq->callSign))); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(buf, TQSL_API_TO_CERT(cert)->crq->callSign, bufsiz); tqslTrace("tqsl_getCertificateCallSign", "KeyOnly, call=%s", buf); return 0; } item.name_buf = nbuf; item.name_buf_size = sizeof nbuf; item.value_buf = buf; item.value_buf_size = bufsiz; int ret = tqsl_cert_get_subject_name_entry(TQSL_API_TO_CERT(cert)->cert, "AROcallsign", &item); tqslTrace("tqsl_getCertificateCallSign", "Result=%d, call=%s", ret, buf); return !ret; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateAROName(tQSL_Cert cert, char *buf, int bufsiz) { char nbuf[40]; TQSL_X509_NAME_ITEM item; tqslTrace("tqsl_getCertificateAROName", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateAROName", "cert=0x%lx, buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } item.name_buf = nbuf; item.name_buf_size = sizeof nbuf; item.value_buf = buf; item.value_buf_size = bufsiz; return !tqsl_cert_get_subject_name_entry(TQSL_API_TO_CERT(cert)->cert, "commonName", &item); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateEmailAddress(tQSL_Cert cert, char *buf, int bufsiz) { char nbuf[40]; TQSL_X509_NAME_ITEM item; tqslTrace("tqsl_getCertificateEmailAddress", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateEmailAddress", "arg err cert=0x%lx, buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } item.name_buf = nbuf; item.name_buf_size = sizeof nbuf; item.value_buf = buf; item.value_buf_size = bufsiz; return !tqsl_cert_get_subject_name_entry(TQSL_API_TO_CERT(cert)->cert, "emailAddress", &item); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerial(tQSL_Cert cert, long *serial) { tqslTrace("tqsl_getCertificateSerial", NULL); if (tqsl_init()) return 1; if (cert == NULL || serial == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateSerial", "arg err cert=0x%lx, serial=0x%lx", cert, serial); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *serial = ASN1_INTEGER_get(X509_get_serialNumber(TQSL_API_TO_CERT(cert)->cert)); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt(tQSL_Cert cert, char *serial, int serialsiz) { tqslTrace("tqsl_getCertificateSerialExt", NULL); if (tqsl_init()) return 1; if (cert == NULL || serial == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert)) || serialsiz < 1) { tqslTrace("tqsl_getCertificateSerialExt", "arg err cert=0x%lx, serial=0x%lx", cert, serial); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } BIGNUM *bn = BN_new(); ASN1_INTEGER_to_BN(X509_get_serialNumber(TQSL_API_TO_CERT(cert)->cert), bn); char *s = BN_bn2hex(bn); strncpy(serial, s, serialsiz); serial[serialsiz-1] = 0; OPENSSL_free(s); BN_free(bn); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialLength(tQSL_Cert cert) { int rval; tqslTrace("tqsl_getCertificateSerialLength", NULL); if (tqsl_init()) return 1; if (cert == NULL) { tqslTrace("tqsl_getCertificateSerialLength", "arg error,cert=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } BIGNUM *bn = BN_new(); ASN1_INTEGER_to_BN(X509_get_serialNumber(TQSL_API_TO_CERT(cert)->cert), bn); char *s = BN_bn2hex(bn); rval = strlen(s); OPENSSL_free(s); BN_free(bn); return rval; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuer(tQSL_Cert cert, char *buf, int bufsiz) { char *cp; tqslTrace("tqsl_getCertificateIssuer", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateIssuer", "arg err cert=0x%lx, buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } cp = X509_NAME_oneline(X509_get_issuer_name(TQSL_API_TO_CERT(cert)->cert), buf, bufsiz); if (cp == NULL) { tqslTrace("tqsl_getCertificateIssuer", "X509_NAME_oneline error %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; } return (cp == NULL); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganization(tQSL_Cert cert, char *buf, int bufsiz) { char nbuf[40]; TQSL_X509_NAME_ITEM item; X509_NAME *iss; tqslTrace("tqsl_getCertificateIssuerOrganization", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateIssuerOrganization", "arg error cert=0x%lx buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly && TQSL_API_TO_CERT(cert)->crq) { // Handle the key-only case if (bufsiz <= static_cast(strlen(TQSL_API_TO_CERT(cert)->crq->providerName))) { tqslTrace("tqsl_getCertificateIssuerOrganization", "bufsiz error have=%d need=%d", bufsiz, static_cast(strlen(TQSL_API_TO_CERT(cert)->crq->providerName))); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(buf, TQSL_API_TO_CERT(cert)->crq->providerName, bufsiz); return 0; } item.name_buf = nbuf; item.name_buf_size = sizeof nbuf; item.value_buf = buf; item.value_buf_size = bufsiz; if ((iss = X509_get_issuer_name(TQSL_API_TO_CERT(cert)->cert)) == NULL) { tqslTrace("tqsl_getCertificateIssuerOrganization", "get_issuer_name err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } return !tqsl_get_name_entry(iss, "organizationName", &item); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganizationalUnit(tQSL_Cert cert, char *buf, int bufsiz) { char nbuf[40]; TQSL_X509_NAME_ITEM item; X509_NAME *iss; tqslTrace("tqsl_getCertificateIssuerOrganizationalUnit", NULL); if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateIssuerOrganizationalUnit", "arg err cert=0x%lx, buf=0x%lx", cert, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly && TQSL_API_TO_CERT(cert)->crq) { // Handle the key-only case if (bufsiz <= static_cast(strlen(TQSL_API_TO_CERT(cert)->crq->providerUnit))) { tqslTrace("tqsl_getCertificateIssuerOrganizationalUnit", "bufsize error have=%d need=%d", bufsiz, static_cast(strlen(TQSL_API_TO_CERT(cert)->crq->providerUnit))); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(buf, TQSL_API_TO_CERT(cert)->crq->providerUnit, bufsiz); return 0; } item.name_buf = nbuf; item.name_buf_size = sizeof nbuf; item.value_buf = buf; item.value_buf_size = bufsiz; if ((iss = X509_get_issuer_name(TQSL_API_TO_CERT(cert)->cert)) == NULL) { tqslTrace("tqsl_getCertificateIssuerOrganizationalUnit", "get_issuer_name err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } return !tqsl_get_name_entry(iss, "organizationalUnitName", &item); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotBeforeDate(tQSL_Cert cert, tQSL_Date *date) { char datebuf[40]; int len = (sizeof datebuf) -1; tqslTrace("tqsl_getCertificateQSONotBeforeDate", NULL); if (tqsl_init()) return 1; if (cert == NULL || date == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateQSONotBeforeDate", "arg err cert=0x%lx date=0x%lx", cert, date); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly && TQSL_API_TO_CERT(cert)->crq) { // Handle the key-only case *date = TQSL_API_TO_CERT(cert)->crq->qsoNotBefore; return 0; } if (tqsl_get_cert_ext(TQSL_API_TO_CERT(cert)->cert, "QSONotBeforeDate", (unsigned char *)datebuf, &len, NULL)) return 1; datebuf[len] = 0; return tqsl_initDate(date, const_cast(datebuf)); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotAfterDate(tQSL_Cert cert, tQSL_Date *date) { char datebuf[40]; int len = (sizeof datebuf) -1; tqslTrace("tqsl_getCertificateQSONotAfterDate", NULL); if (tqsl_init()) return 1; if (cert == NULL || date == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateQSONotAfterDate", "arg err cert=0x%lx date=0x%lx", cert, date); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly && TQSL_API_TO_CERT(cert)->crq) { // Handle the key-only case *date = TQSL_API_TO_CERT(cert)->crq->qsoNotAfter; return 0; } if (tqsl_get_cert_ext(TQSL_API_TO_CERT(cert)->cert, "QSONotAfterDate", (unsigned char *)datebuf, &len, NULL)) return 1; datebuf[len] = 0; return tqsl_initDate(date, const_cast(datebuf)); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotBeforeDate(tQSL_Cert cert, tQSL_Date *date) { const ASN1_TIME *tm; tqslTrace("tqsl_getCertificateNotBeforeDate", NULL); if (tqsl_init()) return 1; if (cert == NULL || date == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateNotBeforeDate", "arg err cert=0x%lx date=0x%lx", cert, date); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly) { tqslTrace("tqsl_getCertificateNotBeforeDate", "Err:cert is keyonly"); tQSL_Error = TQSL_CERT_KEY_ONLY; return 1; } if ((tm = X509_get_notBefore(TQSL_API_TO_CERT(cert)->cert)) == NULL) { tqslTrace("tqsl_getCertificateNotBeforeDate", "get_notBefore err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } return tqsl_get_asn1_date(tm, date); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotAfterDate(tQSL_Cert cert, tQSL_Date *date) { const ASN1_TIME *tm; if (tqsl_init()) return 1; if (cert == NULL || date == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getCertificateNotAfterDate", "arg err cert=0x%lx date=0x%lx", cert, date); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly) { tqslTrace("tqsl_getCertificateNotAfterDate", "Err:cert is keyonly"); tQSL_Error = TQSL_CERT_KEY_ONLY; return 1; } if ((tm = X509_get_notAfter(TQSL_API_TO_CERT(cert)->cert)) == NULL) { tqslTrace("tqsl_getCertificateNotAfterDate", "get_notAfter err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } return tqsl_get_asn1_date(tm, date); } DLLEXPORT int CALLCONVENTION tqsl_getCertificateDXCCEntity(tQSL_Cert cert, int *dxcc) { char buf[40]; int len = sizeof buf; tqslTrace("tqsl_getCertificateDXCCEntity", NULL); if (tqsl_init()) return 1; if (cert == NULL || dxcc == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificateDXCCEntity", "arg err cert=0x%lx dxcc=0x%lx", cert, dxcc); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->keyonly && TQSL_API_TO_CERT(cert)->crq) { // Handle the key-only case *dxcc = TQSL_API_TO_CERT(cert)->crq->dxccEntity; return 0; } if (tqsl_get_cert_ext(TQSL_API_TO_CERT(cert)->cert, "dxccEntity", (unsigned char *)buf, &len, NULL)) { tqslTrace("tqsl_getCertificateDXCCEntity", "Cert does not have dxcc extension"); return 1; } *dxcc = strtol(buf, NULL, 10); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificatePrivateKeyType(tQSL_Cert cert) { tqslTrace("tqsl_getCertificatePrivateKeyType", NULL); if (tqsl_init()) return 1; if (!tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_getCertificatePrivateKeyType", "arg err, bad cert"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (tqsl_beginSigning(cert, const_cast (""), 0, 0)) { // Try to unlock the key using no password if (tQSL_Error == TQSL_PASSWORD_ERROR) { tqsl_getErrorString(); // Clear the error tqslTrace("tqsl_getCertificatePrivateKeyType", "password error - encrypted"); return TQSL_PK_TYPE_ENC; } tqslTrace("tqsl_getCertificatePrivateKeyType", "other error"); return TQSL_PK_TYPE_ERR; } tqslTrace("tqsl_getCertificatePrivateKeyType", "unencrypted"); return TQSL_PK_TYPE_UNENC; } DLLEXPORT void CALLCONVENTION tqsl_freeCertificate(tQSL_Cert cert) { if (cert == NULL) return; tqsl_cert_free(TQSL_API_TO_CERT(cert)); } DLLEXPORT void CALLCONVENTION tqsl_freeCertificateList(tQSL_Cert* list, int ncerts) { for (int i = 0; i < ncerts; i++) if (list[i]) tqsl_cert_free(TQSL_API_TO_CERT(list[i])); if (list) free(list); } DLLEXPORT int CALLCONVENTION tqsl_beginSigning(tQSL_Cert cert, char *password, int(*pwcb)(char *, int, void *), void *userdata) { tqslTrace("tqsl_beginSigning", NULL); if (tqsl_init()) return 1; if (cert == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_beginSigning", "arg err cert=0x%lx", cert); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->key != NULL) return 0; if (TQSL_API_TO_CERT(cert)->keyonly) { if (TQSL_API_TO_CERT(cert)->privkey == 0) { tqslTrace("tqsl_beginSigning", "can't sign, keyonly"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } return tqsl_unlock_key(TQSL_API_TO_CERT(cert)->privkey, &(TQSL_API_TO_CERT(cert)->key), password, pwcb, userdata); } return tqsl_find_matching_key(TQSL_API_TO_CERT(cert)->cert, &(TQSL_API_TO_CERT(cert)->key), &(TQSL_API_TO_CERT(cert)->crq), password, pwcb, userdata); } DLLEXPORT int CALLCONVENTION tqsl_getMaxSignatureSize(tQSL_Cert cert, int *sigsize) { tqslTrace("tqsl_getMaxSignatureSize", NULL); if (tqsl_init()) return 1; if (cert == NULL || sigsize == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_getMaxSignatureSize", "arg err cert=0x%lx, sigsize=0x%lx", cert, sigsize); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->key == NULL) { tqslTrace("tqsl_getMaxSignatureSize", "arg err key=null"); tQSL_Error = TQSL_SIGNINIT_ERROR; return 1; } *sigsize = EVP_PKEY_size(TQSL_API_TO_CERT(cert)->key); return 0; } DLLEXPORT int CALLCONVENTION tqsl_checkSigningStatus(tQSL_Cert cert) { tqslTrace("tqsl_checkSigningStatus", NULL); if (tqsl_init()) return 1; if (cert == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_checkSigningStatus", "arg err cert=0x%lx", cert); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->key == NULL) { tqslTrace("tqsl_checkSigningStatus", "arg err no key"); tQSL_Error = TQSL_SIGNINIT_ERROR; return 1; } return 0; } DLLEXPORT int CALLCONVENTION tqsl_signDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int *siglen) { tqslTrace("tqsl_signDataBlock", NULL); if (tqsl_init()) return 1; if (cert == NULL || data == NULL || sig == NULL || siglen == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_signDataBlock", "arg error cert=0x%lx data=0x%lx sig=0x%lx siglen=0x%lx", cert, data, sig, siglen); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } EVP_MD_CTX *ctx = EVP_MD_CTX_create(); if (ctx == NULL) return 1; unsigned int slen = *siglen; if (TQSL_API_TO_CERT(cert)->key == NULL) { tqslTrace("tqsl_signDataBlock", "can't sign, no key"); tQSL_Error = TQSL_SIGNINIT_ERROR; if (ctx) EVP_MD_CTX_destroy(ctx); return 1; } EVP_SignInit(ctx, EVP_sha1()); EVP_SignUpdate(ctx, data, datalen); if (!EVP_SignFinal(ctx, sig, &slen, TQSL_API_TO_CERT(cert)->key)) { tqslTrace("tqsl_signDataBlock", "signing failed %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; if (ctx) EVP_MD_CTX_destroy(ctx); return 1; } *siglen = slen; if (ctx) EVP_MD_CTX_destroy(ctx); return 0; } DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int siglen) { EVP_MD_CTX *ctx = EVP_MD_CTX_create(); unsigned int slen = siglen; tqslTrace("tqsl_verifyDataBlock", NULL); if (ctx == NULL) return 1; if (tqsl_init()) return 1; if (cert == NULL || data == NULL || sig == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_verifyDataBlock", "arg error cert=0x%lx data=0x%lx sig=0x%lx", cert, data, sig); tQSL_Error = TQSL_ARGUMENT_ERROR; if (ctx) EVP_MD_CTX_destroy(ctx); return 1; } if (TQSL_API_TO_CERT(cert)->key == NULL) { tqslTrace("tqsl_verifyDataBlock", "no key"); tQSL_Error = TQSL_SIGNINIT_ERROR; if (ctx) EVP_MD_CTX_destroy(ctx); return 1; } EVP_VerifyInit(ctx, EVP_sha1()); EVP_VerifyUpdate(ctx, data, datalen); if (EVP_VerifyFinal(ctx, sig, slen, TQSL_API_TO_CERT(cert)->key) <= 0) { tqslTrace("tqsl_verifyDataBlock", "verify fail %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; if (ctx) EVP_MD_CTX_destroy(ctx); return 1; } if (ctx) EVP_MD_CTX_destroy(ctx); return 0; } DLLEXPORT int CALLCONVENTION tqsl_endSigning(tQSL_Cert cert) { tqslTrace("tqsl_endSigning", NULL); if (tqsl_init()) return 1; if (cert == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_endSigning", "arg err cert=0x%lx", cert); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->key != NULL) { EVP_PKEY_free(TQSL_API_TO_CERT(cert)->key); TQSL_API_TO_CERT(cert)->key = NULL; } return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress1(tQSL_Cert cert, char *buf, int bufsiz) { tqslTrace("tqsl_getCertificateRequestAddress1", NULL); if (tqsl_check_crq_field(cert, buf, bufsiz)) { tqslTrace("tqsl_getCertificateRequestAddress1", "check fail"); return 1; } strncpy(buf, (TQSL_API_TO_CERT(cert)->crq)->address1, bufsiz); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress2(tQSL_Cert cert, char *buf, int bufsiz) { tqslTrace("tqsl_getCertificateRequestAddress2", NULL); if (tqsl_check_crq_field(cert, buf, bufsiz)) { tqslTrace("tqsl_getCertificateRequestAddress2", "check fail"); return 1; } strncpy(buf, (TQSL_API_TO_CERT(cert)->crq)->address2, bufsiz); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCity(tQSL_Cert cert, char *buf, int bufsiz) { tqslTrace("tqsl_getCertificateRequestCity", NULL); if (tqsl_check_crq_field(cert, buf, bufsiz)) { tqslTrace("tqsl_getCertificateRequestCity", "check fail"); return 1; } strncpy(buf, (TQSL_API_TO_CERT(cert)->crq)->city, bufsiz); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestState(tQSL_Cert cert, char *buf, int bufsiz) { tqslTrace("tqsl_getCertificateRequestState", NULL); if (tqsl_check_crq_field(cert, buf, bufsiz)) { tqslTrace("tqsl_getCertificateRequestState", "check fail"); return 1; } strncpy(buf, (TQSL_API_TO_CERT(cert)->crq)->state, bufsiz); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestPostalCode(tQSL_Cert cert, char *buf, int bufsiz) { tqslTrace("tqsl_getCertificateRequestPostalCode", NULL); if (tqsl_check_crq_field(cert, buf, bufsiz)) { tqslTrace("tqsl_getCertificateRequestPostalCode", "check fail"); return 1; } strncpy(buf, (TQSL_API_TO_CERT(cert)->crq)->postalCode, bufsiz); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCountry(tQSL_Cert cert, char *buf, int bufsiz) { tqslTrace("tqsl_getCertificateRequestCountry", NULL); if (tqsl_check_crq_field(cert, buf, bufsiz)) { tqslTrace("tqsl_getCertificateRequestCountry", "check fail"); return 1; } strncpy(buf, (TQSL_API_TO_CERT(cert)->crq)->country, bufsiz); return 0; } static int tqsl_add_bag_attribute(PKCS12_SAFEBAG *bag, const char *oidname, const string& value) { int nid; nid = OBJ_txt2nid(const_cast(oidname)); if (nid == NID_undef) { tqslTrace("tqsl_add_bag_attribute", "OBJ_txt2nid err %s", tqsl_openssl_error()); return 1; } unsigned char *uni; int unilen; if (asc2uni(value.c_str(), value.length(), &uni, &unilen)) { ASN1_TYPE *val; X509_ATTRIBUTE *attrib; if (!uni[unilen - 1] && !uni[unilen - 2]) unilen -= 2; if ((val = ASN1_TYPE_new()) != 0) { ASN1_TYPE_set(val, V_ASN1_BMPSTRING, uni); if ((attrib = X509_ATTRIBUTE_new()) != 0) { X509_ATTRIBUTE_set1_object(attrib, OBJ_nid2obj(nid)); if ((X509_ATTRIBUTE_set1_data(attrib, V_ASN1_BMPSTRING, uni, unilen)) != 0) { #if (OPENSSL_VERSION_NUMBER & 0xfffff000) == 0x00906000 attrib->set = 1; #else #if OPENSSL_VERSION_NUMBER < 0x10100000L #if (OPENSSL_VERSION_NUMBER & 0xfffff000) >= 0x00907000 attrib->single = 0; #else #error "Unexpected OpenSSL version; check X509_ATTRIBUTE struct compatibility" #endif #endif #endif #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) STACK_OF(X509_ATTRIBUTE) *sk; sk = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag); if (sk) { sk_X509_ATTRIBUTE_push(sk, attrib); #else if (bag->attrib) { sk_X509_ATTRIBUTE_push(bag->attrib, attrib); #endif //cerr << "Added " << oidname << endl; } else { tqslTrace("tqsl_add_bag_attribute", "no attrib"); return 1; } } else { tqslTrace("tqsl_add_bag_attribute", "no value set"); return 1; } } else { tqslTrace("tqsl_add_bag_attribute", "attrib create err %s", tqsl_openssl_error()); return 1; } } else { tqslTrace("tqsl_add_bag_attribute", "bmp->data empty"); return 1; } } else { // asc2uni ok tqslTrace("tqsl_add_bag_attribute", "asc2uni err %s", tqsl_openssl_error()); return 1; } return 0; } static int tqsl_exportPKCS12(tQSL_Cert cert, bool returnB64, const char *filename, char *base64, int b64len, const char *p12password) { STACK_OF(X509) *root_sk = 0, *ca_sk = 0, *chain = 0; const char *cp; char rootpath[TQSL_MAX_PATH_LEN], capath[TQSL_MAX_PATH_LEN]; char buf[256]; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; STACK_OF(PKCS12_SAFEBAG) *bags = 0; PKCS12_SAFEBAG *bag = 0; STACK_OF(PKCS7) *safes = 0; PKCS7 *authsafe = 0; int cert_pbe = NID_aes_256_cbc; int key_pbe = NID_aes_256_cbc; PKCS8_PRIV_KEY_INFO *p8 = 0; PKCS12 *p12 = 0; const EVP_MD *md = 0; BIO *out = 0, *b64 = 0; string callSign, issuerOrganization, issuerOrganizationalUnit; tQSL_Date date; string QSONotBeforeDate, QSONotAfterDate, dxccEntity, Email, Address1, Address2, City, State, Postal, Country; int dxcc = 0; int rval = 1; tqslTrace("tqsl_exportPKCS12", NULL); if (cert == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_exportPKCS12", "arg error cert=0x%lx", cert); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if ((returnB64 && base64 == NULL) || (!returnB64 && filename == NULL)) { tqslTrace("tqsl_exportPKCS12", "arg error returnB64=%d base64=0x%lx filename=0x%lx", returnB64, base64, filename); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } #if defined(__APPLE__) const char *oldc = getenv("OLDCRYPTO"); tqslTrace("tqsl_exportPKCS12", "get env returns %s", oldc ? oldc : "null"); // For compatibility with Apple Keychain for Mac // They don't support anything but deprecated P12 crypto // SHA1, 3DES, RC2. if (oldc && !strcmp(oldc, "TRUE")) { cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; md = reinterpret_cast (EVP_get_digestbyname("sha1")); } #endif /* Get parameters for key bag attributes */ if (tqsl_getCertificateCallSign(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get callsign err %d", tQSL_Error); return 1; } callSign = buf; if (tqsl_getCertificateIssuerOrganization(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get org err %d", tQSL_Error); return 1; } issuerOrganization = buf; if (tqsl_getCertificateIssuerOrganizationalUnit(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get ou err %d", tQSL_Error); return 1; } issuerOrganizationalUnit = buf; if (!TQSL_API_TO_CERT(cert)->keyonly) { if (tqsl_getCertificateEmailAddress(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get email err %d", tQSL_Error); return 1; } Email = buf; if (tqsl_getCertificateRequestAddress1(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get addr1 err %d", tQSL_Error); return 1; } Address1 = buf; if (tqsl_getCertificateRequestAddress2(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get addr2 err %d", tQSL_Error); return 1; } Address2 = buf; if (tqsl_getCertificateRequestCity(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get city err %d", tQSL_Error); return 1; } City = buf; if (tqsl_getCertificateRequestState(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get state err %d", tQSL_Error); return 1; } State = buf; if (tqsl_getCertificateRequestPostalCode(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get postal err %d", tQSL_Error); return 1; } Postal = buf; if (tqsl_getCertificateRequestCountry(cert, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "get country err %d", tQSL_Error); return 1; } Country = buf; } if (tqsl_getCertificateQSONotBeforeDate(cert, &date)) { tqslTrace("tqsl_exportPKCS12", "get qso not before err %d", tQSL_Error); return 1; } if (!tqsl_convertDateToText(&date, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "qso not before err %d", tQSL_Error); return 1; } QSONotBeforeDate = buf; if (tqsl_getCertificateQSONotAfterDate(cert, &date)) { tqslTrace("tqsl_exportPKCS12", "get qso not after err %d", tQSL_Error); return 1; } if (!tqsl_isDateNull(&date)) { if (!tqsl_convertDateToText(&date, buf, sizeof buf)) { tqslTrace("tqsl_exportPKCS12", "qso not before err %d", tQSL_Error); return 1; } QSONotAfterDate = buf; } if (tqsl_getCertificateDXCCEntity(cert, &dxcc)) { tqslTrace("tqsl_exportPKCS12", "get entity err %d", tQSL_Error); return 1; } snprintf(buf, sizeof buf, "%d", dxcc); dxccEntity = buf; if (TQSL_API_TO_CERT(cert)->key == NULL) { tqslTrace("tqsl_exportPKCS12", "key is null"); tQSL_Error = TQSL_SIGNINIT_ERROR; return 1; } if (!TQSL_API_TO_CERT(cert)->keyonly) { tqslTrace("tqsl_exportPKCS12", "keyonly cert"); /* Generate local key ID to tie key to cert */ X509_digest(TQSL_API_TO_CERT(cert)->cert, EVP_sha1(), keyid, &keyidlen); /* Check the chain of authority back to a trusted root */ tqsl_make_cert_path("root", rootpath, sizeof rootpath); if ((root_sk = tqsl_ssl_load_certs_from_file(rootpath)) == NULL) { if (!tqsl_ssl_error_is_nofile()) { tqslTrace("tqsl_exportPKCS12", "can't find certs"); goto p12_end; } } tqsl_make_cert_path("authorities", capath, sizeof capath); if ((ca_sk = tqsl_ssl_load_certs_from_file(capath)) == NULL) { if (!tqsl_ssl_error_is_nofile()) { tqslTrace("tqsl_exportPKCS12", "can't find certs"); goto p12_end; } } /* tqsl_ssl_verify_cert will collect the certificates in the chain, back to the * root certificate, verify them and return a stack containing copies of just * those certificates (including the user certificate). */ cp = tqsl_ssl_verify_cert(TQSL_API_TO_CERT(cert)->cert, ca_sk, root_sk, 0, &tqsl_expired_is_ok, &chain); if (cp) { if (chain) sk_X509_free(chain); tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, cp, sizeof tQSL_CustomError); tqslTrace("tqsl_exportPKCS12", "verify fail: %s", cp); return 1; } } // !keyonly tQSL_Error = TQSL_OPENSSL_ERROR; // Assume error /* Open the output file */ if (!returnB64) { out = BIO_new_file(filename, "wb"); } else { b64 = BIO_new(BIO_f_base64()); out = BIO_new(BIO_s_mem()); out = BIO_push(b64, out); } if (!out) { tqslTrace("tqsl_exportPKCS12", "BIO_new err %s", tqsl_openssl_error()); goto p12_end; } safes = sk_PKCS7_new_null(); if (!TQSL_API_TO_CERT(cert)->keyonly) { /* Create a safebag stack and fill it with the needed certs */ bags = sk_PKCS12_SAFEBAG_new_null(); for (int i = 0; i < sk_X509_num(chain); i++) { X509 *x = sk_X509_value(chain, i); #if (OPENSSL_VERSION_NUMBER & 0xfffff000) == 0x00906000 bag = PKCS12_pack_safebag(reinterpret_cast(x), (int (*)())i2d_X509, NID_x509Certificate, NID_certBag); #else bag = PKCS12_x5092certbag(x); #endif if (!bag) { tqslTrace("tqsl_exportPKCS12", "Error creating bag: %s", tqsl_openssl_error()); goto p12_end; } if (x == TQSL_API_TO_CERT(cert)->cert) { PKCS12_add_friendlyname(bag, "TrustedQSL user certificate", -1); PKCS12_add_localkeyid(bag, keyid, keyidlen); } sk_PKCS12_SAFEBAG_push(bags, bag); } /* Convert stack of safebags into an authsafe */ unsigned char p12salt[9]; memcpy(p12salt, "lamesalt", 8); authsafe = PKCS12_pack_p7encdata(cert_pbe, p12password, -1, p12salt, 8, PKCS12_DEFAULT_ITER, bags); if (!authsafe) { tqslTrace("tqsl_exportPKCS12", "Error creating authsafe: %s", tqsl_openssl_error()); goto p12_end; } sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = 0; /* Add to stack of authsafes */ sk_PKCS7_push(safes, authsafe); } // !keyonly /* Make a shrouded key bag */ p8 = EVP_PKEY2PKCS8(TQSL_API_TO_CERT(cert)->key); if (!p8) { tqslTrace("tqsl_exportPKCS12", "Error creating p8 container: %s", tqsl_openssl_error()); goto p12_end; } bag = PKCS12_MAKE_SHKEYBAG(key_pbe, p12password, -1, 0, 0, PKCS12_DEFAULT_ITER, p8); if (!bag) { tqslTrace("tqsl_exportPKCS12", "Error creating p8 keybag: %s", tqsl_openssl_error()); goto p12_end; } PKCS8_PRIV_KEY_INFO_free(p8); p8 = NULL; PKCS12_add_friendlyname(bag, "TrustedQSL user certificate", -1); if (!TQSL_API_TO_CERT(cert)->keyonly) PKCS12_add_localkeyid(bag, keyid, keyidlen); /* Add the attributes to the private key bag */ tqsl_add_bag_attribute(bag, "AROcallsign", callSign); tqsl_add_bag_attribute(bag, "QSONotBeforeDate", QSONotBeforeDate); if (QSONotAfterDate != "") tqsl_add_bag_attribute(bag, "QSONotAfterDate", QSONotAfterDate); tqsl_add_bag_attribute(bag, "tqslCRQIssuerOrganization", issuerOrganization); tqsl_add_bag_attribute(bag, "tqslCRQIssuerOrganizationalUnit", issuerOrganizationalUnit); tqsl_add_bag_attribute(bag, "dxccEntity", dxccEntity); tqsl_add_bag_attribute(bag, "tqslCRQEmail", Email); tqsl_add_bag_attribute(bag, "tqslCRQAddress1", Address1); tqsl_add_bag_attribute(bag, "tqslCRQAddress2", Address2); tqsl_add_bag_attribute(bag, "tqslCRQCity", City); tqsl_add_bag_attribute(bag, "tqslCRQState", State); tqsl_add_bag_attribute(bag, "tqslCRQPostal", Postal); tqsl_add_bag_attribute(bag, "tqslCRQCountry", Country); bags = sk_PKCS12_SAFEBAG_new_null(); if (!bags) { tqslTrace("tqsl_exportPKCS12", "Error creating safebag: %s", tqsl_openssl_error()); goto p12_end; } sk_PKCS12_SAFEBAG_push(bags, bag); /* Turn shrouded key bag into unencrypted safe bag and add to safes stack */ authsafe = PKCS12_pack_p7data(bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; sk_PKCS7_push(safes, authsafe); /* Form into PKCS12 data */ p12 = PKCS12_init(NID_pkcs7_data); M_PKCS12_pack_authsafes(p12, safes); sk_PKCS7_pop_free(safes, PKCS7_free); safes = NULL; PKCS12_set_mac(p12, p12password, -1, 0, 0, PKCS12_DEFAULT_ITER, md); /* Write the PKCS12 data */ i2d_PKCS12_bio(out, p12); if (BIO_flush(out) != 1) { rval = 1; tqslTrace("tqsl_exportPKCS12", "Error writing pkcs12: %s", tqsl_openssl_error()); goto p12_end; } if (returnB64) { char *encoded; int len; len = BIO_get_mem_data(out, &encoded); encoded[len - 1] = '\0'; strncpy(base64, encoded, b64len); } rval = 0; tQSL_Error = TQSL_NO_ERROR; p12_end: if (out) { BIO_free(out); if (rval && !returnB64) { #ifdef _WIN32 wchar_t* wfilename = utf8_to_wchar(filename); _wunlink(wfilename); free_wchar(wfilename); #else unlink(filename); #endif } } if (chain) sk_X509_free(chain); if (root_sk) sk_X509_free(root_sk); if (ca_sk) sk_X509_free(ca_sk); if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if (safes) sk_PKCS7_pop_free(safes, PKCS7_free); if (p8) PKCS8_PRIV_KEY_INFO_free(p8); return rval; } DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File(tQSL_Cert cert, const char *filename, const char *p12password) { tqslTrace("tqsl_exportPKCS12File", NULL); return tqsl_exportPKCS12(cert, false, filename, NULL, 0, p12password); } DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64(tQSL_Cert cert, char *base64, int b64len, const char *p12password) { tqslTrace("tqsl_exportPKCS12Base64", NULL); return tqsl_exportPKCS12(cert, true, NULL, base64, b64len, p12password); } static string tqsl_asn1_octet_string_to_hex(ASN1_OCTET_STRING *os) { string str; for (int k = 0; k < os->length; k++) { char hex[3] = " "; hex[0] = ((os->data[k] >> 4) & 0xf) + '0'; if (hex[0] > '9') hex[0] += 'A' - '9' - 1; hex[1] = (os->data[k] & 0xf) + '0'; if (hex[1] > '9') hex[1] += 'A' - '9' - 1; if (str.size()) str += " "; str += hex; } return str; } struct tqsl_imported_cert { string pem; string keyid; string callsign; }; static int tqsl_get_bag_attribute(PKCS12_SAFEBAG *bag, const char *oidname, string& str) { const ASN1_TYPE *attr; str = ""; if ((attr = PKCS12_get_attr(bag, OBJ_txt2nid(const_cast(oidname)))) != 0) { if (attr->type != V_ASN1_BMPSTRING) { tQSL_Error = TQSL_CERT_TYPE_ERROR; tqslTrace("tqsl_get_bag_attribute", "cert type error oid %s", oidname); return 1; } char *c = uni2asc(attr->value.bmpstring->data, attr->value.bmpstring->length); str = c; OPENSSL_free(c); } return 0; } static int tqsl_importPKCS12(bool importB64, const char *filename, const char *base64, const char *p12password, const char *password, int (*pwcb)(char *, int, void *), int(*cb)(int, const char *, void *), void *userdata) { PKCS12 *p12 = 0; PKCS12_SAFEBAG *bag; PKCS8_PRIV_KEY_INFO *p8 = 0; EVP_PKEY *pkey = 0; BIO *in = 0, *bio = 0 , *b64 = 0; STACK_OF(PKCS7) *safes = 0; STACK_OF(PKCS12_SAFEBAG) *bags = 0; PKCS7 *p7; X509 *x; BASIC_CONSTRAINTS *bs = 0; ASN1_OBJECT *callobj = 0, *obj = 0; const ASN1_TYPE *attr = 0; const EVP_CIPHER *cipher; unsigned char *cp; int i, j, bagnid, len; vector rootcerts; vector cacerts; vector usercerts; vector *certlist; vector::iterator it; bool is_cacert; string public_key, private_key, private_keyid, key_callsign, str; map key_attr; map newrecord; map::iterator mit; char path[TQSL_MAX_PATH_LEN], pw[256]; int rval = 1; tqslTrace("tqsl_importPKCS12", NULL); if (tqsl_init()) return 1; if ((!importB64 && filename == NULL) || (importB64 && base64 == NULL)) { tqslTrace("tqsl_importPKCS12", "arg error importB64=%d filename=0x%lx base64=0x%lx", importB64, filename, base64); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tQSL_ImportCall[0] = '\0'; tQSL_ImportSerial = 0; ImportCall[0] = '\0'; tQSL_Error = TQSL_OPENSSL_ERROR; /* Read in the PKCS#12 file */ if (importB64) { b64 = BIO_new(BIO_f_base64()); in = BIO_new_mem_buf(const_cast(base64), strlen(base64)); in = BIO_push(b64, in); } else { in = BIO_new_file(filename, "rb"); } if (in == 0) { tqslTrace("tqsl_importPKCS12", "Couldn't create bio: %s", tqsl_openssl_error()); goto imp_end; } if ((p12 = d2i_PKCS12_bio(in, 0)) == 0) { tqslTrace("tqsl_importPKCS12", "Couldn't read pkcs12: %s", tqsl_openssl_error()); goto imp_end; } BIO_free(in); in = 0; /* Verify MAC */ if (!PKCS12_verify_mac(p12, p12password, -1)) { tqslTrace("tqsl_importPKCS12", "Mac doesn't verify"); tQSL_Error = TQSL_PASSWORD_ERROR; goto imp_end; } /* Loop through the authsafes */ if ((safes = M_PKCS12_unpack_authsafes(p12)) == 0) { tqslTrace("tqsl_importPKCS12", "Can't unpack authsafe: %s", tqsl_openssl_error()); goto imp_end; } callobj = OBJ_txt2obj("AROcallsign", 0); for (i = 0; i < sk_PKCS7_num(safes); i++) { tqsl_imported_cert imported_cert; p7 = sk_PKCS7_value(safes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, p12password, strlen(p12password)); } else { continue; // Not something we understand } if (!bags) { tQSL_Error = TQSL_PKCS12_ERROR; tqslTrace("tqsl_importPKCS12", "bags empty: %s", tqsl_openssl_error()); goto imp_end; } /* Loop through safebags */ for (j = 0; j < sk_PKCS12_SAFEBAG_num(bags); j++) { tqsl_imported_cert imported_cert; bag = sk_PKCS12_SAFEBAG_value(bags, j); switch (M_PKCS12_bag_type(bag)) { case NID_certBag: if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) break; // Can't handle anything else if ((x = M_PKCS12_certbag2x509(bag)) == 0) { tqslTrace("tqsl_importPKCS12", "bag2x509: %s", tqsl_openssl_error()); goto imp_end; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_importPKCS12", "bio_new: %s", tqsl_openssl_error()); goto imp_end; } if (!PEM_write_bio_X509(bio, x)) { tqslTrace("tqsl_importPKCS12", "write_bio: %s", tqsl_openssl_error()); goto imp_end; } len = static_cast(BIO_get_mem_data(bio, &cp)); imported_cert.pem = string((const char *)cp, len); if ((attr = PKCS12_get_attr(bag, NID_localKeyID)) != 0) { if (attr->type != V_ASN1_OCTET_STRING) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch"); tQSL_Error = TQSL_CERT_TYPE_ERROR; goto imp_end; } imported_cert.keyid = tqsl_asn1_octet_string_to_hex(attr->value.octet_string); } BIO_free(bio); bio = 0; is_cacert = false; if ((bs = reinterpret_cast(X509_get_ext_d2i(x, NID_basic_constraints, 0, 0))) != 0) { if (bs->ca) is_cacert = true; BASIC_CONSTRAINTS_free(bs); bs = 0; } certlist = &usercerts; if (is_cacert) { if (X509_check_issued(x, x) == X509_V_OK) // Self signed must be trusted certlist = &rootcerts; else certlist = &cacerts; } else { /* Make sure the cert is TQSL compatible */ TQSL_X509_NAME_ITEM item; char nbuf[40]; char callbuf[256]; item.name_buf = nbuf; item.name_buf_size = sizeof nbuf; item.value_buf = callbuf; item.value_buf_size = sizeof callbuf; if (!tqsl_cert_get_subject_name_entry(x, "AROcallsign", &item)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch"); tQSL_Error = TQSL_CERT_TYPE_ERROR; goto imp_end; } imported_cert.callsign = callbuf; } (*certlist).push_back(imported_cert); break; case NID_pkcs8ShroudedKeyBag: if ((attr = PKCS12_get_attr(bag, NID_localKeyID)) != 0) { if (attr->type != V_ASN1_OCTET_STRING) { tQSL_Error = TQSL_CERT_TYPE_ERROR; tqslTrace("tqsl_importPKCS12", "Cert type mismatch"); goto imp_end; } private_keyid = tqsl_asn1_octet_string_to_hex(attr->value.octet_string); } if (tqsl_get_bag_attribute(bag, "AROcallsign", key_callsign)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no callsign"); goto imp_end; } if (tqsl_get_bag_attribute(bag, "dxccEntity", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no dxcc"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_DXCC_ENTITY"] = str; if (tqsl_get_bag_attribute(bag, "QSONotBeforeDate", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no qsonotbefore"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_QSO_NOT_BEFORE"] = str; if (tqsl_get_bag_attribute(bag, "QSONotAfterDate", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no qsonotafter"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_QSO_NOT_AFTER"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQIssuerOrganization", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no org"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_PROVIDER"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQIssuerOrganizationalUnit", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no ou"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_PROVIDER_UNIT"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQEmail", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no email"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_EMAIL"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQAddress1", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no addr1"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_ADDRESS1"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQAddress2", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no addr2"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_ADDRESS2"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQCity", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no city"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_CITY"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQState", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no state"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_STATE"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQPostal", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no postal"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_POSTAL"] = str; if (tqsl_get_bag_attribute(bag, "tqslCRQCountry", str)) { tqslTrace("tqsl_importPKCS12", "Cert type mismatch - no country"); goto imp_end; } if (str != "") key_attr["TQSL_CRQ_COUNTRY"] = str; if ((p8 = M_PKCS12_decrypt_skey(bag, p12password, strlen(p12password))) == 0) { tqslTrace("tqsl_importPKCS12", "password error"); goto imp_end; } if ((pkey = EVP_PKCS82PKEY(p8)) == 0) { tqslTrace("tqsl_importPKCS12", "pkey error"); goto imp_end; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_importPKCS12", "bio_new error %s", tqsl_openssl_error()); goto imp_end; } if (password == 0) { if (pwcb) { if ((*pwcb)(pw, sizeof pw -1, userdata)) { tqslTrace("tqsl_importPKCS12", "operator aborted at password prompt"); tQSL_Error = TQSL_OPERATOR_ABORT; goto imp_end; } password = pw; } else { password = NULL; } } if (password && *password != '\0') { cipher = EVP_des_ede3_cbc(); len = strlen(password); } else { cipher = 0; len = 0; } if (!PEM_write_bio_PrivateKey(bio, pkey, cipher, (unsigned char *)password, len, 0, 0)) { tqslTrace("tqsl_importPKCS12", "writing bio err: %s", tqsl_openssl_error()); goto imp_end; } len = static_cast(BIO_get_mem_data(bio, &cp)); private_key = string((const char *)cp, len); BIO_free(bio); if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_importPKCS12", "new bio err: %s", tqsl_openssl_error()); goto imp_end; } if (!PEM_write_bio_PUBKEY(bio, pkey)) { tqslTrace("tqsl_importPKCS12", "write pubkey bio err: %s", tqsl_openssl_error()); goto imp_end; } len = static_cast(BIO_get_mem_data(bio, &cp)); public_key = string((const char *)cp, len); BIO_free(bio); bio = 0; EVP_PKEY_free(pkey); pkey = 0; PKCS8_PRIV_KEY_INFO_free(p8); p8 = 0; break; case NID_keyBag: tqslTrace("tqsl_importPKCS12", "cert type err: NID_keyBag"); tQSL_Error = TQSL_CERT_TYPE_ERROR; goto imp_end; } // bag type switch } // safebags loop sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = 0; } sk_PKCS7_pop_free(safes, PKCS7_free); safes = 0; /* Now we have the certificates and key pair, so add them to the local store */ tqslTrace("tqsl_importPKCS12", "have keys"); if (key_callsign == "") { /* Need to get call sign from cert. The tQSL_exportKeys function puts the * call sign in a safebag attribute that should have been read already, * but if some other software created the PKCS#12 file that may not have * happened. There should, however, be a localKeyID attribute that matches * the key to the certificate. If not, it's an error. */ if (private_keyid == "") { // No key ID, can't find cert tqslTrace("tqsl_importPKCS12", "no callsign attribute"); tQSL_Error = TQSL_CERT_TYPE_ERROR; goto imp_end; } for (it = usercerts.begin(); it != usercerts.end(); it++) { if ((*it).keyid == private_keyid) { key_callsign = (*it).callsign; break; } } if (key_callsign == "") { // Can't find cert or callsign tqslTrace("tqsl_importPKCS12", "can't find cert or callsign"); tQSL_Error = TQSL_CERT_TYPE_ERROR; goto imp_end; } } if (!tqsl_make_key_path(key_callsign.c_str(), path, sizeof path)) { tqslTrace("tqsl_importPKCS12", "keypath error %d", tQSL_Error); goto imp_end; } newrecord["PUBLIC_KEY"] = public_key; newrecord["PRIVATE_KEY"] = private_key; newrecord["CALLSIGN"] = key_callsign; for (mit = key_attr.begin(); mit != key_attr.end(); mit++) newrecord[mit->first] = mit->second; if (tqsl_replace_key(key_callsign.c_str(), path, newrecord, cb, userdata)) { tqslTrace("tqsl_importPKCS12", "replace key error %d", tQSL_Error); goto imp_end; } for (it = rootcerts.begin(); it != rootcerts.end(); it++) { if (tqsl_import_cert(it->pem.c_str(), tqsllib::ROOTCERT, cb, userdata) && tQSL_Error != TQSL_CERT_ERROR) { tqslTrace("tqsl_importPKCS12", "import root cert error %d", tQSL_Error); goto imp_end; } } for (it = cacerts.begin(); it != cacerts.end(); it++) { if (tqsl_import_cert(it->pem.c_str(), tqsllib::CACERT, cb, userdata) && tQSL_Error != TQSL_CERT_ERROR) { tqslTrace("tqsl_importPKCS12", "import ca cert error %d", tQSL_Error); goto imp_end; } } rval = 0; // Assume no errors for (it = usercerts.begin(); it != usercerts.end(); it++) { if (tqsl_import_cert(it->pem.c_str(), tqsllib::USERCERT, cb, userdata)) { if (tQSL_Error == TQSL_CERT_ERROR) { rval = 1; // Remember failure to import continue; } char savepath[TQSL_MAX_PATH_LEN], badpath[TQSL_MAX_PATH_LEN]; strncpy(badpath, path, sizeof(badpath)); strncat(badpath, ".bad", sizeof(badpath)-strlen(badpath)-1); badpath[sizeof(badpath)-1] = '\0'; #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); wchar_t* wbadpath = utf8_to_wchar(badpath); wchar_t* wsavepath = NULL; if (!_wrename(wpath, wbadpath)) { #else if (!rename(path, badpath)) { #endif strncpy(savepath, path, sizeof(savepath)); strncat(savepath, ".save", sizeof(savepath)-strlen(savepath)-1); savepath[sizeof(savepath)-1] = '\0'; #ifdef _WIN32 wsavepath = utf8_to_wchar(savepath); if (_wrename(wsavepath, wpath)) // didn't work _wrename(wbadpath, wpath); #else if (rename(savepath, path)) // didn't work rename(badpath, path); #endif else #ifdef _WIN32 { _wunlink(wbadpath); free_wchar(wpath); free_wchar(wbadpath); if (wsavepath) free_wchar(wsavepath); } #else unlink(badpath); #endif } goto imp_end; } } if (rval == 0) { tQSL_Error = TQSL_NO_ERROR; strncpy(tQSL_ImportCall, ImportCall, sizeof tQSL_ImportCall); } else { if (tQSL_Error == 0) { tQSL_Error = TQSL_CERT_ERROR; } } imp_end: if (p12) PKCS12_free(p12); if (in) BIO_free(in); if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if (safes) sk_PKCS7_pop_free(safes, PKCS7_free); if (obj) ASN1_OBJECT_free(obj); if (callobj) ASN1_OBJECT_free(callobj); if (bs) BASIC_CONSTRAINTS_free(bs); if (p8) PKCS8_PRIV_KEY_INFO_free(p8); if (pkey) EVP_PKEY_free(pkey); return rval; } DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File(const char *filename, const char *p12password, const char *password, int (*pwcb)(char *, int, void *), int(*cb)(int, const char *, void *), void *userdata) { tqslTrace("tqsl_importPKCS12File", NULL); return tqsl_importPKCS12(false, filename, NULL, p12password, password, pwcb, cb, userdata); } DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64(const char *base64, const char *p12password, const char *password, int (*pwcb)(char *, int, void *), int(*cb)(int, const char *, void *), void *userdata) { tqslTrace("tqsl_importPKCS12Base64", NULL); return tqsl_importPKCS12(true, NULL, base64, p12password, password, pwcb, cb, userdata); } static int tqsl_backup_cert(tQSL_Cert cert) { char callsign[64]; long serial = 0; int dxcc = 0; int keyonly; tqsl_getCertificateKeyOnly(cert, &keyonly); tqsl_getCertificateCallSign(cert, callsign, sizeof callsign); if (!keyonly) tqsl_getCertificateSerial(cert, &serial); tqsl_getCertificateDXCCEntity(cert, &dxcc); char backupPath[TQSL_MAX_PATH_LEN]; tqsl_make_backup_path(callsign, backupPath, sizeof backupPath); FILE* out = NULL; #ifdef _WIN31 wchar_t* wpath = utf8_to_wchar(backupPath); _wunlink(wpath); fd = _wfopen(lfn, L"wb"); free_wchar(wpath); #else unlink(backupPath); out = fopen(backupPath, "wb"); #endif if (!out) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; strncpy(tQSL_ErrorFile, backupPath, sizeof tQSL_ErrorFile); tQSL_ErrorFile[sizeof tQSL_ErrorFile-1] = 0; tqslTrace("tqsl_backup_cert", "Error %d errno %d file %s", tQSL_Error, tQSL_Errno, backupPath); return 1; } char buf[8192]; fprintf(out, "\n", callsign, dxcc, serial); if (!keyonly) { fprintf(out, "\n"); tqsl_getCertificateEncoded(cert, buf, sizeof buf); fprintf(out, "%s", buf); fprintf(out, "\n"); } fprintf(out, "\n"); tqsl_getKeyEncoded(cert, buf, sizeof buf); fprintf(out, "%s", buf); fprintf(out, "\n\n"); fclose(out); return 0; } static int tqsl_make_backup_list(const char* filter, vector& keys) { keys.clear(); string path = tQSL_BaseDir; #ifdef _WIN32 path += "\\certtrash"; wchar_t* wpath = utf8_to_wchar(path.c_str()); MKDIR(wpath, 0700); #else path += "/certtrash"; MKDIR(path.c_str(), 0700); #endif #ifdef _WIN32 WDIR *dir = wopendir(wpath); free_wchar(wpath); #else DIR *dir = opendir(path.c_str()); #endif if (dir == NULL) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_make_backup_list", "Opendir %s error %s", path.c_str(), strerror(errno)); return 1; } #ifdef _WIN32 struct wdirent *ent; #else struct dirent *ent; #endif int rval = 0; int savedError = 0; int savedErrno = 0; char *savedFile = NULL; #ifdef _WIN32 while ((ent = wreaddir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; char dname[TQSL_MAX_PATH_LEN]; wcstombs(dname, ent->d_name, TQSL_MAX_PATH_LEN); string filename = path + "\\" + dname; struct _stat32 s; wchar_t* wfilename = utf8_to_wchar(filename.c_str()); if (_wstat32(wfilename, &s) == 0) { if (S_ISDIR(s.st_mode)) { free_wchar(wfilename); continue; // If it's a directory, skip it. } } #else while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; string filename = path + "/" + ent->d_name; struct stat s; if (stat(filename.c_str(), &s) == 0) { if (S_ISDIR(s.st_mode)) continue; // If it's a directory, skip it. } #endif XMLElement xel; int status = xel.parseFile(filename.c_str()); if (status) continue; // Can't be parsed XMLElement cert; xel.getFirstElement(cert); pair atrval = cert.getAttribute("CallSign"); if (atrval.second) { // If the callsign matches, or if the filter is empty, add it. if (filter == NULL || atrval.first == filter) { keys.push_back(atrval.first); } } } #ifdef _WIN32 _wclosedir(dir); #else closedir(dir); #endif if (rval) { tQSL_Error = savedError; tQSL_Errno = savedErrno; if (savedFile) { strncpy(tQSL_ErrorFile, savedFile, sizeof tQSL_ErrorFile); free(savedFile); } tqslTrace("tqsl_make_backup_list", "error %s %s", tQSL_ErrorFile, strerror(tQSL_Errno)); } return rval; } DLLEXPORT int CALLCONVENTION tqsl_deleteCertificate(tQSL_Cert cert) { tqslTrace("tqsl_deleteCertificate", NULL); if (tqsl_init()) return 1; if (cert == NULL || !tqsl_cert_check(TQSL_API_TO_CERT(cert), false)) { tqslTrace("tqsl_deleteCertificate", "arg err cert=0x%lx", cert); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tqsl_backup_cert(cert); char callsign[256], path[TQSL_MAX_PATH_LEN], newpath[TQSL_MAX_PATH_LEN]; if (tqsl_getCertificateCallSign(cert, callsign, sizeof callsign)) { tqslTrace("tqsl_deleteCertificate", "no callsign %d", tQSL_Error); return 1; } int rval = 1; EVP_PKEY *key = 0; BIO *bio = 0; tQSL_Error = TQSL_OPENSSL_ERROR; // Delete private key map rec; if (TQSL_API_TO_CERT(cert)->pubkey) { rec["PUBLIC_KEY"] = TQSL_API_TO_CERT(cert)->pubkey; } else { // Get public key from cert if ((key = X509_get_pubkey(TQSL_API_TO_CERT(cert)->cert)) == 0) { tqslTrace("tqsl_deleteCertificate", "no public key %s", tqsl_openssl_error()); goto dc_end; } if ((bio = BIO_new(BIO_s_mem())) == NULL) { tqslTrace("tqsl_deleteCertificate", "bio err %s", tqsl_openssl_error()); goto dc_end; } if (!PEM_write_bio_PUBKEY(bio, key)) { tqslTrace("tqsl_deleteCertificate", "bio write err %s", tqsl_openssl_error()); goto dc_end; } char *cp; int len = static_cast(BIO_get_mem_data(bio, &cp)); rec["PUBLIC_KEY"] = string(cp, len); BIO_free(bio); bio = 0; EVP_PKEY_free(key); key = 0; } rec["CALLSIGN"] = callsign; if (!tqsl_make_key_path(callsign, path, sizeof path)) { tqslTrace("tqsl_deleteCertificate", "key path err %s", tQSL_Error); goto dc_end; } // Since there is no private key in "rec," tqsl_replace_key will just remove the // existing private key. tqsl_replace_key(callsign, path, rec, 0, 0); if (TQSL_API_TO_CERT(cert)->keyonly) { tqslTrace("tqsl_deleteCertificate", "key only"); goto dc_ok; } // Now the certificate tqsl_make_cert_path("user", path, sizeof path); tqsl_make_cert_path("user.new", newpath, sizeof newpath); if (xcerts == NULL) { if ((xcerts = tqsl_ssl_load_certs_from_file(path)) == 0) { tqslTrace("tqsl_deleteCertificate", "error reading certs %d", tQSL_Error); goto dc_end; } } if ((bio = BIO_new_file(newpath, "wb")) == 0) { tqslTrace("tqsl_deleteCertificate", "bio_new_file %s", tqsl_openssl_error()); goto dc_end; } X509 *x; while ((x = sk_X509_shift(xcerts)) != 0) { if (X509_issuer_and_serial_cmp(x, TQSL_API_TO_CERT(cert)->cert)) { if (!PEM_write_bio_X509(bio, x)) { // No match -- keep this one tqslTrace("tqsl_deleteCertificate", "pem_write_bio %s", tqsl_openssl_error()); goto dc_end; } } } BIO_free(bio); bio = 0; // Looks like the new file is okay, commit it #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); if (_wunlink(wpath) && errno != ENOENT) { free_wchar(wpath); #else if (unlink(path) && errno != ENOENT) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_deleteCertificate", "unlink err %d", errno); goto dc_end; } #ifdef _WIN32 wchar_t* wnewpath = utf8_to_wchar(newpath); if (_wrename(wnewpath, wpath)) { free_wchar(wpath); free_wchar(wnewpath); #else if (rename(newpath, path)) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_deleteCertificate", "rename err %d", errno); goto dc_end; } #ifdef _WIN32 free_wchar(wpath); free_wchar(wnewpath); #endif dc_ok: rval = 0; tQSL_Error = TQSL_NO_ERROR; dc_end: if (xcerts) { sk_X509_free(xcerts); xcerts = NULL; } if (key) EVP_PKEY_free(key); if (bio) BIO_free(bio); return rval; } /** Get the list of restorable callsign certificates. */ DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates(char ***calls, int *ncall, const char *filter) { vector callsigns; if (tqsl_make_backup_list(filter, callsigns)) { return 1; } *ncall = callsigns.size(); if (*ncall == 0) { if (calls) { *calls = NULL; } return 0; } if (calls == NULL) { return 0; } *calls = reinterpret_cast(calloc(*ncall, sizeof(**calls))); vector::iterator it; char **p = *calls; for (it = callsigns.begin(); it != callsigns.end(); it++) { *p++ = strdup((*it).c_str()); } return 0; } DLLEXPORT void CALLCONVENTION tqsl_freeDeletedCertificateList(char **list, int nloc) { if (!list) return; for (int i = 0; i < nloc; i++) if (list[i]) free(list[i]); if (list) free(list); } /** Restore a deleted callsign certificate by callsign. */ DLLEXPORT int CALLCONVENTION tqsl_restoreCallsignCertificate(const char *callsign) { tqslTrace("tqsl_restoreCallsignCertificate", "callsign = %s", callsign); char backupPath[TQSL_MAX_PATH_LEN]; tqsl_make_backup_path(callsign, backupPath, sizeof backupPath); XMLElement xel; int status = xel.parseFile(backupPath); if (status) { if (errno == ENOENT) { // No file is OK tqslTrace("tqsl_restoreCallsignCertificate", "FNF"); return 0; } strncpy(tQSL_ErrorFile, backupPath, sizeof tQSL_ErrorFile); if (status == XML_PARSE_SYSTEM_ERROR) { tQSL_Error = TQSL_FILE_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_restoreCallsignCertificate", "open error %s: %s", backupPath, strerror(tQSL_Errno)); } else { tqslTrace("tqsl_restoreCallsignCertificate", "syntax error %s", backupPath); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; } return 1; } XMLElement cert; string call; int dxcc = 0; long serial = 0; string privateKey; string publicKey; XMLElementList& ellist = xel.getElementList(); XMLElementList::iterator ep; for (ep = ellist.find("UserCert"); ep != ellist.end(); ep++) { if (ep->first != "UserCert") break; pair rval = ep->second->getAttribute("CallSign"); if (rval.second) call = rval.first; rval = ep->second->getAttribute("serial"); if (rval.second) serial = strtol(rval.first.c_str(), NULL, 10); rval = ep->second->getAttribute("dxcc"); if (rval.second) dxcc = strtol(rval.first.c_str(), NULL, 10); XMLElement el; if (ep->second->getFirstElement("SignedCert", el)) { publicKey = el.getText(); } if (ep->second->getFirstElement("PrivateKey", el)) { privateKey = el.getText(); } } // See if this certificate exists tQSL_Cert *certlist; int ncerts; tqsl_selectCertificates(&certlist, &ncerts, call.c_str(), dxcc, 0, 0, TQSL_SELECT_CERT_EXPIRED|TQSL_SELECT_CERT_SUPERCEDED|TQSL_SELECT_CERT_WITHKEYS); for (int i = 0; i < ncerts; i++) { long s = 0; int keyonly = false; tqsl_getCertificateKeyOnly(certlist[i], &keyonly); if (keyonly) { if (serial != 0) { // A full cert for this was imported continue; } } if (tqsl_getCertificateSerial(certlist[i], &s)) { continue; } if (s == serial) { // Already imported tqsl_freeCertificateList(certlist, ncerts); tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "This callsign certificate is already active and cannot be restored.", sizeof tQSL_CustomError); tqslTrace("tqsl_restoreCallsignCertificate", "certificate already exists"); return 1; } } tqsl_freeCertificateList(certlist, ncerts); int stat = tqsl_importKeyPairEncoded(call.c_str(), "user", privateKey.c_str(), publicKey.c_str()); if (!stat) { // Remove the backup file #ifdef _WIN32 wchar_t* wbpath = utf8_to_wchar(backupPath); _wunlink(wbpath); free_wchar(wbpath); #else unlink(backupPath); #endif } return stat; } /********** END OF PUBLIC API FUNCTIONS **********/ /* Utility functions to manage private data structures */ static int tqsl_check_crq_field(tQSL_Cert cert, char *buf, int bufsiz) { if (tqsl_init()) return 1; if (cert == NULL || buf == NULL || bufsiz < 0 || !tqsl_cert_check(TQSL_API_TO_CERT(cert))) { tqslTrace("tqsl_check_crq_field", "arg err cert=0x%lx buf=0x%lx bufsiz=%d", cert, buf, bufsiz); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (TQSL_API_TO_CERT(cert)->crq == NULL) { if (tqsl_find_matching_key(TQSL_API_TO_CERT(cert)->cert, NULL, &(TQSL_API_TO_CERT(cert)->crq), "", NULL, NULL) && tQSL_Error != TQSL_PASSWORD_ERROR) { tqslTrace("tqsl_check_crq_field", "can't find matching key err %d", tQSL_Error); return 1; } } return 0; } static int tqsl_cert_check(tqsl_cert *p, bool needcert) { if (p != NULL && p->id == 0xCE && (!needcert || p->cert != NULL)) return 1; tQSL_Error = TQSL_ARGUMENT_ERROR; return 0; } static tqsl_cert * tqsl_cert_new() { tqsl_cert *p; p = reinterpret_cast(tqsl_calloc(1, sizeof(tqsl_cert))); if (p != NULL) p->id = 0xCE; return p; } static void tqsl_cert_free(tqsl_cert *p) { if (p == NULL || p->id != 0xCE) return; p->id = 0; if (p->cert != NULL) X509_free(p->cert); if (p->key != NULL) EVP_PKEY_free(p->key); if (p->crq != NULL) tqsl_free_cert_req(p->crq, 0); if (p->pubkey != NULL) delete[] p->pubkey; if (p->privkey != NULL) delete[] p->privkey; tqsl_free(p); } static TQSL_CERT_REQ * tqsl_free_cert_req(TQSL_CERT_REQ *req, int seterr) { if (req == NULL) return NULL; tqsl_free(req); if (seterr) tQSL_Error = seterr; return NULL; } static TQSL_CERT_REQ * tqsl_copy_cert_req(TQSL_CERT_REQ *userreq) { TQSL_CERT_REQ *req; if ((req = reinterpret_cast(tqsl_calloc(1, sizeof(TQSL_CERT_REQ)))) == NULL) { tqslTrace("tqsl_copy_cert_req", "ENOMEM"); errno = ENOMEM; return NULL; } *req = *userreq; return req; } static int tqsl_check_parm(const char *p, const char *parmName) { if (strlen(p) == 0) { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Missing parameter: %s", parmName); tqslTrace("tqsl_check_parm", "error %s", tQSL_CustomError); return 1; } return 0; } static char * tqsl_trim(char *buf) { char lastc; char *cp, *op; /* Trim white space off end of string */ cp = buf + strlen(buf); while (cp != buf) { cp--; if (!isspace(*cp)) break; *cp = 0; } /* Skip past leading whitespace */ for (cp = buf; isspace(*cp); cp++) {} /* Fold runs of white space into single space */ lastc = 0; op = buf; for (; *cp != '\0'; cp++) { if (isspace(*cp)) *cp = ' '; if (*cp != ' ' || lastc != ' ') *op++ = *cp; lastc = *cp; } *op = '\0'; return cp; } /* Filter a list (stack) of X509 certs based on call sign, QSO date and/or * issuer. * * Returns a new stack of matching certs without altering the original stack. * * Note that you don't have to supply any of the criteria. If you supply * none, you;ll just get back an exact copy of the stack. */ CLIENT_STATIC STACK_OF(X509) * tqsl_filter_cert_list(STACK_OF(X509) *sk, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flags) { set superceded_certs; char buf[256], name_buf[256]; TQSL_X509_NAME_ITEM item; X509 *x; STACK_OF(X509) *newsk; int i, ok, len; tQSL_Date qso_date; tqslTrace("tqsl_filter_cert_list", NULL); if (tqsl_init()) return NULL; if ((newsk = sk_X509_new_null()) == NULL) { tqslTrace("tqsl_filter_cert_list", "sk_X509_new_null err %s", tqsl_openssl_error()); return NULL; } tqsl_cert* cp = tqsl_cert_new(); /* Loop through the list of certs */ for (i = 0; i < sk_X509_num(sk); i++) { ok = 1; /* Certificate is selected unless some check says otherwise */ x = sk_X509_value(sk, i); cp->cert = x; /* Check for expired unless asked not to */ if (ok && !(flags & TQSL_SELECT_CERT_EXPIRED)) { int exp = false; if (!tqsl_isCertificateExpired(TQSL_OBJ_TO_API(cp), &exp)) { if (exp) { ok = 0; } } } /* Check for superceded unless asked not to */ if (ok && !(flags & TQSL_SELECT_CERT_SUPERCEDED)) { int sup = false; if (!tqsl_isCertificateSuperceded(TQSL_OBJ_TO_API(cp), &sup)) { if (sup) { ok = 0; } } } /* Compare issuer if asked to */ if (ok && issuer != NULL) { X509_NAME *iss; if ((iss = X509_get_issuer_name(x)) == NULL) ok = 0; if (ok) { item.name_buf = name_buf; item.name_buf_size = sizeof name_buf; item.value_buf = buf; item.value_buf_size = sizeof buf; tqsl_get_name_entry(iss, "organizationName", &item); ok = !strcmp(issuer->organizationName, item.value_buf); } if (ok) { item.name_buf = name_buf; item.name_buf_size = sizeof name_buf; item.value_buf = buf; item.value_buf_size = sizeof buf; tqsl_get_name_entry(iss, "organizationalUnitName", &item); ok = !strcmp(issuer->organizationalUnitName, item.value_buf); } } /* Check call sign if asked */ if (ok && callsign != NULL) { item.name_buf = name_buf; item.name_buf_size = sizeof name_buf; item.value_buf = buf; item.value_buf_size = sizeof buf; if (!tqsl_cert_get_subject_name_entry(x, "AROcallsign", &item)) ok = 0; else ok = !strcmp(callsign, item.value_buf); } /* Check DXCC entity if asked */ if (ok && dxcc > 0) { len = sizeof buf-1; if (tqsl_get_cert_ext(x, "dxccEntity", (unsigned char *)buf, &len, NULL)) { ok = 0; } else { buf[len] = 0; if (dxcc != strtol(buf, NULL, 10)) ok = 0; } } /* Check QSO date if asked */ if (ok && date != NULL && !tqsl_isDateNull(date)) { len = sizeof buf-1; if (tqsl_get_cert_ext(x, "QSONotBeforeDate", (unsigned char *)buf, &len, NULL)) ok = 0; else if (tqsl_initDate(&qso_date, buf)) ok = 0; else if (tqsl_compareDates(date, &qso_date) < 0) ok = 0; } if (ok && date != NULL && !tqsl_isDateNull(date)) { len = sizeof buf-1; if (tqsl_get_cert_ext(x, "QSONotAfterDate", (unsigned char *)buf, &len, NULL)) ok = 0; else if (tqsl_initDate(&qso_date, buf)) ok = 0; else if (tqsl_compareDates(date, &qso_date) > 0) ok = 0; } /* If no check failed, copy this cert onto the new stack */ if (ok) sk_X509_push(newsk, X509_dup(x)); } tqsl_free(cp); return newsk; } /* Set up a read-only BIO from the given file and pass to * tqsl_ssl_load_certs_from_BIO. */ CLIENT_STATIC STACK_OF(X509) * tqsl_ssl_load_certs_from_file(const char *filename) { BIO *in; STACK_OF(X509) *sk; FILE *cfile; tqslTrace("tqsl_ssl_load_certs_from_file", "filename=%s", filename); #ifdef _WIN32 wchar_t* wfilename = utf8_to_wchar(filename); if ((cfile = _wfopen(wfilename, L"r")) == NULL) { free_wchar(wfilename); #else if ((cfile = fopen(filename, "r")) == NULL) { #endif strncpy(tQSL_ErrorFile, filename, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_ssl_load_certs_from_file", "File open error %s", strerror(errno)); return NULL; } #ifdef _WIN32 free(wfilename); #endif if ((in = BIO_new_fp(cfile, 0)) == NULL) { tQSL_Error = TQSL_OPENSSL_ERROR; tqslTrace("tqsl_ssl_load_certs_from_file", "bio_new_fp err %s", tqsl_openssl_error()); return NULL; } sk = tqsl_ssl_load_certs_from_BIO(in); BIO_free(in); fclose(cfile); return sk; } /* Load a set of certs from a file into a stack. The file may contain * other X509 objects (e.g., CRLs), but we'll ignore those. * * Return NULL if there are no certs in the file or on error. */ CLIENT_STATIC STACK_OF(X509) * tqsl_ssl_load_certs_from_BIO(BIO *in) { STACK_OF(X509_INFO) *sk = NULL; STACK_OF(X509) *stack = NULL; X509_INFO *xi; if (tqsl_init()) return NULL; if (!(stack = sk_X509_new_null())) { tqslTrace("tqsl_ssl_load_certs_from_BIO", "bio_new_fp err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } if (!(sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL))) { sk_X509_free(stack); tqslTrace("tqsl_ssl_load_certs_from_BIO", "PEM_X509_INFO_read_bio err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } /* Extract the certs from the X509_INFO objects and put them on a stack */ while (sk_X509_INFO_num(sk)) { xi = sk_X509_INFO_shift(sk); if (xi->x509 != NULL) { sk_X509_push(stack, xi->x509); xi->x509 = NULL; } X509_INFO_free(xi); } /* Empty file isn't really an error, is it? if(!sk_X509_num(stack)) { sk_X509_free(stack); stack = NULL; strcpy(tQSL_CustomError, "No certificates found"); tQSL_Error = TQSL_CUSTOM_ERROR; } */ sk_X509_INFO_free(sk); return stack; } /* Chain-verify a cert against a set of CA and a set of trusted root certs. * * Returns NULL if cert verifies, an error message if it does not. */ CLIENT_STATIC const char * tqsl_ssl_verify_cert(X509 *cert, STACK_OF(X509) *cacerts, STACK_OF(X509) *rootcerts, int purpose, int (*cb)(int ok, X509_STORE_CTX *ctx), STACK_OF(X509) **chain) { X509_STORE *store; X509_STORE_CTX *ctx; int rval; const char *errm; if (cert == NULL) { tqslTrace("tqsl_ssl_verify_cert", "No certificate to verify"); return "No certificate to verify"; } if (tqsl_init()) return NULL; store = X509_STORE_new(); if (store == NULL) { tqslTrace("tqsl_ssl_verify_cert", "out of memory"); return "Out of memory"; } if (cb != NULL) X509_STORE_set_verify_cb(store, cb); ctx = X509_STORE_CTX_new(); if (ctx == NULL) { X509_STORE_free(store); tqslTrace("tqsl_ssl_verify_cert", "store_ctx_new out of memory"); return "Out of memory"; } X509_STORE_CTX_init(ctx, store, cert, cacerts); if (cb != NULL) X509_STORE_CTX_set_verify_cb(ctx, cb); if (rootcerts) X509_STORE_CTX_trusted_stack(ctx, rootcerts); if (purpose >= 0) X509_STORE_CTX_set_purpose(ctx, purpose); X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CB_ISSUER_CHECK); rval = X509_verify_cert(ctx); errm = X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx)); if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_NOT_YET_VALID) { errm = "Your computer's clock is set to a date in the past. This Certificate cannot be loaded until you fix that.\n\n"; } if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED) { errm = "Your computer's clock is set to a date in the future. This Certificate cannot be loaded until you fix that.\n\n"; } #if OPENSSL_VERSION_NUMBER < 0x10100000L #define X509_STORE_CTX_get0_chain(o) ((o)->chain) #endif if (chain) { if (rval && X509_STORE_CTX_get0_chain(ctx)) *chain = sk_X509_dup(X509_STORE_CTX_get0_chain(ctx)); else *chain = 0; } X509_STORE_CTX_free(ctx); if (rval) return NULL; if (errm != NULL) { tqslTrace("tqsl_ssl_verify_cert", "err %s", errm); return errm; } return "Verification failed"; } /* [static] - Grab the data from an X509_NAME_ENTRY and put it into * a TQSL_X509_NAME_ITEM object, checking buffer sizes. * * Returns 0 on error, 1 if okay. * * It's okay for the name_buf or value_buf item of the object to * be NULL; it'll just be skipped. */ static int tqsl_get_name_stuff(X509_NAME_ENTRY *entry, TQSL_X509_NAME_ITEM *name_item) { ASN1_OBJECT *obj; ASN1_STRING *value; const char *val; unsigned int len; if (entry == NULL) { tqslTrace("tqsl_get_name_stuff", "entry=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 0; } obj = X509_NAME_ENTRY_get_object(entry); if (obj == NULL) { tqslTrace("tqsl_get_name_stuff", "get_object err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 0; } if (name_item->name_buf != NULL) { len = i2t_ASN1_OBJECT(name_item->name_buf, name_item->name_buf_size, obj); if (len <= 0 || len > strlen(name_item->name_buf)) { tqslTrace("tqsl_get_name_stuff", "len error len= %d need=%d", len, strlen(name_item->name_buf)); tQSL_Error = TQSL_OPENSSL_ERROR; return 0; } } if (name_item->value_buf != NULL) { value = X509_NAME_ENTRY_get_data(entry); val = (const char *)ASN1_STRING_get0_data(value); strncpy(name_item->value_buf, val, name_item->value_buf_size); name_item->value_buf[name_item->value_buf_size-1] = '\0'; if (strlen(val) > strlen(name_item->value_buf)) { tqslTrace("tqsl_get_name_stuff", "len error len= %d need=%d", strlen(val), strlen(name_item->value_buf)); tQSL_Error = TQSL_OPENSSL_ERROR; return 0; } } return 1; } /* Get a name entry from an X509_NAME by its name. */ CLIENT_STATIC int tqsl_get_name_entry(X509_NAME *name, const char *obj_name, TQSL_X509_NAME_ITEM *name_item) { X509_NAME_ENTRY *entry; int num_entries, i; if (tqsl_init()) return 0; num_entries = X509_NAME_entry_count(name); if (num_entries <= 0) return 0; /* Loop through the name entries */ for (i = 0; i < num_entries; i++) { entry = X509_NAME_get_entry(name, i); if (!tqsl_get_name_stuff(entry, name_item)) continue; if (name_item->name_buf != NULL && !strcmp(name_item->name_buf, obj_name)) { /* Found the wanted entry */ return 1; } } return 0; } /* Get a name entry from a cert's subject name by its name. */ CLIENT_STATIC int tqsl_cert_get_subject_name_entry(X509 *cert, const char *obj_name, TQSL_X509_NAME_ITEM *name_item) { X509_NAME *name; if (cert == NULL) return 0; if (tqsl_init()) return 0; if ((name = X509_get_subject_name(cert)) == NULL) return 0; return tqsl_get_name_entry(name, obj_name, name_item); } /* Initialize the tQSL (really OpenSSL) random number generator * Return 0 on error. */ CLIENT_STATIC int tqsl_init_random() { char fname[TQSL_MAX_PATH_LEN]; static int initialized = 0; if (initialized) return 1; if (RAND_file_name(fname, sizeof fname) != NULL) RAND_load_file(fname, -1); initialized = RAND_status(); if (!initialized) { tqslTrace("tqsl_init_random", "init error %s", tqsl_openssl_error()); tQSL_Error = TQSL_RANDOM_ERROR; } return initialized; } /* Generate an RSA key of at least 1024 bits length */ CLIENT_STATIC EVP_PKEY * tqsl_new_rsa_key(int nbits) { EVP_PKEY *pkey; if (nbits < 1024) { tqslTrace("tqsl_new_rsa_key", "nbits too small %d", nbits); tQSL_Error = TQSL_ARGUMENT_ERROR; return NULL; } if ((pkey = EVP_PKEY_new()) == NULL) { tqslTrace("tqsl_new_rsa_key", "EVP_PKEY_new err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } if (!tqsl_init_random()) /* Unable to init RN generator */ return NULL; RSA *rsa = RSA_new(); if (rsa == NULL) { EVP_PKEY_free(pkey); tqslTrace("tqsl_new_rsa_key", "RSA_new err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } BIGNUM *pubexp = BN_new(); if (pubexp == NULL) { EVP_PKEY_free(pkey); RSA_free(rsa); tqslTrace("tqsl_new_rsa_key", "BN_new err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } if (BN_set_word(pubexp, 0x10001) != 1) { EVP_PKEY_free(pkey); RSA_free(rsa); BN_free(pubexp); tqslTrace("tqsl_new_rsa_key", "BN_set_word err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } if (RSA_generate_key_ex(rsa, nbits, pubexp, NULL) != 1) { EVP_PKEY_free(pkey); RSA_free(rsa); BN_free(pubexp); tqslTrace("tqsl_new_rsa_key", "RSA_generate_key err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } if (!EVP_PKEY_assign_RSA(pkey, rsa)) { EVP_PKEY_free(pkey); RSA_free(rsa); BN_free(pubexp); tqslTrace("tqsl_new_rsa_key", "EVP_PKEY_assign_RSA err %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return NULL; } BN_free(pubexp); return pkey; } /* Output an ADIF field to a file descriptor. */ CLIENT_STATIC int tqsl_write_adif_field(FILE *fp, const char *fieldname, char type, const unsigned char *value, int len) { if (fieldname == NULL) /* Silly caller */ return 0; if (fputc('<', fp) == EOF) return 1; if (fputs(fieldname, fp) == EOF) return 1; if (type && type != ' ' && type != '\0') { if (fputc(':', fp) == EOF) return 1; if (fputc(type, fp) == EOF) return 1; } if (value != NULL && len != 0) { if (len < 0) len = strlen((const char *)value); if (fputc(':', fp) == EOF) return 1; fprintf(fp, "%d>", len); if (fwrite(value, 1, len, fp) != (unsigned int) len) return 1; } else if (fputc('>', fp) == EOF) { return 1; } if (fputs("\n\n", fp) == EOF) return 1; return 0; } /* Output an ADIF field to a BIO */ CLIENT_STATIC int tqsl_bio_write_adif_field(BIO *bio, const char *fieldname, char type, const unsigned char *value, int len) { int bret; if (fieldname == NULL) /* Silly caller */ return 0; if ((bret = BIO_write(bio, "<", 1)) <= 0) return 1; if ((bret = BIO_write(bio, fieldname, strlen(fieldname))) <= 0) return 1; if (type && type != ' ' && type != '\0') { if ((bret = BIO_write(bio, ":", 1)) <= 0) return 1; if ((bret = BIO_write(bio, &type, 1)) <= 0) return 1; } if (value != NULL && len != 0) { if (len < 0) len = strlen((const char *)value); if ((bret = BIO_write(bio, ":", 1)) <= 0) return 1; char numbuf[20]; snprintf(numbuf, sizeof numbuf, "%d>", len); if ((bret = BIO_write(bio, numbuf, strlen(numbuf))) <= 0) return 1; if ((bret = BIO_write(bio, value, len)) != len) return 1; } else if ((bret = BIO_write(bio, ">", 1)) <= 0) { return 1; } if ((bret = BIO_write(bio, "\n\n", 2)) <= 0) return 1; return 0; } static int tqsl_self_signed_is_ok(int ok, X509_STORE_CTX *ctx) { if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) return 1; if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_UNTRUSTED) return 1; return ok; } static int tqsl_expired_is_ok(int ok, X509_STORE_CTX *ctx) { if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED || X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_UNTRUSTED) return 1; return ok; } static char * tqsl_make_cert_path(const char *filename, char *path, int size) { strncpy(path, tQSL_BaseDir, size); #ifdef _WIN32 strncat(path, "\\certs", size - strlen(path)); wchar_t* wpath = utf8_to_wchar(path); if (MKDIR(wpath, 0700) && errno != EEXIST) { free_wchar(wpath); #else strncat(path, "/certs", size - strlen(path)); if (MKDIR(path, 0700) && errno != EEXIST) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_make_cert_path", "Making path %s failed with %s", path, strerror(errno)); return NULL; } #ifdef _WIN32 free_wchar(wpath); strncat(path, "\\", size - strlen(path)); #else strncat(path, "/", size - strlen(path)); #endif strncat(path, filename, size - strlen(path)); return path; } static int tqsl_clean_call(const char *callsign, char *buf, int size) { if ((static_cast(strlen(callsign))) > size-1) { tQSL_Error = TQSL_BUFFER_ERROR; return 1; } const char *cp; for (cp = callsign; *cp; cp++) { if (!isdigit(*cp) && !isalpha(*cp)) *buf = '_'; else *buf = *cp; ++buf; } *buf = 0; return 0; } static char * tqsl_make_key_path(const char *callsign, char *path, int size) { char fixcall[256]; tqsl_clean_call(callsign, fixcall, sizeof fixcall); strncpy(path, tQSL_BaseDir, size); #ifdef _WIN32 strncat(path, "\\keys", size - strlen(path)); wchar_t* wpath = utf8_to_wchar(path); if (MKDIR(wpath, 0700) && errno != EEXIST) { free_wchar(wpath); #else strncat(path, "/keys", size - strlen(path)); if (MKDIR(path, 0700) && errno != EEXIST) { #endif strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_make_key_path", "Making path %s failed with %s", path, strerror(errno)); return 0; } #ifdef _WIN32 free_wchar(wpath); strncat(path, "\\", size - strlen(path)); #else strncat(path, "/", size - strlen(path)); #endif strncat(path, fixcall, size - strlen(path)); return path; } static char * tqsl_make_backup_path(const char *callsign, char *path, int size) { char fixcall[256]; tqsl_clean_call(callsign, fixcall, sizeof fixcall); strncpy(path, tQSL_BaseDir, size); #ifdef _WIN32 strncat(path, "\\certtrash", size - strlen(path)); wchar_t* wpath = utf8_to_wchar(path); if (MKDIR(wpath, 0700) && errno != EEXIST) { free_wchar(wpath); #else strncat(path, "/certtrash", size - strlen(path)); if (MKDIR(path, 0700) && errno != EEXIST) { #endif strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_make_backup_path", "Making path %s failed with %s", path, strerror(errno)); return 0; } #ifdef _WIN32 free_wchar(wpath); strncat(path, "\\", size - strlen(path)); #else strncat(path, "/", size - strlen(path)); #endif strncat(path, fixcall, size - strlen(path)); return path; } static int tqsl_handle_root_cert(const char *pem, X509 *x, int (*cb)(int, const char *, void *), void *userdata) { const char *cp; /* Verify self-signature on the root certificate */ if ((cp = tqsl_ssl_verify_cert(x, NULL, NULL, 0, &tqsl_self_signed_is_ok)) != NULL) { strncpy(tQSL_CustomError, cp, sizeof tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; tqslTrace("tqsl_handle_root_cert", "sig verify err %s", tQSL_CustomError); return 1; } return tqsl_store_cert(pem, x, "root", TQSL_CERT_CB_ROOT, false, cb, userdata); } static int tqsl_ssl_error_is_nofile() { if (tQSL_Error == TQSL_SYSTEM_ERROR && tQSL_Errno == ENOENT) return 1; return 0; } static int tqsl_handle_ca_cert(const char *pem, X509 *x, int (*cb)(int, const char *, void *), void *userdata) { STACK_OF(X509) *root_sk; char rootpath[TQSL_MAX_PATH_LEN]; const char *cp; tqsl_make_cert_path("root", rootpath, sizeof rootpath); if ((root_sk = tqsl_ssl_load_certs_from_file(rootpath)) == NULL) { if (!tqsl_ssl_error_is_nofile()) { tqslTrace("tqsl_handle_ca_cert", "error not nofile - %d", errno); return 1; } } cp = tqsl_ssl_verify_cert(x, NULL, root_sk, 0, &tqsl_expired_is_ok); sk_X509_free(root_sk); if (cp) { strncpy(tQSL_CustomError, cp, sizeof tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; tqslTrace("tqsl_handle_ca_cert", "verify error %s", tQSL_CustomError); return 1; } return tqsl_store_cert(pem, x, "authorities", TQSL_CERT_CB_CA, false, cb, userdata); } static int tqsl_handle_user_cert(const char *cpem, X509 *x, int (*cb)(int, const char *, void *), void *userdata) { STACK_OF(X509) *root_sk, *ca_sk; char rootpath[TQSL_MAX_PATH_LEN], capath[TQSL_MAX_PATH_LEN]; char pem[sizeof tqsl_static_buf]; const char *cp; strncpy(pem, cpem, sizeof pem); /* Match the public key in the supplied certificate with a * private key in the key store. */ if (tqsl_find_matching_key(x, NULL, NULL, "", NULL, NULL)) { if (tQSL_Error != TQSL_PASSWORD_ERROR) { tqslTrace("tqsl_handle_user_cert", "match error %s", tqsl_openssl_error()); return 1; } tQSL_Error = TQSL_NO_ERROR; /* clear error */ } /* Check the chain of authority back to a trusted root */ tqsl_make_cert_path("root", rootpath, sizeof rootpath); if ((root_sk = tqsl_ssl_load_certs_from_file(rootpath)) == NULL) { if (!tqsl_ssl_error_is_nofile()) { tqslTrace("tqsl_handle_user_cert", "Error loading certs %s", tqsl_openssl_error()); return 1; } } tqsl_make_cert_path("authorities", capath, sizeof capath); if ((ca_sk = tqsl_ssl_load_certs_from_file(capath)) == NULL) { if (!tqsl_ssl_error_is_nofile()) { sk_X509_free(root_sk); tqslTrace("tqsl_handle_user_cert", "Error loading authorities %s", tqsl_openssl_error()); return 1; } } cp = tqsl_ssl_verify_cert(x, ca_sk, root_sk, 0, &tqsl_expired_is_ok); sk_X509_free(ca_sk); sk_X509_free(root_sk); if (cp) { strncpy(tQSL_CustomError, cp, sizeof tQSL_CustomError); tQSL_Error = TQSL_CUSTOM_ERROR; tqslTrace("tqsl_handle_user_cert", "verify error %s", cp); return 1; } return tqsl_store_cert(pem, x, "user", TQSL_CERT_CB_USER, false, cb, userdata); } CLIENT_STATIC int tqsl_store_cert(const char *pem, X509 *cert, const char *certfile, int type, bool force, int (*cb)(int, const char *, void *), void *userdata) { STACK_OF(X509) *sk; char path[TQSL_MAX_PATH_LEN]; char issuer[256]; char name[256]; char value[256]; FILE *out; BIGNUM *bserial, *oldserial; string subjid, msg, callsign; TQSL_X509_NAME_ITEM item; int len, rval; tQSL_Date newExpires; string stype = "Unknown"; const ASN1_TIME *tm; if (type == TQSL_CERT_CB_ROOT) { stype = "Trusted Root Authority"; } else if (type == TQSL_CERT_CB_CA) { stype = "Certificate Authority"; } else if (type == TQSL_CERT_CB_USER) { stype = "Callsign"; // Invalidate the cached user certs if (xcerts != NULL) { sk_X509_free(xcerts); xcerts = NULL; } } tqsl_make_cert_path(certfile, path, sizeof path); item.name_buf = name; item.name_buf_size = sizeof name; item.value_buf = value; item.value_buf_size = sizeof value; if (tqsl_cert_get_subject_name_entry(cert, "AROcallsign", &item)) { // Subject contains a call sign (probably a user cert) callsign = value; strncpy(ImportCall, callsign.c_str(), sizeof(tQSL_ImportCall)); tQSL_ImportSerial = ASN1_INTEGER_get(X509_get_serialNumber(cert)); subjid = string(" ") + value; tm = X509_get_notAfter(cert); if (tm) { tqsl_get_asn1_date(tm, &newExpires); } else { newExpires.year = 9999; newExpires.month = 1; newExpires.day = 1; } if (tqsl_cert_get_subject_name_entry(cert, "commonName", &item)) subjid += string(" (") + value + ")"; len = sizeof value-1; if (!tqsl_get_cert_ext(cert, "dxccEntity", (unsigned char *)value, &len, NULL)) { value[len] = 0; subjid += string(" DXCC = ") + value; } } else if (tqsl_cert_get_subject_name_entry(cert, "organizationName", &item)) { // Subject contains an organization (probably a CA or root CA cert) subjid = string(" ") + value; if (tqsl_cert_get_subject_name_entry(cert, "organizationalUnitName", &item)) subjid += string(" ") + value; } if (subjid == "") { // If haven't found a displayable subject name we understand, use the raw DN X509_NAME_oneline(X509_get_subject_name(cert), issuer, sizeof issuer); subjid = string(" ") + issuer; } X509_NAME_oneline(X509_get_issuer_name(cert), issuer, sizeof issuer); /* Check for dupes */ if ((sk = tqsl_ssl_load_certs_from_file(path)) == NULL) { if (!tqsl_ssl_error_is_nofile()) { tqslTrace("tqsl_store_cert", "unexpected openssl err %s", tqsl_openssl_error()); return 1; /* Unexpected OpenSSL error */ } } /* Check each certificate */ if (sk != NULL) { int i, n; tQSL_Date expires; bserial = BN_new(); ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bserial); n = sk_X509_num(sk); for (i = 0; i < n; i++) { char buf[256]; X509 *x; const char *cp; x = sk_X509_value(sk, i); cp = X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf); if (cp != NULL && !strcmp(cp, issuer)) { oldserial = BN_new(); ASN1_INTEGER_to_BN(X509_get_serialNumber(x), oldserial); int result = BN_ucmp(bserial, oldserial); BN_free(oldserial); if (result == 0) break; /* We have a match */ } if (!force && type == TQSL_CERT_CB_USER) { // Don't check for newer certs on restore item.name_buf = name; item.name_buf_size = sizeof name; item.value_buf = value; item.value_buf_size = sizeof value; if (tqsl_cert_get_subject_name_entry(x, "AROcallsign", &item)) { if (value == callsign) { /* * If it's another cert for * this call, is it older? */ tm = X509_get_notAfter(x); if (tm) { tqsl_get_asn1_date(tm, &expires); } else { expires.year = 0; expires.month = 0; expires.day = 0; } if (tqsl_compareDates(&newExpires, &expires) < 0) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "A newer certificate for this callsign is already installed", sizeof tQSL_CustomError); tqslTrace("tqsl_load_cert", tQSL_CustomError); BN_free(bserial); sk_X509_free(sk); return 1; } } } } } BN_free(bserial); sk_X509_free(sk); if (i < n) { /* Have a match -- cert is already in the file */ if (cb != NULL) { int rval; string msg = "Duplicate " + stype + " certificate: " + subjid; rval = (*cb)(TQSL_CERT_CB_RESULT | type | TQSL_CERT_CB_DUPLICATE, msg.c_str(), userdata); if (rval) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "Duplicate Callsign certificate", sizeof tQSL_CustomError); tqslTrace("tqsl_load_cert", tQSL_CustomError); return 1; } } if (tQSL_Error == 0) { tQSL_Error = TQSL_CERT_ERROR; } return 1; } } /* Cert is not a duplicate. Append it to the certificate file */ if (cb != NULL) { msg = "Adding " + stype + " Certificate for: " + subjid; tqslTrace("tqsl_load_cert", msg.c_str()); rval = (*cb)(TQSL_CERT_CB_MILESTONE | type | TQSL_CERT_CB_PROMPT, msg.c_str(), userdata); if (rval) { tqslTrace("tqsl_load_cert", "operator aborted"); tQSL_Error = TQSL_OPERATOR_ABORT; return 1; } } #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); if ((out = _wfopen(wpath, L"a")) == NULL) { free_wchar(wpath); #else if ((out = fopen(path, "a")) == NULL) { #endif strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_load_cert", "opening file err %s", strerror(errno)); return 1; } #ifdef _WIN32 free_wchar(wpath); #endif // Make sure there's always a newline between certs size_t pemlen = strlen(pem); if (fwrite("\n", 1, 1, out) != 1 || fwrite(pem, 1, pemlen, out) != pemlen) { strncpy(tQSL_ErrorFile, certfile, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_load_cert", "writing file err %s", strerror(errno)); return 1; } if (fclose(out) == EOF) { strncpy(tQSL_ErrorFile, certfile, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_load_cert", "writing file err %s", strerror(errno)); return 1; } msg = "Loaded: " + subjid; if (cb) rval = (*cb)(TQSL_CERT_CB_RESULT | type | TQSL_CERT_CB_LOADED, msg.c_str(), userdata); else rval = 0; if (rval) { tQSL_Error = TQSL_OPERATOR_ABORT; return 1; } strncpy(tQSL_ImportCall, ImportCall, sizeof tQSL_ImportCall); return 0; } static int pw_aborted; static int fixed_password_callback(char *buf, int bufsiz, int verify, void *userdata) { pw_aborted = 0; if (userdata != NULL) strncpy(buf, reinterpret_cast(userdata), bufsiz); else buf[0] = 0; return strlen(buf); } static void *prompt_userdata; static int prompted_password_callback(char *buf, int bufsiz, int verify, void *userfunc) { pw_aborted = 0; if (userfunc != NULL) { int (*cb)(char *, int, void *) = (int (*)(char *, int, void *))userfunc; if ((*cb)(buf, bufsiz, prompt_userdata)) { pw_aborted = 1; return 0; } } else { buf[0] = 0; } return strlen(buf); } static tQSL_ADIF keyf_adif = 0; static int tqsl_open_key_file(const char *path) { if (keyf_adif) tqsl_endADIF(&keyf_adif); return tqsl_beginADIF(&keyf_adif, path); } static int tqsl_read_key(map& fields) { TQSL_ADIF_GET_FIELD_ERROR adif_status; tqsl_adifFieldResults field; static tqsl_adifFieldDefinitions adif_fields[] = { { "PUBLIC_KEY", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "PRIVATE_KEY", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "CALLSIGN", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_PROVIDER", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_PROVIDER_UNIT", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_ADDRESS1", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_ADDRESS2", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_CITY", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_STATE", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_POSTAL", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_COUNTRY", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_DXCC_ENTITY", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_QSO_NOT_BEFORE", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "TQSL_CRQ_QSO_NOT_AFTER", "", TQSL_ADIF_RANGE_TYPE_NONE, 2000, 0, 0, NULL, NULL }, { "DELETED", "", TQSL_ADIF_RANGE_TYPE_NONE, 200, 0, 0, NULL, NULL }, { "eor", "", TQSL_ADIF_RANGE_TYPE_NONE, 0, 0, 0, NULL, NULL }, { "", "", TQSL_ADIF_RANGE_TYPE_NONE, 0, 0, 0, NULL, NULL }, }; fields.clear(); do { if (tqsl_getADIFField(keyf_adif, &field, &adif_status, adif_fields, notypes, &tqsl_static_alloc)) return 1; if (adif_status == TQSL_ADIF_GET_FIELD_EOF) return 1; if (!strcasecmp(field.name, "eor")) return 0; if (adif_status == TQSL_ADIF_GET_FIELD_SUCCESS) { char *cp; for (cp = field.name; *cp; cp++) *cp = toupper(*cp); fields[field.name] = reinterpret_cast(field.data); } } while (adif_status == TQSL_ADIF_GET_FIELD_SUCCESS || adif_status == TQSL_ADIF_GET_FIELD_NO_NAME_MATCH); tQSL_Error = TQSL_ADIF_ERROR; return 1; } static void tqsl_close_key_file(void) { tqsl_endADIF(&keyf_adif); } static int tqsl_replace_key(const char *callsign, const char *path, map& newfields, int (*cb)(int, const char *, void *), void *userdata) { char newpath[TQSL_MAX_PATH_LEN]; char savepath[TQSL_MAX_PATH_LEN]; #ifdef _WIN32 wchar_t* wnewpath = NULL; #endif map fields; vector< map > records; vector< map >::iterator it; EVP_PKEY *new_key = NULL, *key = NULL; BIO *bio = 0; FILE *out = 0; int rval = 1; if ((bio = BIO_new_mem_buf(reinterpret_cast(const_cast(newfields["PUBLIC_KEY"].c_str())), newfields["PUBLIC_KEY"].length())) == NULL) { tqslTrace("tqsl_replace_key", "BIO_new_mem_buf err %s", tqsl_openssl_error()); goto trk_end; } if ((new_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { tqslTrace("tqsl_replace_key", "PEM_read_bio_PUBKEY err %s", tqsl_openssl_error()); goto trk_end; } BIO_free(bio); bio = 0; if (tqsl_open_key_file(path)) { if (tQSL_Error != TQSL_SYSTEM_ERROR || tQSL_Errno != ENOENT) { tqslTrace("tqsl_replace_key", "error opening key file %s: %s", path, strerror(tQSL_Errno)); return 1; } tQSL_Error = TQSL_NO_ERROR; } while (tqsl_read_key(fields) == 0) { vectorseen; bool match = false; for (size_t i = 0; i < seen.size(); i++) { if (seen[i] == fields["PUBLIC_KEY"]) { match = true; break; } } if (match) continue; // Drop dupes seen.push_back(fields["PUBLIC_KEY"]); if ((bio = BIO_new_mem_buf(reinterpret_cast(const_cast(fields["PUBLIC_KEY"].c_str())), fields["PUBLIC_KEY"].length())) == NULL) { tqslTrace("tqsl_replace_key", "BIO_new_mem_buf error %s", tqsl_openssl_error()); goto trk_end; } if ((key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { tqslTrace("tqsl_replace_key", "Pem_read_bio_rsa_pubkey error %s", tqsl_openssl_error()); goto trk_end; } BIO_free(bio); bio = NULL; if (EVP_PKEY_cmp(key, new_key) == 1) { fields["DELETED"] = "True"; // Mark as deleted } records.push_back(fields); } tqsl_close_key_file(); if (newfields["PRIVATE_KEY"] != "") records.push_back(newfields); strncpy(newpath, path, sizeof newpath); strncat(newpath, ".new", sizeof newpath - strlen(newpath)-1); strncpy(savepath, path, sizeof savepath); strncat(savepath, ".save", sizeof savepath - strlen(savepath)-1); #ifdef _WIN32 wnewpath = utf8_to_wchar(newpath); if ((out = _wfopen(wnewpath, TQSL_OPEN_WRITE)) == NULL) { free_wchar(wnewpath); #else if ((out = fopen(newpath, TQSL_OPEN_WRITE)) == NULL) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_replace_key", "open file %s: %s", newpath, strerror(tQSL_Errno)); goto trk_end; } for (it = records.begin(); it != records.end(); it++) { map::iterator mit; for (mit = it->begin(); mit != it->end(); mit++) { if (tqsl_write_adif_field(out, mit->first.c_str(), 0, (const unsigned char *)mit->second.c_str(), -1)) { tqslTrace("tqsl_replace_key", "error writing %s", strerror(tQSL_Errno)); #ifdef _WIN32 free_wchar(wnewpath); #endif goto trk_end; } } tqsl_write_adif_field(out, "eor", 0, NULL, 0); } if (fclose(out) == EOF) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_replace_key", "error closing %s", strerror(tQSL_Errno)); #ifdef _WIN32 free_wchar(wnewpath); #endif goto trk_end; } out = 0; /* Output file looks okay. Replace the old file with the new one. */ #ifdef _WIN32 wchar_t* wsavepath = utf8_to_wchar(savepath); if (_wunlink(wsavepath) && errno != ENOENT) { free_wchar(wsavepath); free_wchar(wnewpath); #else if (unlink(savepath) && errno != ENOENT) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_replace_key", "unlink file %s: %s", savepath, strerror(tQSL_Errno)); goto trk_end; } #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); if (_wrename(wpath, wsavepath) && errno != ENOENT) { free_wchar(wpath); free_wchar(wsavepath); free_wchar(wnewpath); #else if (rename(path, savepath) && errno != ENOENT) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_replace_key", "rename file %s->%s: %s", path, savepath, strerror(tQSL_Errno)); goto trk_end; } #ifdef _WIN32 if (_wrename(wnewpath, wpath)) { free_wchar(wnewpath); free_wchar(wpath); free_wchar(wsavepath); #else if (rename(newpath, path)) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_replace_key", "rename file %s->%s: %s", newpath, path, strerror(tQSL_Errno)); goto trk_end; } #ifdef _WIN32 free_wchar(wnewpath); free_wchar(wpath); free_wchar(wsavepath); #endif tqslTrace("tqsl_replace_key", "loaded private key for: %s", callsign); if (cb) { string msg = string("Loaded private key for: ") + callsign; (*cb)(TQSL_CERT_CB_RESULT + TQSL_CERT_CB_PKEY + TQSL_CERT_CB_LOADED, msg.c_str(), userdata); } rval = 0; trk_end: tqsl_close_key_file(); if (out) fclose(out); if (new_key) EVP_PKEY_free(new_key); if (key) EVP_PKEY_free(key); if (bio) BIO_free(bio); return rval; } static int tqsl_unlock_key(const char *pem, EVP_PKEY **keyp, const char *password, int (*cb)(char *, int, void *), void *userdata) { RSA *prsa = NULL; BIO *bio; int (*ssl_cb)(char *, int, int, void *) = NULL; void *cb_user = NULL; long e; int rval = 1; if ((bio = BIO_new_mem_buf(reinterpret_cast(const_cast(pem)), strlen(pem))) == NULL) { tqslTrace("tqsl_unlock_key", "BIO_new_mem_buf err %s", tqsl_openssl_error()); goto err; } if (password != NULL) { ssl_cb = &fixed_password_callback; cb_user = reinterpret_cast(const_cast(password)); } else if (cb != NULL) { prompt_userdata = userdata; ssl_cb = &prompted_password_callback; cb_user = reinterpret_cast(cb); } if ((prsa = PEM_read_bio_RSAPrivateKey(bio, NULL, ssl_cb, cb_user)) == NULL) { tqslTrace("tqsl_unlock_key", "PEM_read_bio_RSAPrivateKey err %s", tqsl_openssl_error()); goto err; } if (keyp != NULL) { if ((*keyp = EVP_PKEY_new()) == NULL) goto err; EVP_PKEY_assign_RSA(*keyp, prsa); prsa = NULL; } rval = 0; goto end; err: e = ERR_peek_error(); if ((ERR_GET_LIB(e) == ERR_LIB_EVP && ERR_GET_REASON(e) == EVP_R_BAD_DECRYPT) #if OPENSSL_VERSION_MAJOR >= 3 || (ERR_GET_LIB(e) == ERR_LIB_PROV && ERR_GET_REASON(e) == PROV_R_BAD_DECRYPT) #endif || (ERR_GET_LIB(e) == ERR_LIB_PEM && ERR_GET_REASON(e) == PEM_R_BAD_PASSWORD_READ) || (ERR_GET_LIB(e) == ERR_LIB_PKCS12 && ERR_GET_REASON(e) == PKCS12_R_PKCS12_CIPHERFINAL_ERROR)) { tqsl_getErrorString(); /* clear error */ tQSL_Error = pw_aborted ? TQSL_OPERATOR_ABORT : TQSL_PASSWORD_ERROR; ERR_clear_error(); #if OPENSSL_VERSION_MAJOR >= 3 // Handle corrupted key } else if (ERR_GET_LIB(e) == ERR_LIB_OSSL_DECODER && ERR_GET_REASON(e) == ERR_R_UNSUPPORTED) { ERR_clear_error(); strncpy(tQSL_ErrorFile, "Private key file is corrupt", sizeof tQSL_ErrorFile); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; #endif } else { tQSL_Error = TQSL_OPENSSL_ERROR; } tqslTrace("tqsl_unlock_key", "Key read error %d", tQSL_Error); end: if (prsa != NULL) RSA_free(prsa); if (bio != NULL) BIO_free(bio); return rval; } static int tqsl_find_matching_key(X509 *cert, EVP_PKEY **keyp, TQSL_CERT_REQ **crq, const char *password, int (*cb)(char *, int, void *), void *userdata) { char path[TQSL_MAX_PATH_LEN]; char aro[256]; TQSL_X509_NAME_ITEM item = { path, sizeof path, aro, sizeof aro }; EVP_PKEY *cert_key = NULL; EVP_PKEY *curkey = NULL; int rval = 0; int match = 0; int deleted = 0; BIO *bio = NULL; map fields; bool finddeleted = false; if (keyp != NULL) *keyp = NULL; if (!tqsl_cert_get_subject_name_entry(cert, "AROcallsign", &item)) { tqslTrace("tqsl_find_matching_key", "get subj name err %d", tQSL_Error); return 1; } tQSL_ImportSerial = ASN1_INTEGER_get(X509_get_serialNumber(cert)); if (!tqsl_make_key_path(aro, path, sizeof path)) { tqslTrace("tqsl_find_matching_key", "key path err %d", tQSL_Error); rval = 1; goto end_nokey; } strncpy(ImportCall, aro, sizeof ImportCall); again: if (tqsl_open_key_file(path)) { /* Friendly error for file not found */ if (tQSL_Error == TQSL_SYSTEM_ERROR) { if (tQSL_Errno == ENOENT) { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "You can only open this callsign certificate by running TQSL on the computer where you created the certificate request for %s.", aro); } else { snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Can't open %s: %s\nThis file is needed to open this callsign certificate.", aro, strerror(tQSL_Errno)); } tQSL_Error = TQSL_CUSTOM_ERROR; tqslTrace("tqsl_find_matching_key", "opening file path err %s", tQSL_CustomError); } return 1; } if ((cert_key = X509_get_pubkey(cert)) == NULL) { tqslTrace("tqsl_find_matching_key", "error getting public key %s", tqsl_openssl_error()); goto err; } if (crq != NULL) { if (*crq != NULL) tqsl_free_cert_req(*crq, 0); *crq = reinterpret_cast(tqsl_calloc(1, sizeof(TQSL_CERT_REQ))); } while (!tqsl_read_key(fields)) { /* Compare the keys */ if ((bio = BIO_new_mem_buf(reinterpret_cast(const_cast(fields["PUBLIC_KEY"].c_str())), fields["PUBLIC_KEY"].length())) == NULL) { tqslTrace("tqsl_find_matching_key", "BIO_new_mem_buf err %s", tqsl_openssl_error()); goto err; } if ((curkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { tqslTrace("tqsl_find_matching_key", "PEM_read_bio_RSA_PUBKEY err %s", tqsl_openssl_error()); goto err; } BIO_free(bio); bio = NULL; if (EVP_PKEY_cmp(curkey, cert_key) == 1) { if (fields["DELETED"] == "True") { if (finddeleted) { match = 1; deleted = 1; } } else { match = 1; } } if (match) { /* We have a winner */ if (tqsl_unlock_key(fields["PRIVATE_KEY"].c_str(), keyp, password, cb, userdata)) { tqslTrace("tqsl_find_matching_key", "tqsl_unlock_key err %d", tQSL_Error); rval = 1; goto end; } if (crq != NULL) { tQSL_Error = TQSL_BUFFER_ERROR; if (!safe_strncpy((*crq)->providerName, fields["TQSL_CRQ_PROVIDER"].c_str(), sizeof (*crq)->providerName)) goto end; if (!safe_strncpy((*crq)->providerUnit, fields["TQSL_CRQ_PROVIDER_UNIT"].c_str(), sizeof (*crq)->providerUnit)) goto end; if (!safe_strncpy((*crq)->address1, fields["TQSL_CRQ_ADDRESS1"].c_str(), sizeof (*crq)->address1)) goto end; if (!safe_strncpy((*crq)->address2, fields["TQSL_CRQ_ADDRESS2"].c_str(), sizeof (*crq)->address2)) goto end; if (!safe_strncpy((*crq)->city, fields["TQSL_CRQ_CITY"].c_str(), sizeof (*crq)->city)) goto end; if (!safe_strncpy((*crq)->state, fields["TQSL_CRQ_STATE"].c_str(), sizeof (*crq)->state)) goto end; if (!safe_strncpy((*crq)->postalCode, fields["TQSL_CRQ_POSTAL"].c_str(), sizeof (*crq)->postalCode)) goto end; if (!safe_strncpy((*crq)->country, fields["TQSL_CRQ_COUNTRY"].c_str(), sizeof (*crq)->country)) goto end; tQSL_Error = 0; } rval = 0; break; } } if (match) goto end; if (!finddeleted) { finddeleted = true; tqsl_close_key_file(); goto again; } tqslTrace("tqsl_find_matching_key", "No matching private key found"); rval = 1; tQSL_Error = TQSL_CERT_NOT_FOUND; strncpy(tQSL_ImportCall, ImportCall, sizeof tQSL_ImportCall); goto end; err: rval = 1; tQSL_Error = TQSL_OPENSSL_ERROR; end: tqsl_close_key_file(); if (deleted) { int savedErr = tQSL_Error; tqsl_clear_deleted(aro, path, cert_key); tQSL_Error = savedErr; } end_nokey: if (curkey != NULL) EVP_PKEY_free(curkey); if (bio != NULL) BIO_free(bio); if (cert_key != NULL) EVP_PKEY_free(cert_key); // if (in != NULL) // fclose(in); if (rval == 0) { strncpy(tQSL_ImportCall, ImportCall, sizeof tQSL_ImportCall); } return rval; } static int tqsl_make_key_list(vector< map > & keys) { keys.clear(); string path = tQSL_BaseDir; #ifdef _WIN32 path += "\\keys"; wchar_t* wpath = utf8_to_wchar(path.c_str()); MKDIR(wpath, 0700); #else path += "/keys"; MKDIR(path.c_str(), 0700); #endif #ifdef _WIN32 WDIR *dir = wopendir(wpath); free_wchar(wpath); #else DIR *dir = opendir(path.c_str()); #endif if (dir == NULL) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_make_key_list", "Opendir %s error %s", path.c_str(), strerror(errno)); return 1; } #ifdef _WIN32 struct wdirent *ent; #else struct dirent *ent; #endif int rval = 0; int savedError = 0; int savedErrno = 0; char *savedFile = NULL; #ifdef _WIN32 while ((ent = wreaddir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; if (wcsstr(ent->d_name, L".save") || wcsstr(ent->d_name, L".new")) continue; char dname[TQSL_MAX_PATH_LEN]; wcstombs(dname, ent->d_name, TQSL_MAX_PATH_LEN); string filename = path + "\\" + dname; #else while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; if (strstr(ent->d_name, ".save") || strstr(ent->d_name, ".new")) continue; string filename = path + "/" + ent->d_name; #endif char fixcall[256]; #ifdef _WIN32 struct _stat32 s; wchar_t* wfilename = utf8_to_wchar(filename.c_str()); if (_wstat32(wfilename, &s) == 0) { if (S_ISDIR(s.st_mode)) { free_wchar(wfilename); continue; // If it's a directory, skip it. } } #else struct stat s; if (stat(filename.c_str(), &s) == 0) { if (S_ISDIR(s.st_mode)) continue; // If it's a directory, skip it. } #endif if (!tqsl_open_key_file(filename.c_str())) { vectorseen; map fields; while (!tqsl_read_key(fields)) { if (fields["DELETED"] == "True") continue; // Skip this one bool match = false; for (size_t i = 0; i < seen.size(); i++) { if (seen[i] == fields["PUBLIC_KEY"]) { match = true; break; } } if (match) continue; seen.push_back(fields["PUBLIC_KEY"]); if (tqsl_clean_call(fields["CALLSIGN"].c_str(), fixcall, sizeof fixcall)) { rval = 1; savedError = tQSL_Error; savedErrno = tQSL_Errno; if (savedFile) free(savedFile); savedFile = strdup(tQSL_ErrorFile); continue; // Keep looking for keys } #ifdef _WIN32 wchar_t* wfixcall = utf8_to_wchar(fixcall); if (wcscmp(wfixcall, ent->d_name)) { free_wchar(wfixcall); #else if (strcasecmp(fixcall, ent->d_name)) { #endif continue; } keys.push_back(fields); } tqsl_close_key_file(); } else { rval = 1; // Unable to open - remember that savedErrno = tQSL_Errno; savedError = tQSL_Error; if (savedFile) free(savedFile); savedFile = strdup(tQSL_ErrorFile); } } #ifdef _WIN32 _wclosedir(dir); #else closedir(dir); #endif if (rval) { tQSL_Error = savedError; tQSL_Errno = savedErrno; if (savedFile) { strncpy(tQSL_ErrorFile, savedFile, sizeof tQSL_ErrorFile); free(savedFile); } tqslTrace("tqsl_make_key_list", "error %s %s", tQSL_ErrorFile, strerror(tQSL_Errno)); } return rval; } static int tqsl_get_cert_ext(X509 *cert, const char *ext, unsigned char *userbuf, int *buflen, int *crit) { int i, n, datasiz; X509_EXTENSION *xe; char buf[256]; ASN1_OBJECT *obj; ASN1_OCTET_STRING *data; if (tqsl_init()) return 1; if (cert == NULL || ext == NULL || userbuf == NULL || buflen == NULL) { tqslTrace("tqsl_get_cert_ext", "arg error cert=0x%lx, ext=0x%lx userbuf=0x%lx, buflen=0x%lx crit=0x%lx", cert, ext, userbuf, buflen, crit); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } n = X509_get_ext_count(cert); for (i = 0; i < n; i++) { xe = X509_get_ext(cert, i); if (xe == NULL) { tqslTrace("tqsl_get_cert_ext", "X509_get_ext error %s", tqsl_openssl_error()); tQSL_Error = TQSL_OPENSSL_ERROR; return 1; } buf[0] = '\0'; obj = X509_EXTENSION_get_object(xe); if (obj) OBJ_obj2txt(buf, sizeof buf, obj, 0); if (strcmp(buf, ext)) continue; /* This is the desired extension */ data = X509_EXTENSION_get_data(xe); if (data != NULL) { datasiz = ASN1_STRING_length(data); if (datasiz > *buflen-1) { tqslTrace("tqsl_get_cert_ext", "buffer len %d needed %d", *buflen, datasiz); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } *buflen = datasiz; if (datasiz) memcpy(userbuf, ASN1_STRING_get0_data(data), datasiz); userbuf[datasiz] = '\0'; } if (crit != NULL) *crit = X509_EXTENSION_get_critical(xe); return 0; } snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Certificate Extension not found: %s", ext); tQSL_Error = TQSL_CUSTOM_ERROR; if (strcmp(ext, "supercededCertificate")) tqslTrace("tqsl_get_cert_ext", "Err %s", tQSL_CustomError); return 1; } CLIENT_STATIC int tqsl_get_asn1_date(const ASN1_TIME *tm, tQSL_Date *date) { char *v; int i; i = tm->length; v = reinterpret_cast(tm->data); if (i >= 14) { for (i = 0; i < 12; i++) if ((v[i] > '9') || (v[i] < '0')) goto err; date->year = (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0'); date->month = (v[4]-'0')*10+(v[5]-'0'); if ((date->month > 12) || (date->month < 1)) goto err; date->day = (v[6]-'0')*10+(v[7]-'0'); } else if (i < 12) { goto err; } else { for (i = 0; i < 10; i++) if ((v[i] > '9') || (v[i] < '0')) goto err; date->year = (v[0]-'0')*10+(v[1]-'0'); if (date->year < 50) date->year+=100; date->year += 1900; date->month = (v[2]-'0')*10+(v[3]-'0'); if ((date->month > 12) || (date->month < 1)) goto err; date->day = (v[4]-'0')*10+(v[5]-'0'); } return 0; err: tqslTrace("tqsl_get_asn1_date", "invalid date"); tQSL_Error = TQSL_INVALID_DATE; return 1; } static char * tqsl_sign_base64_data(tQSL_Cert cert, char *b64data) { int len; static unsigned char sig[256]; int siglen = sizeof sig; if (b64data && !strncmp(b64data, "-----", 5)) { b64data = strchr(b64data, '\n'); if (b64data == NULL) return NULL; b64data++; } len = sizeof tqsl_static_buf; if (tqsl_decodeBase64(b64data, tqsl_static_buf, &len)) return NULL; if (tqsl_signDataBlock(cert, tqsl_static_buf, len, sig, &siglen)) return NULL; if (tqsl_encodeBase64(sig, siglen, reinterpret_cast(tqsl_static_buf), sizeof tqsl_static_buf)) return NULL; return reinterpret_cast(tqsl_static_buf); } static bool safe_strncpy(char *dest, const char *src, int size) { strncpy(dest, src, size); dest[size-1] = 0; return ((static_cast((strlen(src))) < size)); } static string tqsl_cert_status_filename(const char *f = "cert_status.xml") { string s = tQSL_BaseDir; #ifdef _WIN32 s += "\\"; #else s += "/"; #endif s += f; return s; } static int tqsl_load_cert_status_data(XMLElement &xel) { int status = xel.parseFile(tqsl_cert_status_filename().c_str()); if (status) { if (errno == ENOENT) { // No file is OK tqslTrace("tqsl_load_cert_status_data", "FNF"); return 0; } strncpy(tQSL_ErrorFile, tqsl_cert_status_filename().c_str(), sizeof tQSL_ErrorFile); if (status == XML_PARSE_SYSTEM_ERROR) { tQSL_Error = TQSL_FILE_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_load_cert_status_data", "open error %s: %s", tqsl_cert_status_filename().c_str(), strerror(tQSL_Errno)); } else { tqslTrace("tqsl_load_cert_status_data", "syntax error %s", tqsl_cert_status_filename().c_str()); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; } return 1; } return status; } static int tqsl_dump_cert_status_data(XMLElement &xel) { ofstream out; string fn = tqsl_cert_status_filename(); out.exceptions(std::ios::failbit | std::ios::eofbit | std::ios::badbit); try { #ifdef _WIN32 wchar_t* wfn = utf8_to_wchar(fn.c_str()); out.open(wfn); free_wchar(wfn); #else out.open(fn.c_str()); #endif out << xel << endl; out.close(); } catch(exception& x) { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Error writing certificate status file (%s): %s/%s", fn.c_str(), x.what(), strerror(errno)); tqslTrace("tqsl_dump_cert_status_data", "write error %s", tQSL_CustomError); return 1; } return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCertificateStatus(long serial) { XMLElement top_el; if (tqsl_load_cert_status_data(top_el)) return TQSL_CERT_STATUS_UNK; XMLElement sfile; if (top_el.getFirstElement(sfile)) { XMLElement cd; bool ok = sfile.getFirstElement("Cert", cd); while (ok && cd.getElementName() == "Cert") { pair s = cd.getAttribute("serial"); if (s.second && strtol(s.first.c_str(), NULL, 10) == serial) { XMLElement xs; if (cd.getFirstElement("status", xs)) { if (!strcasecmp(xs.getText().c_str(), "Bad serial")) return TQSL_CERT_STATUS_INV; else if (!strcasecmp(xs.getText().c_str(), "Superceded")) return TQSL_CERT_STATUS_SUP; else if (!strcasecmp(xs.getText().c_str(), "Expired")) return TQSL_CERT_STATUS_EXP; else if (!strcasecmp(xs.getText().c_str(), "Unrevoked")) return TQSL_CERT_STATUS_OK; else return TQSL_CERT_STATUS_UNK; } } ok = sfile.getNextElement(cd); } } return TQSL_CERT_STATUS_UNK; } DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus(long serial, const char *status) { if (status == NULL) { tqslTrace("tqsl_setCertificateStatus", "status=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } char sstr[32]; snprintf(sstr, sizeof sstr, "%ld", serial); XMLElement top_el; int stat = tqsl_load_cert_status_data(top_el); if (stat == TQSL_FILE_SYSTEM_ERROR) { tqslTrace("tqsl_setCertificateStatus", "error %d", tQSL_Error); return 1; } XMLElement sfile; if (!top_el.getFirstElement(sfile)) sfile.setElementName("CertStatus"); XMLElementList& ellist = sfile.getElementList(); bool exists = false; XMLElementList::iterator ep; for (ep = ellist.find("Cert"); ep != ellist.end(); ep++) { if (ep->first != "Cert") break; pair rval = ep->second->getAttribute("serial"); if (rval.second && strtol(rval.first.c_str(), NULL, 10) == serial) { exists = true; break; } } XMLElement *cs = new XMLElement("Cert"); cs->setPretext("\n "); XMLElement *se = new XMLElement; se->setPretext(cs->getPretext() + " "); se->setElementName("status"); se->setText(status); cs->addElement(se); cs->setAttribute("serial", sstr); cs->setText("\n "); if (exists) ellist.erase(ep); sfile.addElement(cs); sfile.setText("\n"); return tqsl_dump_cert_status_data(sfile); } static int tqsl_clear_deleted(const char *callsign, const char *path, EVP_PKEY *cert_key) { char newpath[TQSL_MAX_PATH_LEN]; char savepath[TQSL_MAX_PATH_LEN]; #ifdef _WIN32 wchar_t* wnewpath = NULL; #endif map fields; vector< map > records; vector< map >::iterator it; EVP_PKEY *new_key = NULL, *key = NULL; BIO *bio = 0; FILE *out = 0; int rval = 1; if (tqsl_open_key_file(path)) { if (tQSL_Error != TQSL_SYSTEM_ERROR || tQSL_Errno != ENOENT) { tqslTrace("tqsl_clear_deleted", "error opening key file %s: %s", path, strerror(tQSL_Errno)); return 1; } tQSL_Error = TQSL_NO_ERROR; } while (tqsl_read_key(fields) == 0) { if ((bio = BIO_new_mem_buf(reinterpret_cast(const_cast(fields["PUBLIC_KEY"].c_str())), fields["PUBLIC_KEY"].length())) == NULL) { tqslTrace("tqsl_clear_deleted", "BIO_new_mem_buf error %s", tqsl_openssl_error()); goto trk_end; } if ((key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { tqslTrace("tqsl_clear_deleted", "Pem_read_bio_rsa_pubkey error %s", tqsl_openssl_error()); goto trk_end; } BIO_free(bio); bio = NULL; if (EVP_PKEY_cmp(key, cert_key) == 1) { fields["DELETED"] = "False"; } records.push_back(fields); } tqsl_close_key_file(); strncpy(newpath, path, sizeof newpath); strncat(newpath, ".new", sizeof newpath - strlen(newpath)-1); strncpy(savepath, path, sizeof savepath); strncat(savepath, ".save", sizeof savepath - strlen(savepath)-1); #ifdef _WIN32 wnewpath = utf8_to_wchar(newpath); if ((out = _wfopen(wnewpath, TQSL_OPEN_WRITE)) == NULL) { free_wchar(wnewpath); #else if ((out = fopen(newpath, TQSL_OPEN_WRITE)) == NULL) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_clear_deleted", "open file %s: %s", newpath, strerror(tQSL_Errno)); goto trk_end; } for (it = records.begin(); it != records.end(); it++) { map::iterator mit; for (mit = it->begin(); mit != it->end(); mit++) { if (tqsl_write_adif_field(out, mit->first.c_str(), 0, (const unsigned char *)mit->second.c_str(), -1)) { tqslTrace("tqsl_clear_deleted", "error writing %s", strerror(tQSL_Errno)); #ifdef _WIN32 free_wchar(wnewpath); #endif goto trk_end; } } tqsl_write_adif_field(out, "eor", 0, NULL, 0); } if (fclose(out) == EOF) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_clear_deleted", "error closing %s", strerror(tQSL_Errno)); #ifdef _WIN32 free_wchar(wnewpath); #endif goto trk_end; } out = 0; /* Output file looks okay. Replace the old file with the new one. */ #ifdef _WIN32 wchar_t* wsavepath = utf8_to_wchar(savepath); if (_wunlink(wsavepath) && errno != ENOENT) { free_wchar(wsavepath); free_wchar(wnewpath); #else if (unlink(savepath) && errno != ENOENT) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_clear_deleted", "unlink file %s: %s", savepath, strerror(tQSL_Errno)); goto trk_end; } #ifdef _WIN32 wchar_t* wpath = utf8_to_wchar(path); if (_wrename(wpath, wsavepath) && errno != ENOENT) { free_wchar(wpath); free_wchar(wsavepath); free_wchar(wnewpath); #else if (rename(path, savepath) && errno != ENOENT) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_clear_deleted", "rename file %s->%s: %s", path, savepath, strerror(tQSL_Errno)); goto trk_end; } #ifdef _WIN32 if (_wrename(wnewpath, wpath)) { free_wchar(wnewpath); free_wchar(wpath); free_wchar(wsavepath); #else if (rename(newpath, path)) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_clear_deleted", "rename file %s->%s: %s", newpath, path, strerror(tQSL_Errno)); goto trk_end; } #ifdef _WIN32 free_wchar(wnewpath); free_wchar(wpath); free_wchar(wsavepath); #endif rval = 0; trk_end: tqsl_close_key_file(); if (out) fclose(out); if (new_key) EVP_PKEY_free(new_key); if (key) EVP_PKEY_free(key); if (bio) BIO_free(bio); return rval; } static int tqsl_key_exists(const char *callsign, EVP_PKEY *cert_key) { map fields; vector< map >::iterator it; EVP_PKEY *key = NULL; BIO *bio = 0; int rval = 0; char path[TQSL_MAX_PATH_LEN]; if (!tqsl_make_key_path(callsign, path, sizeof path)) { tqslTrace("tqsl_createCertRequest", "make_key_path error %d", errno); return 0; } if (tqsl_open_key_file(path)) { return 0; } while (tqsl_read_key(fields) == 0) { if ((bio = BIO_new_mem_buf(reinterpret_cast(const_cast(fields["PUBLIC_KEY"].c_str())), fields["PUBLIC_KEY"].length())) == NULL) { tqslTrace("tqsl_clear_deleted", "BIO_new_mem_buf error %s", tqsl_openssl_error()); goto trk_end; } if ((key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { tqslTrace("tqsl_clear_deleted", "Pem_read_bio_rsa_pubkey error %s", tqsl_openssl_error()); goto trk_end; } BIO_free(bio); bio = NULL; if (EVP_PKEY_cmp(key, cert_key) == 1) { rval = 1; } } trk_end: tqsl_close_key_file(); if (key) EVP_PKEY_free(key); if (bio) BIO_free(bio); return rval; } /** Save the json results for a given callsign location Detail. */ DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo(const char *callsign, const char *json) { FILE *out; if (callsign == NULL || json == NULL) { tqslTrace("tqsl_saveCallsinLocationInfo", "arg error callsign=0x%lx, json=0x%lx", callsign, json); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } char fixcall[256]; char path[TQSL_MAX_PATH_LEN]; size_t size = sizeof path; tqsl_clean_call(callsign, fixcall, sizeof fixcall); strncpy(path, tQSL_BaseDir, size); #ifdef _WIN32 strncat(path, "\\", size - strlen(path)); #else strncat(path, "/", size - strlen(path)); #endif strncat(path, fixcall, size - strlen(path)); strncat(path, ".json", size - strlen(path)); /* Try opening the output stream */ #ifdef _WIN32 wchar_t* wfilename = utf8_to_wchar(path); if ((out = _wfopen(wfilename, TQSL_OPEN_WRITE)) == NULL) { free_wchar(wfilename); #else if ((out = fopen(path, TQSL_OPEN_WRITE)) == NULL) { #endif strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tqslTrace("tqsl_saveCallsignLocationInfo", "Open file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; return 1; } #ifdef _WIN32 free_wchar(wfilename); #endif if (fputs(json, out) == EOF) { strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tqslTrace("tqsl_createCertRequest", "Write request file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; return 1; } if (fclose(out) == EOF) { strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_saveCallsignLocationInfo", "write error %d", errno); return 1; } return 0; } /** Retrieve the json results for a given callsign location Detail. */ DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo(const char *callsign, char **buf) { FILE *in; static void* mybuf = NULL; static size_t bufsize = 0; if (bufsize == 0) { bufsize = 4096; mybuf = tqsl_malloc(bufsize); } if (callsign == NULL || buf == NULL) { tqslTrace("tqsl_getCallsinLocationInfo", "arg error callsign=0x%lx, buf=0x%lx", callsign, buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } char fixcall[256]; char path[TQSL_MAX_PATH_LEN]; size_t size = sizeof path; tqsl_clean_call(callsign, fixcall, sizeof fixcall); strncpy(path, tQSL_BaseDir, size); #ifdef _WIN32 strncat(path, "\\", size - strlen(path)); #else strncat(path, "/", size - strlen(path)); #endif strncat(path, fixcall, size - strlen(path)); strncat(path, ".json", size - strlen(path)); size_t buflen = bufsize; #ifdef _WIN32 struct _stat32 s; wchar_t* wfilename = utf8_to_wchar(path); if (_wstat32(wfilename, &s) == 0) { buflen = s.st_size + 512; } if ((in = _wfopen(wfilename, TQSL_OPEN_READ)) == NULL) { free_wchar(wfilename); #else struct stat s; if (stat(path, &s) == 0) { buflen = s.st_size + 512; } if ((in = fopen(path, TQSL_OPEN_READ)) == NULL) { #endif strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tqslTrace("tqsl_getCallsignLocationInfo", "Open file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; return 1; } #ifdef _WIN32 free_wchar(wfilename); #endif if (buflen > bufsize) { bufsize = buflen + 512; mybuf = tqsl_realloc(mybuf, bufsize); } *buf = reinterpret_cast(mybuf); size_t len; if ((len = fread(mybuf, 1, buflen, in)) == 0) { strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tqslTrace("tqsl_getCallsignLocationInformation", "Read file - system error %s", strerror(errno)); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; return 1; } if (fclose(in) == EOF) { strncpy(tQSL_ErrorFile, path, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_getCallsignLocationInformation", "read error %d", errno); return 1; } if (len < buflen) { char *t = reinterpret_cast(mybuf); t[len] = '\0'; } return 0; } tqsl-2.7.2/src/location.h0000644000175000017500000000123414534122221015247 0ustar rmurphyrmurphy/*************************************************************************** location.h - description ------------------- begin : Fri Nov 15 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef __location_h #define __location_h // TQSL_LOCATION_FIELD flag bits #define TQSL_LOCATION_FIELD_UPPER 1 #define TQSL_LOCATION_FIELD_MUSTSEL 2 #define TQSL_LOCATION_FIELD_SELNXT 4 #endif // __location_h tqsl-2.7.2/src/location.cpp0000755000175000017500000037641714534122221015627 0ustar rmurphyrmurphy/*************************************************************************** location.cpp - description ------------------- begin : Wed Nov 6 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id: location.cpp,v 1.14 2013/03/01 13:20:30 k1mu Exp $ ***************************************************************************/ // #define DXCC_TEST #define TQSLLIB_DEF #include "location.h" #include #include #include #ifdef __APPLE__ #include #endif #include #include #include #include #include #include #include #include #include #include #include "tqsllib.h" #include "tqslerrno.h" #include "xml.h" #include "openssl_cert.h" #ifdef _WIN32 #include "windows.h" #include #endif #include "winstrdefs.h" using std::string; using std::vector; using std::map; using std::pair; using std::make_pair; using std::ofstream; using std::ios; using std::endl; using std::exception; static int init_adif_map(void); namespace tqsllib { class TQSL_LOCATION_ITEM { public: TQSL_LOCATION_ITEM() : ivalue(0) {} string text; string label; string zonemap; int ivalue; }; class TQSL_LOCATION_FIELD { public: TQSL_LOCATION_FIELD() {} TQSL_LOCATION_FIELD(string i_gabbi_name, const char *i_label, int i_data_type, int i_data_len, int i_input_type, int i_flags = 0); string label; string gabbi_name; int data_type; int data_len; string cdata; vector items; int idx; int idata; int input_type; int flags; bool changed; string dependency; }; TQSL_LOCATION_FIELD::TQSL_LOCATION_FIELD(string i_gabbi_name, const char *i_label, int i_data_type, int i_data_len, int i_input_type, int i_flags) : data_type(i_data_type), data_len(i_data_len), cdata(""), input_type(i_input_type), flags(i_flags) { if (!i_gabbi_name.empty()) gabbi_name = i_gabbi_name; if (i_label) label = i_label; idx = idata = 0; } typedef vector TQSL_LOCATION_FIELDLIST; class TQSL_LOCATION_PAGE { public: TQSL_LOCATION_PAGE() : complete(false), prev(0), next(0) {} bool complete; int prev, next; string dependentOn, dependency; map > hash; TQSL_LOCATION_FIELDLIST fieldlist; }; typedef vector TQSL_LOCATION_PAGELIST; class TQSL_NAME { public: explicit TQSL_NAME(string n = "", string c = "") : name(n), call(c) {} string name; string call; }; class TQSL_LOCATION { public: TQSL_LOCATION() : sentinel(0x5445), page(0), cansave(false), sign_clean(false), cert_flags(TQSL_SELECT_CERT_WITHKEYS | TQSL_SELECT_CERT_EXPIRED), newflags(false), newDXCC(-1) {} ~TQSL_LOCATION() { sentinel = 0; } int sentinel; int page; bool cansave; string name; TQSL_LOCATION_PAGELIST pagelist; vector names; string signdata; string loc_details; string qso_details; bool sign_clean; string tSTATION; string tCONTACT; string sigspec; char data_errors[512]; int cert_flags; bool newflags; int newDXCC; }; class Band { public: string name, spectrum; int low, high; }; class Mode { public: string mode, group; }; class PropMode { public: string descrip, name; }; class Satellite { public: Satellite() { start.year = start.month = start.day = 0; end.year = end.month = end.day = 0; } string descrip, name; tQSL_Date start, end; }; bool operator< (const Band& o1, const Band& o2) { static const char *suffixes[] = { "M", "CM", "MM"}; static const char *prefix_chars = "0123456789."; // get suffixes string b1_suf = o1.name.substr(o1.name.find_first_not_of(prefix_chars)); string b2_suf = o2.name.substr(o2.name.find_first_not_of(prefix_chars)); if (b1_suf != b2_suf) { // Suffixes differ -- compare suffixes int b1_idx = (sizeof suffixes / sizeof suffixes[0]); int b2_idx = b1_idx; for (int i = 0; i < static_cast(sizeof suffixes / sizeof suffixes[0]); i++) { if (b1_suf == suffixes[i]) b1_idx = i; if (b2_suf == suffixes[i]) b2_idx = i; } return b1_idx < b2_idx; } return atof(o1.name.c_str()) > atof(o2.name.c_str()); } bool operator< (const PropMode& o1, const PropMode& o2) { if (o1.descrip < o2.descrip) return true; if (o1.descrip == o2.descrip) return (o1.name < o2.name); return false; } bool operator< (const Satellite& o1, const Satellite& o2) { if (o1.descrip < o2.descrip) return true; if (o1.descrip == o2.descrip) return (o1.name < o2.name); return false; } bool operator< (const Mode& o1, const Mode& o2) { static const char *groups[] = { "CW", "PHONE", "IMAGE", "DATA" }; // m1 < m2 if m1 is a modegroup and m2 is not if (o1.mode == o1.group) { if (o2.mode != o2.group) return true; } else if (o2.mode == o2.group) { return false; } // If groups are same, compare modes if (o1.group == o2.group) return o1.mode < o2.mode; int m1_g = (sizeof groups / sizeof groups[0]); int m2_g = m1_g; for (int i = 0; i < static_cast(sizeof groups / sizeof groups[0]); i++) { if (o1.group == groups[i]) m1_g = i; if (o2.group == groups[i]) m2_g = i; } return m1_g < m2_g; } } // namespace tqsllib using tqsllib::XMLElement; using tqsllib::XMLElementList; using tqsllib::Band; using tqsllib::Mode; using tqsllib::PropMode; using tqsllib::Satellite; using tqsllib::TQSL_LOCATION; using tqsllib::TQSL_LOCATION_PAGE; using tqsllib::TQSL_LOCATION_PAGELIST; using tqsllib::TQSL_LOCATION_FIELD; using tqsllib::TQSL_LOCATION_FIELDLIST; using tqsllib::TQSL_LOCATION_ITEM; using tqsllib::TQSL_NAME; using tqsllib::ROOTCERT; using tqsllib::CACERT; using tqsllib::USERCERT; using tqsllib::tqsl_get_pem_serial; #define CAST_TQSL_LOCATION(x) (reinterpret_cast((x))) typedef map IntMap; typedef map BoolMap; typedef map DateMap; static int num_entities = 0; static bool _ent_init = false; static struct _dxcc_entity { int number; const char* name; const char *zonemap; tQSL_Date start, end; } *entity_list = 0; template struct triplet { T1 first; T2 middle; T3 last; }; template triplet make_triplet(const T1 &f, const T2 &m, const T3 &l) { triplet trip; trip.first = f; trip.middle = m; trip.last = l; return trip; } // config data static XMLElement tqsl_xml_config; static int tqsl_xml_config_major = -1; static int tqsl_xml_config_minor = 0; static IntMap DXCCMap; static BoolMap DeletedMap; static IntMap DXCCZoneMap; static DateMap DXCCStartMap; static DateMap DXCCEndMap; static vector< pair > DXCCList; static vector BandList; static vector ModeList; static vector PropModeList; static vector SatelliteList; static map tqsl_page_map; static map tqsl_field_map; static map tqsl_adif_map; static vector tqsl_adif_mode_map; static map tqsl_adif_submode_map; static map > tqsl_cabrillo_map; static map > tqsl_cabrillo_user_map; static char char_toupper(char c) { return toupper(c); } static string string_toupper(const string& in) { string out = in; transform(out.begin(), out.end(), out.begin(), char_toupper); return out; } // isspace() called on extended chars in UTF-8 raises asserts in // the windows C++ libs. Don't call isspace() if out of range. // static inline int isspc(int c) { if (c < 0 || c > 255) return 0; return isspace(c); } // trim from start static inline std::string <rim(std::string &s) { #if __cplusplus > 199711L s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) {return !std::isspace(c);})); #else s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(isspc)))); #endif return s; } // trim from end static inline std::string &rtrim(std::string &s) { #if __cplusplus > 199711L s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch);}).base(), s.end()); #else s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(isspc))).base(), s.end()); #endif return s; } // trim from both ends static inline std::string &trim(std::string &s) { return ltrim(rtrim(s)); } #define TQSL_NPAGES 4 static TQSL_LOCATION * check_loc(tQSL_Location loc, bool unclean = true) { if (tqsl_init()) return 0; if (loc == 0) return 0; if (unclean) CAST_TQSL_LOCATION(loc)->sign_clean = false; return CAST_TQSL_LOCATION(loc); } static int tqsl_load_xml_config() { if (tqsl_xml_config.getElementList().size() > 0) // Already init'd return 0; XMLElement default_config; XMLElement user_config; tqslTrace("tqsl_load_xml_config", NULL); #ifdef _WIN32 string default_path = string(tQSL_RsrcDir) + "\\config.xml"; string user_path = string(tQSL_BaseDir) + "\\config.xml"; #else string default_path = string(tQSL_RsrcDir) + "/config.xml"; string user_path = string(tQSL_BaseDir) + "/config.xml"; #endif tqslTrace("tqsl_load_xml_config", "user_path=%s", user_path.c_str()); int default_status = default_config.parseFile(default_path.c_str()); int user_status = user_config.parseFile(user_path.c_str()); tqslTrace("tqsl_load_xml_config", "default_status=%d, user_status=%d", default_status, user_status); if (default_status != XML_PARSE_NO_ERROR && user_status != XML_PARSE_NO_ERROR) { if (user_status == XML_PARSE_SYSTEM_ERROR) tQSL_Error = TQSL_CONFIG_ERROR; else tQSL_Error = TQSL_CONFIG_SYNTAX_ERROR; return 1; } int default_major = -1; int default_minor = 0; int user_major = -1; int user_minor = 0; XMLElement top; if (default_config.getFirstElement("tqslconfig", top)) { default_major = strtol(top.getAttribute("majorversion").first.c_str(), NULL, 10); default_minor = strtol(top.getAttribute("minorversion").first.c_str(), NULL, 10); } if (user_config.getFirstElement("tqslconfig", top)) { user_major = strtol(top.getAttribute("majorversion").first.c_str(), NULL, 10); user_minor = strtol(top.getAttribute("minorversion").first.c_str(), NULL, 10); } if (default_major > user_major || (default_major == user_major && default_minor > user_minor)) { tqsl_xml_config = default_config; tqsl_xml_config_major = default_major; tqsl_xml_config_minor = default_minor; return 0; } if (user_major < 0) { tQSL_Error = TQSL_CONFIG_SYNTAX_ERROR; tqslTrace("tqsl_load_xml_config", "Syntax error"); return 1; } tqsl_xml_config = user_config; tqsl_xml_config_major = user_major; tqsl_xml_config_minor = user_minor; return 0; } static int tqsl_get_xml_config_section(const string& section, XMLElement& el) { if (tqsl_load_xml_config()) return 1; XMLElement top; if (!tqsl_xml_config.getFirstElement("tqslconfig", top)) { tqsl_xml_config.clear(); tQSL_Error = TQSL_CONFIG_SYNTAX_ERROR; return 1; } if (!top.getFirstElement(section, el)) { tQSL_Error = TQSL_CONFIG_SYNTAX_ERROR; return 1; } return 0; } static int tqsl_load_provider_list(vector &plist) { plist.clear(); XMLElement providers; if (tqsl_get_xml_config_section("providers", providers)) return 1; tqslTrace("tqsl_load_provider_list", NULL); XMLElement provider; bool gotit = providers.getFirstElement("provider", provider); while (gotit) { TQSL_PROVIDER pdata; memset(&pdata, 0, sizeof pdata); pair rval = provider.getAttribute("organizationName"); if (!rval.second) { tQSL_Error = TQSL_PROVIDER_NOT_FOUND; tqslTrace("tqsl_load_provider_list", "Providers not found"); return 1; } strncpy(pdata.organizationName, rval.first.c_str(), sizeof pdata.organizationName); XMLElement item; if (provider.getFirstElement("organizationalUnitName", item)) strncpy(pdata.organizationalUnitName, item.getText().c_str(), sizeof pdata.organizationalUnitName); if (provider.getFirstElement("emailAddress", item)) strncpy(pdata.emailAddress, item.getText().c_str(), sizeof pdata.emailAddress); if (provider.getFirstElement("url", item)) strncpy(pdata.url, item.getText().c_str(), sizeof pdata.url); plist.push_back(pdata); gotit = providers.getNextElement(provider); if (gotit && provider.getElementName() != "provider") break; } return 0; } static XMLElement tCONTACT_sign; static int make_sign_data(TQSL_LOCATION *loc) { map field_data; // Loop through the location pages, getting field data // int old_page = loc->page; tqsl_setStationLocationCapturePage(loc, 1); do { TQSL_LOCATION_PAGE& p = loc->pagelist[loc->page-1]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD& f = p.fieldlist[i]; string s; if (f.input_type == TQSL_LOCATION_FIELD_DDLIST || f.input_type == TQSL_LOCATION_FIELD_LIST) { if (f.idx < 0 || f.idx >= static_cast(f.items.size())) s = ""; else s = f.items[f.idx].text; } else if (f.data_type == TQSL_LOCATION_FIELD_INT) { char buf[20]; snprintf(buf, sizeof buf, "%d", f.idata); s = buf; } else { s = f.cdata; } field_data[f.gabbi_name] = s; } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; tqsl_nextStationLocationCapture(loc); } while (1); tqsl_setStationLocationCapturePage(loc, old_page); loc->signdata = ""; loc->loc_details = ""; loc->sign_clean = false; XMLElement sigspecs; if (tqsl_get_xml_config_section("sigspecs", sigspecs)) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - it does not have a sigspecs section", sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } XMLElement sigspec; XMLElement ss; if (!sigspecs.getFirstElement("sigspec", sigspec)) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - it does not have a sigspec section", sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } ss = sigspec; bool ok; do { if (sigspec.getAttribute("status").first == "deprecated") { ok = sigspecs.getNextElement(sigspec); continue; } double ssver = atof(ss.getAttribute("version").first.c_str()); double newver = atof(sigspec.getAttribute("version").first.c_str()); if (newver > ssver) ss = sigspec; ok = sigspecs.getNextElement(sigspec); } while (ok); sigspec = ss; loc->sigspec = "SIGN_"; loc->sigspec += sigspec.getAttribute("name").first; loc->sigspec += "_V"; loc->sigspec += sigspec.getAttribute("version").first; tCONTACT_sign.clear(); if (!sigspec.getFirstElement("tCONTACT", tCONTACT_sign)) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - missing sigspec.tCONTACT", sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } if (tCONTACT_sign.getElementList().size() == 0) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - empty sigspec.tCONTACT", sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } XMLElement tSTATION; if (!sigspec.getFirstElement("tSTATION", tSTATION)) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - missing sigspec.tSTATION", sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } XMLElement specfield; if (!(ok = tSTATION.getFirstElement(specfield))) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - missing tSTATION.specfield", sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } do { string value = field_data[specfield.getElementName()]; value = trim(value); if (value == "") { pair attr = specfield.getAttribute("required"); if (attr.second && strtol(attr.first.c_str(), NULL, 10)) { string err = specfield.getElementName() + " field required by "; attr = sigspec.getAttribute("name"); if (attr.second) err += attr.first + " "; attr = sigspec.getAttribute("version"); if (attr.second) err += "V" + attr.first + " "; err += "signature specification not found"; tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, err.c_str(), sizeof tQSL_CustomError); tqslTrace("make_sign_data", "Error %s", tQSL_CustomError); return 1; } } else { loc->signdata += value; if (loc->loc_details != "") { loc->loc_details += ", "; } loc->loc_details += specfield.getElementName() + ": " + value; } ok = tSTATION.getNextElement(specfield); } while (ok); loc->sign_clean = true; return 0; } static int init_dxcc() { if (DXCCMap.size() > 0) return 0; tqslTrace("init_dxcc", NULL); XMLElement dxcc; if (tqsl_get_xml_config_section("dxcc", dxcc)) { tqslTrace("init_dxcc", "Error %d getting dxcc config section", tQSL_Error); return 1; } XMLElement dxcc_entity; bool ok = dxcc.getFirstElement("entity", dxcc_entity); while (ok) { pair rval = dxcc_entity.getAttribute("arrlId"); pair zval = dxcc_entity.getAttribute("zonemap"); pair strdate = dxcc_entity.getAttribute("valid"); pair enddate = dxcc_entity.getAttribute("invalid"); pair deleted = dxcc_entity.getAttribute("deleted"); if (rval.second) { int num = strtol(rval.first.c_str(), NULL, 10); DXCCMap[num] = dxcc_entity.getText(); DeletedMap[num] = false; if (deleted.second) { DeletedMap[num] = (deleted.first == "1"); } if (zval.second) { DXCCZoneMap[num] = zval.first; } tQSL_Date d; d.year = 1945; d.month = 11; d.day = 15; DXCCStartMap[num] = d; if (strdate.second) { if (!tqsl_initDate(&d, strdate.first.c_str())) { DXCCStartMap[num] = d; } } d.year = 0; d.month = 0; d.day = 0; DXCCEndMap[num] = d; if (enddate.second) { if (!tqsl_initDate(&d, enddate.first.c_str())) { DXCCEndMap[num] = d; } } DXCCList.push_back(make_pair(num, dxcc_entity.getText())); } ok = dxcc.getNextElement(dxcc_entity); } return 0; } static int init_band() { if (BandList.size() > 0) return 0; tqslTrace("init_band", NULL); XMLElement bands; if (tqsl_get_xml_config_section("bands", bands)) { tqslTrace("init_band", "Error %d getting bands", tQSL_Error); return 1; } XMLElement config_band; bool ok = bands.getFirstElement("band", config_band); while (ok) { Band b; b.name = config_band.getText(); b.spectrum = config_band.getAttribute("spectrum").first; b.low = strtol(config_band.getAttribute("low").first.c_str(), NULL, 10); b.high = strtol(config_band.getAttribute("high").first.c_str(), NULL, 10); BandList.push_back(b); ok = bands.getNextElement(config_band); } sort(BandList.begin(), BandList.end()); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion(int *major, int *minor) { if (tqsl_init()) return 1; if (tqsl_load_xml_config()) { tqslTrace("tqsl_getConfigVersion", "Error %d from tqsl_load_xml_config", tQSL_Error); return 1; } tqslTrace("tqsl_getConfigVersion", "major=%d, minor=%d", tqsl_xml_config_major, tqsl_xml_config_minor); if (major) *major = tqsl_xml_config_major; if (minor) *minor = tqsl_xml_config_minor; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumBand(int *number) { if (number == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tqslTrace("tqsl_getNumBand", NULL); if (init_band()) { tqslTrace("tqsl_getNumBand", "init_band error=%d", tQSL_Error); return 1; } *number = BandList.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getBand(int index, const char **name, const char **spectrum, int *low, int *high) { if (index < 0 || name == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_band()) { tqslTrace("tqsl_getBand", "init_band error=%d", tQSL_Error); return 1; } if (index >= static_cast(BandList.size())) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_getBand", "init_band arg error - index %d", index); return 1; } *name = BandList[index].name.c_str(); if (spectrum) *spectrum = BandList[index].spectrum.c_str(); if (low) *low = BandList[index].low; if (high) *high = BandList[index].high; return 0; } static int init_mode() { if (ModeList.size() > 0) return 0; XMLElement modes; if (tqsl_get_xml_config_section("modes", modes)) { tqslTrace("init_mode", "Error from tqsl_get_xml_config_section %d", tQSL_Error); return 1; } XMLElement config_mode; bool ok = modes.getFirstElement("mode", config_mode); while (ok) { Mode m; m.mode = config_mode.getText(); m.group = config_mode.getAttribute("group").first; ModeList.push_back(m); ok = modes.getNextElement(config_mode); } sort(ModeList.begin(), ModeList.end()); return 0; } static int init_propmode() { if (PropModeList.size() > 0) return 0; XMLElement propmodes; if (tqsl_get_xml_config_section("propmodes", propmodes)) { tqslTrace("init_propmode", "Error getting config section %d", tQSL_Error); return 1; } XMLElement config_mode; bool ok = propmodes.getFirstElement("propmode", config_mode); while (ok) { PropMode p; p.descrip = config_mode.getText(); p.name = config_mode.getAttribute("name").first; PropModeList.push_back(p); ok = propmodes.getNextElement(config_mode); } sort(PropModeList.begin(), PropModeList.end()); return 0; } static int init_satellite() { if (SatelliteList.size() > 0) return 0; XMLElement satellites; if (tqsl_get_xml_config_section("satellites", satellites)) { tqslTrace("init_satellite", "Error getting config section %d", tQSL_Error); return 1; } XMLElement config_sat; bool ok = satellites.getFirstElement("satellite", config_sat); while (ok) { Satellite s; s.descrip = config_sat.getText(); s.name = config_sat.getAttribute("name").first; tQSL_Date d; if (!tqsl_initDate(&d, config_sat.getAttribute("startDate").first.c_str())) s.start = d; if (!tqsl_initDate(&d, config_sat.getAttribute("endDate").first.c_str())) s.end = d; SatelliteList.push_back(s); ok = satellites.getNextElement(config_sat); } sort(SatelliteList.begin(), SatelliteList.end()); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumMode(int *number) { if (tqsl_init()) return 1; if (number == NULL) { tqslTrace("tqsl_getNumMode", "Argument error, number = 0x%lx", number); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_mode()) { tqslTrace("tqsl_getNumMode", "init_mode error %d", tQSL_Error); return 1; } *number = ModeList.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getMode(int index, const char **mode, const char **group) { if (index < 0 || mode == NULL) { tqslTrace("tqsl_getMode", "Arg error index=%d, mode=0x%lx, group=0x%lx", index, mode, group); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_mode()) { tqslTrace("tqsl_getMode", "init_mode error %d", tQSL_Error); return 1; } if (index >= static_cast(ModeList.size())) { tqslTrace("tqsl_getMode", "Argument error: %d", index); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *mode = ModeList[index].mode.c_str(); if (group) *group = ModeList[index].group.c_str(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumADIFMode(int *number) { if (tqsl_init()) return 1; if (number == NULL) { tqslTrace("tqsl_getNumADIFMode", "Argument error, number = 0x%lx", number); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_adif_map()) { tqslTrace("tqsl_getNumADIFMode", "init_mode error %d", tQSL_Error); return 1; } *number = tqsl_adif_mode_map.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry(int index, const char **mode) { if (tqsl_init()) return 1; if (mode == NULL) { tqslTrace("tqsl_getADIFMode", "Argument error, mode = 0x%lx", mode); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_adif_map()) { tqslTrace("tqsl_getADIFMode", "init_mode error %d", tQSL_Error); return 1; } if (index < 0 || index > static_cast (tqsl_adif_mode_map.size())) { tqslTrace("tqsl_getADIFMode", "Argument error, index = %d", index); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *mode = tqsl_adif_mode_map[index].c_str(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumDXCCEntity(int *number) { if (number == NULL) { tqslTrace("tqsl_getNumDXCCEntity", "Arg error - number=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getNumDXCCEntity", "init_dxcc error %d", tQSL_Error); return 1; } *number = DXCCList.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity(int index, int *number, const char **name) { if (index < 0 || name == NULL || number == NULL) { tqslTrace("tqsl_getDXCCEntity", "arg error index=%d, number = 0x%lx, name=0x%lx", index, number, name); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getDXCCEntity", "init_dxcc error %d", tQSL_Error); return 1; } if (index >= static_cast(DXCCList.size())) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_getDXCCEntity", "index range %d", index); return 1; } *number = DXCCList[index].first; *name = DXCCList[index].second.c_str(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName(int number, const char **name) { if (name == NULL) { tqslTrace("tqsl_getDXCCEntityName", "Name=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getDXCCEntityName", "init_dxcc error %d", tQSL_Error); return 1; } IntMap::const_iterator it; it = DXCCMap.find(number); if (it == DXCCMap.end()) { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } *name = it->second.c_str(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap(int number, const char **zonemap) { if (zonemap == NULL) { tqslTrace("tqsl_getDXCCZoneMap", "zonemap ptr null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getDXCCZoneMap", "init_dxcc error %d", tQSL_Error); return 1; } IntMap::const_iterator it; it = DXCCZoneMap.find(number); if (it == DXCCZoneMap.end()) { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } const char *map = it->second.c_str(); if (!map || map[0] == '\0') { *zonemap = NULL; } else { *zonemap = map; } return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDXCCStartDate(int number, tQSL_Date *d) { if (d == NULL) { tqslTrace("tqsl_getDXCCStartDate", "date ptr null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getDXCCStartDate", "init_dxcc error %d", tQSL_Error); return 1; } DateMap::const_iterator it; it = DXCCStartMap.find(number); if (it == DXCCStartMap.end()) { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } tQSL_Date newdate = it->second; *d = newdate; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDXCCEndDate(int number, tQSL_Date *d) { if (d == NULL) { tqslTrace("tqsl_getDXCCEndDate", "date ptr null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getDXCCEndDate", "init_dxcc error %d", tQSL_Error); return 1; } DateMap::const_iterator it; it = DXCCEndMap.find(number); if (it == DXCCEndMap.end()) { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } tQSL_Date newdate = it->second; *d = newdate; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted(int number, int *deleted) { if (deleted == NULL) { tqslTrace("tqsl_getDXCCDeleted", "Name=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_dxcc()) { tqslTrace("tqsl_getDXCCDeleted", "init_dxcc error %d", tQSL_Error); return 1; } *deleted = 0; BoolMap::const_iterator it; it = DeletedMap.find(number); if (it == DeletedMap.end()) { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } *deleted = it->second; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumPropagationMode(int *number) { if (tqsl_init()) return 1; if (number == NULL) { tqslTrace("tqsl_getNumPropagationMode", "number=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_propmode()) { tqslTrace("tqsl_getNumPropagationMode", "init_propmode error %d", tQSL_Error); return 1; } *number = PropModeList.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode(int index, const char **name, const char **descrip) { if (index < 0 || name == NULL) { tqslTrace("tqsl_getPropagationMode", "arg error index=%d name=0x%lx descrip=0x%lx", index, name, descrip); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_propmode()) { tqslTrace("tqsl_getPropagationMode", "init_propmode error %d", tQSL_Error); return 1; } if (index >= static_cast(PropModeList.size())) { tqslTrace("tqsl_getPropagationMode", "index out of range: %d", index); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *name = PropModeList[index].name.c_str(); if (descrip) *descrip = PropModeList[index].descrip.c_str(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumSatellite(int *number) { if (tqsl_init()) return 1; if (number == NULL) { tqslTrace("tqsl_getNumSatellite", "arg error number = null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_satellite()) { tqslTrace("tqsl_getNumSatellite", "init_satellite error %d", tQSL_Error); return 1; } *number = SatelliteList.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getSatellite(int index, const char **name, const char **descrip, tQSL_Date *start, tQSL_Date *end) { if (index < 0 || name == NULL) { tqslTrace("tqsl_getSatellite", "arg error index=%d name=0x%lx", index, name); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_satellite()) { tqslTrace("tqsl_getSatellite", "init_satellite error %d", tQSL_Error); return 1; } if (index >= static_cast(SatelliteList.size())) { tqslTrace("tqsl_getSatellite", "index error %d", index); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *name = SatelliteList[index].name.c_str(); if (descrip) *descrip = SatelliteList[index].descrip.c_str(); if (start) *start = SatelliteList[index].start; if (end) *end = SatelliteList[index].end; return 0; } static int init_cabrillo_map() { if (tqsl_cabrillo_map.size() > 0) return 0; XMLElement cabrillo_map; if (tqsl_get_xml_config_section("cabrillomap", cabrillo_map)) { tqslTrace("init_cabrillo_map", "get_xml_config_section error %d", tQSL_Error); return 1; } XMLElement cabrillo_item; bool ok = cabrillo_map.getFirstElement("cabrillocontest", cabrillo_item); int call_field = 0; int grid_field = 0; while (ok) { if (cabrillo_item.getText() != "") { call_field = strtol(cabrillo_item.getAttribute("field").first.c_str(), NULL, 10); grid_field = strtol(cabrillo_item.getAttribute("gridsquare").first.c_str(), NULL, 10); if (call_field > TQSL_MIN_CABRILLO_MAP_FIELD) { tqsl_cabrillo_map[cabrillo_item.getText()] = make_triplet(call_field - 1, grid_field - 1, (cabrillo_item.getAttribute("type").first == "VHF") ? TQSL_CABRILLO_VHF : TQSL_CABRILLO_HF); } } ok = cabrillo_map.getNextElement(cabrillo_item); } return 0; } DLLEXPORT int CALLCONVENTION tqsl_clearCabrilloMap() { tqslTrace("tqsl_clearCabrilloMap", NULL); tqsl_cabrillo_user_map.clear(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry(const char *contest, int field, int contest_type) { if (contest == NULL || field <= TQSL_MIN_CABRILLO_MAP_FIELD || (contest_type != TQSL_CABRILLO_HF && contest_type != TQSL_CABRILLO_VHF)) { tqslTrace("tqsl_setCabrilloMapEntry", "arg error contest=0x%lx field = %d", contest, field); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } tqsl_cabrillo_user_map[string_toupper(contest)] = make_pair(field-1, contest_type); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry(const char *contest, int *fieldnum, int *contest_type) { if (contest == NULL || fieldnum == NULL) { tqslTrace("tqsl_getCabrilloMapEntry", "arg error contest=0x%lx fieldnum = 0x%lx", contest, fieldnum); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_cabrillo_map()) { tqslTrace("tqsl_getCabrilloMapEntry", "init_cabrillo_map error %d", tQSL_Error); return 1; } map >::iterator it; map >::iterator uit; if ((uit = tqsl_cabrillo_user_map.find(string_toupper(contest))) == tqsl_cabrillo_user_map.end()) { if ((it = tqsl_cabrillo_map.find(string_toupper(contest))) == tqsl_cabrillo_map.end()) { *fieldnum = 0; return 0; } else { *fieldnum = it->second.first + 1 + ((it->second.middle + 1) * 1000); } if (contest_type) *contest_type = it->second.last; } else { *fieldnum = uit->second.first + 1; if (contest_type) *contest_type = uit->second.second; } return 0; } static int init_adif_map() { if (tqsl_adif_map.size() > 0) return 0; XMLElement adif_map; if (tqsl_get_xml_config_section("adifmap", adif_map)) { tqslTrace("init_adif_map", "tqsl_get_xml_config_section error %d", tQSL_Error); return 1; } XMLElement adif_item; bool ok = adif_map.getFirstElement("adifmode", adif_item); while (ok) { string adifmode = adif_item.getAttribute("adif-mode").first; string submode = adif_item.getAttribute("adif-submode").first; // Prefer the "mode=" attribute of the mode definition, else get the item value. string gabbi = adif_item.getAttribute("mode").first; string melem = adif_item.getText(); if (adifmode != "" && submode != "") { tqsl_adif_submode_map[melem] = adifmode + "%" + submode; } if (adifmode == "") { // Handle entries with just a mode element adifmode = melem; } bool found = false; for (unsigned int i = 0; i < tqsl_adif_mode_map.size(); i++) { if (tqsl_adif_mode_map[i] == melem) { found = true; } } if (!found) { tqsl_adif_mode_map.push_back(melem); } if (gabbi != "") { // There should always be one if (adifmode != "") { tqsl_adif_map[adifmode] = gabbi; } // Map this gabbi mode from submode if (submode != "" && submode != adifmode) { tqsl_adif_map[submode] = gabbi; } if (melem != "" && melem != adifmode) { tqsl_adif_map[melem] = gabbi; } // Add a mode%submode lookup too if (adifmode != "" && submode != "") { tqsl_adif_map[adifmode + "%" + submode] = gabbi; } } ok = adif_map.getNextElement(adif_item); } sort(tqsl_adif_mode_map.begin(), tqsl_adif_mode_map.end()); return 0; } DLLEXPORT int CALLCONVENTION tqsl_clearADIFModes() { tqsl_adif_map.clear(); tqsl_adif_mode_map.clear(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setADIFMode(const char *adif_item, const char *mode) { if (adif_item == NULL || mode == NULL) { tqslTrace("tqsl_setADIFMode", "arg error adif_item=0x%lx mode=0x%lx", adif_item, mode); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_adif_map()) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - ADIF map invalid", sizeof tQSL_CustomError); tqslTrace("tqslSetADIFMode", "Error %s", tQSL_CustomError); return 1; } string umode = string_toupper(mode); tqsl_adif_map[string_toupper(adif_item)] = umode; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getADIFMode(const char *adif_item, char *mode, int nmode) { if (adif_item == NULL || mode == NULL) { tqslTrace("tqsl_getADIFMode", "arg error adif_item=0x%lx, mode=0x%lx", adif_item, mode); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_adif_map()) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - ADIF map invalid", sizeof tQSL_CustomError); tqslTrace("tqsl_getADIFMode", "init_adif error %s", tQSL_CustomError); return 1; } string orig = adif_item; orig = string_toupper(orig); string amode; if (tqsl_adif_map.find(orig) != tqsl_adif_map.end()) { amode = tqsl_adif_map[orig]; } else { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } if (nmode < static_cast(amode.length())+1) { tqslTrace("tqsl_getAdifMode", "buffer error %s %s", nmode, amode.length()); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(mode, amode.c_str(), nmode); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode(const char *adif_item, char *mode, char *submode, int nmode) { if (adif_item == NULL || mode == NULL) { tqslTrace("tqsl_getADIFSubMode", "arg error adif_item=0x%lx, mode=0x%lx", adif_item, mode); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (init_adif_map()) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - ADIF map invalid", sizeof tQSL_CustomError); tqslTrace("tqsl_getADIFSubMode", "init_adif error %s", tQSL_CustomError); return 1; } string orig = adif_item; orig = string_toupper(orig); string amode; if (tqsl_adif_submode_map.find(orig) != tqsl_adif_submode_map.end()) { amode = tqsl_adif_submode_map[orig]; } else { tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } string adifmode = amode.substr(0, amode.find("%")); string adifsubmode = amode.substr(amode.find("%")+1); if (nmode < static_cast(amode.length())+1) { tqslTrace("tqsl_getAdifSubMode", "buffer error %s %s", nmode, amode.length()); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(mode, adifmode.c_str(), nmode); strncpy(submode, adifsubmode.c_str(), nmode); return 0; } static int init_loc_maps() { if (tqsl_field_map.size() > 0) return 0; XMLElement config_pages; if (tqsl_get_xml_config_section("locpages", config_pages)) { tqslTrace("init_loc_maps", "get_xml_config_section error %d", tQSL_Error); return 1; } XMLElement config_page; tqsl_page_map.clear(); bool ok; for (ok = config_pages.getFirstElement("page", config_page); ok; ok = config_pages.getNextElement(config_page)) { pair Id = config_page.getAttribute("Id"); int page_num = strtol(Id.first.c_str(), NULL, 10); if (!Id.second || page_num < 1) { // Must have the Id! tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - page missing ID", sizeof tQSL_CustomError); tqslTrace("init_loc_maps", "error %s", tQSL_CustomError); return 1; } tqsl_page_map[page_num] = config_page; } XMLElement config_fields; if (tqsl_get_xml_config_section("locfields", config_fields)) { tqslTrace("init_loc_maps", "get_xml_config_section locfields error %d", tQSL_Error); return 1; } XMLElement config_field; for (ok = config_fields.getFirstElement("field", config_field); ok; ok = config_fields.getNextElement(config_field)) { pair Id = config_field.getAttribute("Id"); if (!Id.second) { // Must have the Id! tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - field missing ID", sizeof tQSL_CustomError); tqslTrace("init_loc_maps", "config field error %s", tQSL_CustomError); return 1; } tqsl_field_map[Id.first] = config_field; } return 0; } static bool inMap(int cqvalue, int ituvalue, bool cqz, bool ituz, const char *map) { /* * Parse the zone map and return true if the value is a valid zone number * The maps are colon-separated number pairs, with a list of pairs comma separated. */ int cq, itu; bool result = false; // No map or empty string -> all match if (!map || map[0] == '\0') { return true; } char *mapcopy = strdup(map); char *mapPart = strtok(mapcopy, ","); while (mapPart) { sscanf(mapPart, "%d:%d", &itu, &cq); if (cqz && ituz) { if ((cq == cqvalue || cqvalue == 0) && (itu == ituvalue || ituvalue == 0)) { result = true; break; } } else if (cqz && (cq == cqvalue || cqvalue == 0)) { result = true; break; } else if (ituz && (itu == ituvalue || ituvalue == 0)) { result = true; break; } mapPart = strtok(NULL, ","); } free(mapcopy); return result; } static int _ent_cmp(const void *a, const void *b) { return strcasecmp(((struct _dxcc_entity *)a)->name, ((struct _dxcc_entity *)b)->name); } static TQSL_LOCATION_FIELD * get_location_field_page(const string& gabbi, TQSL_LOCATION *loc, int* page = NULL) { for (int mypage = 1; mypage > 0; mypage = loc->pagelist[mypage-1].next) { TQSL_LOCATION_FIELDLIST& fl = loc->pagelist[mypage-1].fieldlist; for (int j = 0; j < static_cast(fl.size()); j++) { if (fl[j].gabbi_name == gabbi) { if (page) { *page = mypage; } return &(fl[j]); } } } return 0; } struct sasMap { const char *gabbi; const char *errstr; }; static struct sasMap sasMapping[] = { { "US_STATE", "Invalid zone selections for state" }, { "CA_PROVINCE", "Invalid zone selections for province" }, { "RU_OBLAST", "Invalid zone selections for oblast" }, { "CN_PROVINCE", "Invalid zone selections for province" }, { "AU_STATE", "Invalid zone selections for state" }, { "JA_PREFECTURE", "Invalid zone selections for prefecture" }, { "FI_KUNTA", "Invalid zone selections for kunta" }, { NULL, NULL } }; static TQSL_LOCATION_FIELD* get_primary_sub(TQSL_LOCATION* loc, string* errstr) { for (int i = 0; sasMapping[i].gabbi; i++) { TQSL_LOCATION_FIELD* temp = get_location_field_page(sasMapping[i].gabbi, loc); if (temp) { if (errstr) *errstr = sasMapping[i].errstr; return temp; } } return NULL; } static int find_next_page(TQSL_LOCATION *loc); static int update_page(int page, TQSL_LOCATION *loc) { TQSL_LOCATION_PAGE& p = loc->pagelist[page-1]; int dxcc; int current_entity = -1; int loaded_cqz = -1; int loaded_ituz = -1; TQSL_LOCATION_FIELD *cqz = get_location_field_page("CQZ", loc); TQSL_LOCATION_FIELD *ituz = get_location_field_page("ITUZ", loc); tqslTrace("update_page", "page=%d, loc=0x%lx", page, loc); for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD& field = p.fieldlist[i]; field.changed = false; if (field.gabbi_name == "CALL") { if (field.items.size() == 0 || loc->newflags) { // Build list of call signs from available certs field.changed = true; field.items.clear(); field.idx = 0; loc->newflags = false; field.flags = TQSL_LOCATION_FIELD_SELNXT; // Must be selected p.hash.clear(); tQSL_Cert *certlist; int ncerts; tqsl_selectCertificates(&certlist, &ncerts, 0, 0, 0, 0, loc->cert_flags); for (int i = 0; i < ncerts; i++) { char callsign[40]; tqsl_getCertificateCallSign(certlist[i], callsign, sizeof callsign); tqsl_getCertificateDXCCEntity(certlist[i], &dxcc); char ibuf[10]; snprintf(ibuf, sizeof ibuf, "%d", dxcc); bool found = false; // Only add a given DXCC entity to a call once. map >::iterator call_p; for (call_p = p.hash.begin(); call_p != p.hash.end(); call_p++) { if (call_p->first == callsign && call_p->second[0] == ibuf) { found = true; break; } } if (!found) p.hash[callsign].push_back(ibuf); tqsl_freeCertificate(certlist[i]); } free(certlist); // Fill the call sign list map >::iterator call_p; field.idx = 0; TQSL_LOCATION_ITEM none; none.text = "[None]"; field.items.push_back(none); for (call_p = p.hash.begin(); call_p != p.hash.end(); call_p++) { TQSL_LOCATION_ITEM item; item.text = call_p->first; if (item.text == field.cdata) field.idx = static_cast(field.items.size()); field.items.push_back(item); } if (field.idx == 0 && field.items.size() == 2) { field.idx = 1; } if (field.idx >= 0) { field.cdata = field.items[field.idx].text; } } } else if (field.gabbi_name == "DXCC") { // Note: Expects CALL to be field 0 of this page. string call = p.fieldlist[0].cdata; if (field.items.size() == 0 || call != field.dependency) { // rebuild list field.changed = true; init_dxcc(); int olddxcc = strtol(field.cdata.c_str(), NULL, 10); if (loc->newDXCC != -1) { olddxcc = loc->newDXCC; loc->newDXCC = -1; } field.items.clear(); field.idx = 0; #ifdef DXCC_TEST const char *dxcc_test = getenv("TQSL_DXCC"); if (dxcc_test) { vector &entlist = p.hash[call]; char *parse_dxcc = strdup(dxcc_test); char *cp = strtok(parse_dxcc, ","); while (cp) { if (find(entlist.begin(), entlist.end(), string(cp)) == entlist.end()) entlist.push_back(cp); cp = strtok(0, ","); } free(parse_dxcc); } #endif if (call == "[None]") { int i; if (!_ent_init) { num_entities = DXCCMap.size(); entity_list = new struct _dxcc_entity[num_entities]; IntMap::const_iterator it; for (it = DXCCMap.begin(), i = 0; it != DXCCMap.end(); it++, i++) { entity_list[i].number = it->first; entity_list[i].name = it->second.c_str(); entity_list[i].zonemap = DXCCZoneMap[it->first].c_str(); entity_list[i].start = DXCCStartMap[it->first]; entity_list[i].end = DXCCEndMap[it->first]; } qsort(entity_list, num_entities, sizeof(struct _dxcc_entity), &_ent_cmp); _ent_init = true; } for (i = 0; i < num_entities; i++) { TQSL_LOCATION_ITEM item; item.ivalue = entity_list[i].number; char buf[10]; snprintf(buf, sizeof buf, "%d", item.ivalue); item.text = buf; item.label = entity_list[i].name; item.zonemap = entity_list[i].zonemap; if (item.ivalue == olddxcc) { field.idx = field.items.size(); } field.items.push_back(item); } field.idx = 0; } else { vector::iterator ip; // Always have the "-NONE-" entity. TQSL_LOCATION_ITEM item; item.label = "-NONE-"; item.zonemap = ""; // This iterator walks the list of DXCC entities associated // with this callsign field.items.push_back(item); bool setIndex = false; for (ip = p.hash[call].begin(); ip != p.hash[call].end(); ip++) { item.text = *ip; item.ivalue = strtol(ip->c_str(), NULL, 10); IntMap::iterator dxcc_it = DXCCMap.find(item.ivalue); if (dxcc_it != DXCCMap.end()) { item.label = dxcc_it->second; item.zonemap = DXCCZoneMap[item.ivalue]; } if (item.ivalue == olddxcc) { field.idx = field.items.size(); setIndex = true; } field.items.push_back(item); } if (!setIndex) { field.idx = field.items.size()-1; } } if (field.items.size() > 0) { field.cdata = field.items[field.idx].text; } field.dependency = call; } // rebuild list } else { if (tqsl_field_map.find(field.gabbi_name) == tqsl_field_map.end()) { // Shouldn't happen! tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - field map mismatch.", sizeof tQSL_CustomError); tqslTrace("update_page", "field map error %s", field.gabbi_name.c_str()); return 1; } XMLElement config_field = tqsl_field_map.find(field.gabbi_name)->second; pair attr = config_field.getAttribute("dependsOn"); if (attr.first != "") { // Items list depends on other field TQSL_LOCATION_FIELD *fp = get_location_field_page(attr.first, loc); if (fp) { // Found the dependency field. Now find the enums to use string val = fp->cdata; if (fp->items.size() > 0) val = fp->items[fp->idx].text; if (val == field.dependency) continue; field.dependency = val; field.changed = true; field.items.clear(); string oldcdata = field.cdata; field.idx = 0; XMLElement enumlist; bool ok = config_field.getFirstElement("enums", enumlist); while (ok) { pair dependency = enumlist.getAttribute("dependency"); if (dependency.second && dependency.first == val) { if (!(field.flags & TQSL_LOCATION_FIELD_MUSTSEL)) { TQSL_LOCATION_ITEM item; item.label = "[None]"; field.items.push_back(item); } XMLElement enumitem; bool iok = enumlist.getFirstElement("enum", enumitem); while (iok) { TQSL_LOCATION_ITEM item; item.text = enumitem.getAttribute("value").first; item.label = enumitem.getText(); item.zonemap = enumitem.getAttribute("zonemap").first; field.items.push_back(item); if (item.text == oldcdata) { field.idx = field.items.size() - 1; } iok = enumlist.getNextElement(enumitem); } } ok = config_field.getNextElement(enumlist); } // enum loop } else { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - dependent field not found.", sizeof tQSL_CustomError); tqslTrace("update_page", "error %s", tQSL_CustomError); return 1; } } else { // No dependencies TQSL_LOCATION_FIELD *ent = get_location_field_page("DXCC", loc); current_entity = strtol(ent->cdata.c_str(), NULL, 10); bool isCQZ = field.gabbi_name == "CQZ"; bool isITUZ = field.gabbi_name == "ITUZ"; if (field.items.size() == 0 || (isCQZ && current_entity != loaded_cqz) || (isITUZ && current_entity != loaded_ituz)) { XMLElement enumlist; if (config_field.getFirstElement("enums", enumlist)) { field.items.clear(); field.idx = 0; string oldcdata = field.cdata; field.changed = true; if (!(field.flags & TQSL_LOCATION_FIELD_MUSTSEL)) { TQSL_LOCATION_ITEM item; item.label = "[None]"; field.items.push_back(item); } XMLElement enumitem; bool iok = enumlist.getFirstElement("enum", enumitem); while (iok) { TQSL_LOCATION_ITEM item; item.text = enumitem.getAttribute("value").first; item.label = enumitem.getText(); item.zonemap = enumitem.getAttribute("zonemap").first; field.items.push_back(item); if (item.text == oldcdata) { field.idx = field.items.size() - 1; } iok = enumlist.getNextElement(enumitem); } } else { // No enums supplied int ftype = strtol(config_field.getAttribute("intype").first.c_str(), NULL, 10); if (ftype == TQSL_LOCATION_FIELD_LIST || ftype == TQSL_LOCATION_FIELD_DDLIST) { // This a list field int lower = strtol(config_field.getAttribute("lower").first.c_str(), NULL, 10); int upper = strtol(config_field.getAttribute("upper").first.c_str(), NULL, 10); const char *zoneMap; /* Get the map */ if (tqsl_getDXCCZoneMap(current_entity, &zoneMap)) { zoneMap = NULL; } // Try for a zonemap from the primary subdivision TQSL_LOCATION_FIELD* pas = NULL; if (find_next_page(loc)) { pas = get_primary_sub(loc, NULL); } if (pas != NULL && pas->items.size() > 0 && (unsigned int) pas->idx < pas->items.size() && pas->items[pas->idx].zonemap != "") zoneMap = pas->items[pas->idx].zonemap.c_str(); if (upper < lower) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - field range order incorrect.", sizeof tQSL_CustomError); tqslTrace("update_page", "error %s", tQSL_CustomError); return 1; } field.items.clear(); field.idx = 0; string oldcdata = field.cdata; field.changed = true; int currentCQ = cqz->idata; int currentITU = ituz->idata; if (isCQZ) { loaded_cqz = current_entity; if (!inMap(0, currentITU, false, true, zoneMap)) { currentITU = 0; // Not valid here, ignore } } if (isITUZ) { loaded_ituz = current_entity; if (!inMap(currentCQ, 0, true, false, zoneMap)) { currentCQ = 0; // Not valid here, ignore } } if (!(field.flags & TQSL_LOCATION_FIELD_MUSTSEL)) { TQSL_LOCATION_ITEM item; item.label = "[None]"; field.items.push_back(item); } char buf[40]; for (int j = lower; j <= upper; j++) { bool zoneOK = true; if (zoneMap) { if (isCQZ) { zoneOK = inMap(j, currentITU, true, true, zoneMap); } if (isITUZ) { zoneOK = inMap(currentCQ, j, true, true, zoneMap); } } if (zoneOK) { snprintf(buf, sizeof buf, "%d", j); TQSL_LOCATION_ITEM item; item.text = buf; item.ivalue = j; field.items.push_back(item); if (item.text == oldcdata) { field.idx = field.items.size() - 1; } } } } // intype != TEXT } // enums supplied } // itemlist not empty and current entity } // no dependencies } // field name not CALL|DXCC } // field loop /* Sanity check zones */ bool zonesok = true; string zone_error = ""; int currentCQ = cqz->idata; int currentITU = ituz->idata; // Check each division, start from entity, then division TQSL_LOCATION_FIELD *entity = get_location_field_page("DXCC", loc); if (entity) { zone_error = "Invalid zone selections for DXCC entity"; if (entity && entity->idx >=0 && entity->items.size() > 0) { string dxzm = entity->items[entity->idx].zonemap; const char* dxccZoneMap = dxzm.c_str(); if (!inMap(currentCQ, currentITU, true, true, dxccZoneMap)) { zonesok = false; } } } // Entity is OK, try for the state/province/oblast TQSL_LOCATION_FIELD *state = get_primary_sub(loc, &zone_error); if (state && state->idx >=0 && state->items.size() > 0) { string szm = state->items[state->idx].zonemap; const char* stateZoneMap = szm.c_str(); if (!inMap(currentCQ, currentITU, true, true, stateZoneMap)) { zonesok = false; } } if (zonesok) { tQSL_CustomError[0] = '\0'; } else { strncpy(tQSL_CustomError, zone_error.c_str(), sizeof tQSL_CustomError); } p.complete = true; return 0; } static int make_page(TQSL_LOCATION_PAGELIST& pagelist, int page_num) { if (init_loc_maps()) { tqslTrace("make_page", "init_loc_maps error %d", tQSL_Error); return 1; } if (tqsl_page_map.find(page_num) == tqsl_page_map.end()) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - page reference could not be found.", sizeof tQSL_CustomError); tqslTrace("make_page", "Error %d %s", page_num, tQSL_CustomError); return 1; } TQSL_LOCATION_PAGE p; pagelist.push_back(p); XMLElement& config_page = tqsl_page_map[page_num]; pagelist.back().prev = strtol(config_page.getAttribute("follows").first.c_str(), NULL, 10); XMLElement config_pageField; bool field_ok = config_page.getFirstElement("pageField", config_pageField); while (field_ok) { string field_name = config_pageField.getText(); if (field_name == "" || tqsl_field_map.find(field_name) == tqsl_field_map.end()) { tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, "TQSL Configuration file invalid - page references undefined field.", sizeof tQSL_CustomError); tqslTrace("make_page", "Error %s", tQSL_CustomError); return 1; } XMLElement& config_field = tqsl_field_map[field_name]; TQSL_LOCATION_FIELD loc_field( field_name, config_field.getAttribute("label").first.c_str(), (config_field.getAttribute("type").first == "C") ? TQSL_LOCATION_FIELD_CHAR : TQSL_LOCATION_FIELD_INT, strtol(config_field.getAttribute("len").first.c_str(), NULL, 10), strtol(config_field.getAttribute("intype").first.c_str(), NULL, 10), strtol(config_field.getAttribute("flags").first.c_str(), NULL, 10) ); // NOLINT(whitespace/parens) pagelist.back().fieldlist.push_back(loc_field); field_ok = config_page.getNextElement(config_pageField); } return 0; } DLLEXPORT int CALLCONVENTION tqsl_initStationLocationCapture(tQSL_Location *locp) { if (tqsl_init()) return 1; if (locp == NULL) { tqslTrace("tqsl_initStationLocationCapture", "Arg error locp=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_LOCATION *loc = new TQSL_LOCATION; *locp = loc; if (init_loc_maps()) { tqslTrace("tqsl_initStationLocationCapture", "init_loc_maps error %d", tQSL_Error); return 1; } map::iterator pit; for (pit = tqsl_page_map.begin(); pit != tqsl_page_map.end(); pit++) { if (make_page(loc->pagelist, pit->first)) { tqslTrace("tqsl_initStationLocationCapture", "make_page error %d", tQSL_Error); return 1; } } loc->page = 1; if (update_page(1, loc)) { tqslTrace("tqsl_initStationLocationCapture", "updatePage error %d", tQSL_Error); return 1; } return 0; } DLLEXPORT int CALLCONVENTION tqsl_endStationLocationCapture(tQSL_Location *locp) { if (tqsl_init()) return 1; if (locp == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_endStationLocationCapture", "arg error locp=NULL"); return 1; } if (*locp == 0) return 0; if (CAST_TQSL_LOCATION(*locp)->sentinel == 0x5445) delete CAST_TQSL_LOCATION(*locp); *locp = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_updateStationLocationCapture(tQSL_Location locp) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_updateStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } // TQSL_LOCATION_PAGE &p = loc->pagelist[loc->page-1]; return update_page(loc->page, loc); } DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocationCapturePages(tQSL_Location locp, int *npages) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getNumStationLocationCapturePages", "check_loc error %d", tQSL_Error); return 1; } if (npages == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_getNumStationLocationCapturePages", "arg error npages=NULL"); return 1; } *npages = loc->pagelist.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCapturePage(tQSL_Location locp, int *page) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getStationLocationCapturePage", "check_loc error %d", tQSL_Error); return 1; } if (page == NULL) { tqslTrace("tqsl_getStationLocationCapturePage", "arg error page=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *page = loc->page; return 0; } DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCapturePage(tQSL_Location locp, int page) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_setStationLocationCapturePage", "check_loc error %d", tQSL_Error); return 1; } if (page < 1 || page > static_cast(loc->pagelist.size())) { tqslTrace("tqsl_setStationLocationCapturePage", "Page %d out of range", page); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } loc->page = page; return 0; } DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCertFlags(tQSL_Location locp, int flags) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_setStationLocationCertFlags", "check_loc error %d", tQSL_Error); return 1; } if (loc->cert_flags != flags) { loc->cert_flags = flags; loc->newflags = true; loc->page = 1; if (update_page(1, loc)) { tqslTrace("tqsl_setStationLocationCertFlags", "update_page error %d", tQSL_Error); return 1; } } return 0; } static int find_next_page(TQSL_LOCATION *loc) { // Set next page based on page dependencies TQSL_LOCATION_PAGE& p = loc->pagelist[loc->page-1]; map::iterator pit; p.next = 0; for (pit = tqsl_page_map.begin(); pit != tqsl_page_map.end(); pit++) { if (strtol(pit->second.getAttribute("follows").first.c_str(), NULL, 10) == loc->page) { string dependsOn = pit->second.getAttribute("dependsOn").first; string dependency = pit->second.getAttribute("dependency").first; if (dependsOn == "") { p.next = pit->first; return 1; // Found next page } TQSL_LOCATION_FIELD *fp = get_location_field_page(dependsOn, loc); if (static_cast(fp->items.size()) > fp->idx && fp->idx >= 0 && fp->items[fp->idx].text == dependency) { p.next = pit->first; return 1; // Found next page } } } return 0; } DLLEXPORT int CALLCONVENTION tqsl_nextStationLocationCapture(tQSL_Location locp) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_nextStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } if (!find_next_page(loc)) return 0; TQSL_LOCATION_PAGE &p = loc->pagelist[loc->page-1]; if (p.next > 0) loc->page = p.next; update_page(loc->page, loc); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNextStationLocationCapturePage(tQSL_Location locp, int *page) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp)) || page == NULL) { tqslTrace("tqsl_nextStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } if (!find_next_page(loc)) return 1; TQSL_LOCATION_PAGE &p = loc->pagelist[loc->page-1]; if (p.next > 0) { *page = p.next; return 0; } return 1; } DLLEXPORT int CALLCONVENTION tqsl_prevStationLocationCapture(tQSL_Location locp) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_prevStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_PAGE &p = loc->pagelist[loc->page-1]; if (p.prev > 0) loc->page = p.prev; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getPrevStationLocationCapturePage(tQSL_Location locp, int *page) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp)) || page == NULL) { tqslTrace("tqsl_getPrevStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_PAGE &p = loc->pagelist[loc->page-1]; if (p.prev > 0) { *page = p.prev; return 0; } return 1; } DLLEXPORT int CALLCONVENTION tqsl_getCurrentStationLocationCapturePage(tQSL_Location locp, int *page) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp)) || page == NULL) { tqslTrace("tqsl_getPrevStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } *page = loc->page; return 0; } DLLEXPORT int CALLCONVENTION tqsl_hasNextStationLocationCapture(tQSL_Location locp, int *rval) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_hasNextStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } if (rval == NULL) { tqslTrace("tqsl_hasNextStationLocationCapture", "Arg error rval=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (!find_next_page(loc)) { tqslTrace("tqsl_hasNextStationLocationCapture", "find_next_page error %d", tQSL_Error); return 1; } *rval = (loc->pagelist[loc->page-1].next > 0); return 0; } DLLEXPORT int CALLCONVENTION tqsl_hasPrevStationLocationCapture(tQSL_Location locp, int *rval) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_hasPrevStationLocationCapture", "check_loc error %d", tQSL_Error); return 1; } if (rval == NULL) { tqslTrace("tqsl_hasPrevStationLocationCapture", "arg error rval=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *rval = (loc->pagelist[loc->page-1].prev > 0); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField(tQSL_Location locp, int *numf) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getNumLocationField", "check_loc error %d", tQSL_Error); return 1; } if (numf == NULL) { tqslTrace("tqsl_getNumLocationField", "arg error numf=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; *numf = fl.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize(tQSL_Location locp, int field_num, int *rval) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldDataLabelSize", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (rval == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldDataLabelSize", "arg error rval=0x%lx, field_num=%d", rval, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *rval = fl[field_num].label.size()+1; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel(tQSL_Location locp, int field_num, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldDataLabel", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (buf == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldDataLabel", "arg error buf=0x%lx, field_num=%d", buf, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(buf, fl[field_num].label.c_str(), bufsiz); buf[bufsiz-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize(tQSL_Location locp, int field_num, int *rval) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldDataGABBISize", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (rval == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldDataGABBISize", "arg error rval=0x%lx, field_num=%d", rval, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *rval = fl[field_num].gabbi_name.size()+1; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI(tQSL_Location locp, int field_num, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldDataGABBI", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (buf == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldDataGABBI", "arg error buf=0x%lx, field_num=%d", buf, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(buf, fl[field_num].gabbi_name.c_str(), bufsiz); buf[bufsiz-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldInputType(tQSL_Location locp, int field_num, int *type) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldInputType", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (type == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldInputType", "arg error type=0x%lx, field_num=%d", type, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *type = fl[field_num].input_type; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldChanged(tQSL_Location locp, int field_num, int *changed) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldChanged", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (changed == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldChanged", "arg error changed=0x%lx, field_num=%d", changed, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *changed = fl[field_num].changed; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataType(tQSL_Location locp, int field_num, int *type) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldDataType", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (type == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldDataType", "arg error type=0x%lx, field_num=%d", type, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *type = fl[field_num].data_type; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldFlags(tQSL_Location locp, int field_num, int *flags) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldFlags", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (flags == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldFlags", "arg error flags=0x%lx, field_num=%d", flags, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *flags = fl[field_num].flags; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLength(tQSL_Location locp, int field_num, int *rval) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldDataLength", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (rval == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldDataLength", "arg error rval=0x%lx, field_num=%d", rval, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *rval = fl[field_num].data_len; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData(tQSL_Location locp, int field_num, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldCharData", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (buf == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldCharData", "arg error buf=0x%lx, field_num=%d", buf, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (fl[field_num].flags & TQSL_LOCATION_FIELD_UPPER) strncpy(buf, string_toupper(fl[field_num].cdata).c_str(), bufsiz); else strncpy(buf, fl[field_num].cdata.c_str(), bufsiz); buf[bufsiz-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIntData(tQSL_Location locp, int field_num, int *dat) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldIntData", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (dat == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldIntData", "arg error dat=0x%lx, field_num=%d", dat, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *dat = fl[field_num].idata; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIndex(tQSL_Location locp, int field_num, int *dat) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldIndex", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (dat == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_getLocationFieldIndex", "arg error dat=0x%lx, field_num=%d", dat, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (fl[field_num].input_type != TQSL_LOCATION_FIELD_DDLIST && fl[field_num].input_type != TQSL_LOCATION_FIELD_LIST) { tqslTrace("tqsl_getLocationFieldIndex", "arg error input type mismatch"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *dat = fl[field_num].idx; return 0; } DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData(tQSL_Location locp, int field_num, const char *buf) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_setLocationFieldCharData", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (buf == NULL || field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_setLocationFieldCharData", "arg error buf=0x%lx, field_num=%d", buf, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } fl[field_num].cdata = string(buf).substr(0, fl[field_num].data_len); if (fl[field_num].flags & TQSL_LOCATION_FIELD_UPPER) fl[field_num].cdata = string_toupper(fl[field_num].cdata); if (fl[field_num].input_type == TQSL_LOCATION_FIELD_DDLIST || fl[field_num].input_type == TQSL_LOCATION_FIELD_LIST) { if (fl[field_num].cdata == "") { fl[field_num].idx = 0; fl[field_num].idata = fl[field_num].items[0].ivalue; } else { bool found = false; for (int i = 0; i < static_cast(fl[field_num].items.size()); i++) { if (fl[field_num].items[i].text == fl[field_num].cdata) { fl[field_num].idx = i; fl[field_num].idata = fl[field_num].items[i].ivalue; found = true; break; } } if (!found) { // There's no entry in the list that matches! fl[field_num].cdata = ""; fl[field_num].idx = 0; fl[field_num].idata = 0; } } } return 0; } /* Set the field's index. For pick lists, this is the index into * 'items'. In that case, also set the field's data to the picked value. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIndex(tQSL_Location locp, int field_num, int dat) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_setLocationFieldIndex", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_setLocationFieldIndex", "arg error index out of range page %d size %d - field_num=%d, dat=%d", loc->page, fl.size(), field_num, dat); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } fl[field_num].idx = dat; if (fl[field_num].input_type == TQSL_LOCATION_FIELD_DDLIST || fl[field_num].input_type == TQSL_LOCATION_FIELD_LIST) { if (dat >= 0 && dat < static_cast(fl[field_num].items.size())) { fl[field_num].idx = dat; fl[field_num].cdata = fl[field_num].items[dat].text; fl[field_num].idata = fl[field_num].items[dat].ivalue; } else { tqslTrace("tqsl_setLocationFieldIndex", "arg error page %d field_num=%d dat=%d", loc->page, field_num, dat); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } } return 0; } /* Set the field's integer data. */ DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIntData(tQSL_Location locp, int field_num, int dat) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_setLocationFieldIntData", "check_loc error %d", tQSL_Error); return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (field_num < 0 || field_num >= static_cast(fl.size())) { tqslTrace("tqsl_setLocationFieldIntData", "arg error field_num=%d, dat=%d", field_num, dat); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } fl[field_num].idata = dat; return 0; } /* For pick lists, this is the index into * 'items'. In that case, also set the field's char data to the picked value. */ DLLEXPORT int CALLCONVENTION tqsl_getNumLocationFieldListItems(tQSL_Location locp, int field_num, int *rval) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getNumLocationFieldListItems", "check_loc error %d", tQSL_Error); return 1; } if (rval == NULL) { tqslTrace("tqsl_getNumLocationFieldListItems", "arg error rval=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; *rval = fl[field_num].items.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem(tQSL_Location locp, int field_num, int item_idx, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getLocationFieldListItem", "check_loc error %d", tQSL_Error); return 1; } bool findKey = false; if (item_idx & 0x10000) { findKey = true; item_idx &= 0xffff; } TQSL_LOCATION_FIELDLIST &fl = loc->pagelist[loc->page-1].fieldlist; if (buf == NULL || field_num < 0 || field_num >= static_cast(fl.size()) || (fl[field_num].input_type != TQSL_LOCATION_FIELD_LIST && fl[field_num].input_type != TQSL_LOCATION_FIELD_DDLIST)) { tqslTrace("tqsl_getLocationFieldListItem", "arg error buf=0x%lx, field_num=%d", buf, field_num); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (item_idx < 0 || item_idx >= static_cast(fl[field_num].items.size())) { tqslTrace("tqsl_getLocationFieldListItem", "arg error item_idx=%d", item_idx); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (findKey) { strncpy(buf, fl[field_num].items[item_idx].text.c_str(), bufsiz); } else { string& str = (fl[field_num].items[item_idx].label == "") ? fl[field_num].items[item_idx].text : fl[field_num].items[item_idx].label; strncpy(buf, str.c_str(), bufsiz); } buf[bufsiz - 1] = '\0'; return 0; } static string tqsl_station_data_filename(bool deleted = false) { const char *f; if (deleted) f = "station_data_trash"; else f = "station_data"; string s = tQSL_BaseDir; #ifdef _WIN32 s += "\\"; #else s += "/"; #endif s += f; return s; } static int tqsl_load_station_data(XMLElement &xel, bool deleted = false) { int status = xel.parseFile(tqsl_station_data_filename(deleted).c_str()); tqslTrace("tqsl_load_station_data", "file %s parse status %d", tqsl_station_data_filename(deleted).c_str(), status); if (status) { if (errno == ENOENT) { // If there's no file, no error. tqslTrace("tqsl_load_station_data", "File does not exist"); return 0; } strncpy(tQSL_ErrorFile, tqsl_station_data_filename(deleted).c_str(), sizeof tQSL_ErrorFile); if (status == XML_PARSE_SYSTEM_ERROR) { tQSL_Error = TQSL_FILE_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_load_station_data", "parse error, errno=%d", tQSL_Errno); } else { tqslTrace("tqsl_load_station_data", "syntax error"); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; } return 1; } return status; } static int tqsl_dump_station_data(XMLElement &xel, bool deleted = false) { ofstream out; string fn = tqsl_station_data_filename(deleted); out.exceptions(ios::failbit | ios::eofbit | ios::badbit); try { #ifdef _WIN32 wchar_t* wfn = utf8_to_wchar(fn.c_str()); out.open(wfn); free_wchar(wfn); #else out.open(fn.c_str()); #endif out << xel << endl; out.close(); } catch(exception& x) { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Unable to save new station location file (%s): %s/%s", fn.c_str(), x.what(), strerror(errno)); tqslTrace("tqsl_dump_station_data", "file error %s %s", fn.c_str(), tQSL_CustomError); return 1; } return 0; } static int tqsl_load_loc(TQSL_LOCATION *loc, XMLElementList::iterator ep, bool ignoreZones) { bool exists; loc->page = 1; loc->data_errors[0] = '\0'; int bad_ituz = 0; int bad_cqz = 0; tqslTrace("tqsl_load_loc", NULL); while(1) { TQSL_LOCATION_PAGE& page = loc->pagelist[loc->page-1]; for (int fidx = 0; fidx < static_cast(page.fieldlist.size()); fidx++) { TQSL_LOCATION_FIELD& field = page.fieldlist[fidx]; if (field.gabbi_name != "") { // A field that may exist XMLElement el; if (ep->second->getFirstElement(field.gabbi_name, el)) { field.cdata = el.getText(); switch (field.input_type) { case TQSL_LOCATION_FIELD_DDLIST: case TQSL_LOCATION_FIELD_LIST: exists = false; for (int i = 0; i < static_cast(field.items.size()); i++) { string cp = field.items[i].text; int q = strcasecmp(field.cdata.c_str(), cp.c_str()); if (q == 0) { field.idx = i; field.cdata = cp; field.idata = field.items[i].ivalue; exists = true; break; } } if (!exists) { if (field.gabbi_name == "CQZ") bad_cqz = strtol(field.cdata.c_str(), NULL, 10); else if (field.gabbi_name == "ITUZ") bad_ituz = strtol(field.cdata.c_str(), NULL, 10); else if (field.gabbi_name == "CALL" || field.gabbi_name == "DXCC") field.idx = -1; } break; case TQSL_LOCATION_FIELD_TEXT: field.cdata = trim(field.cdata); if (field.data_type == TQSL_LOCATION_FIELD_INT) field.idata = strtol(field.cdata.c_str(), NULL, 10); break; } } } if (update_page(loc->page, loc)) return 1; } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; tqsl_nextStationLocationCapture(loc); } if (ignoreZones) return 0; if (bad_cqz && bad_ituz) { snprintf(loc->data_errors, sizeof(loc->data_errors), "This station location is configured with invalid CQ zone %d and invalid ITU zone %d.", bad_cqz, bad_ituz); } else if (bad_cqz) { snprintf(loc->data_errors, sizeof(loc->data_errors), "This station location is configured with invalid CQ zone %d.", bad_cqz); } else if (bad_ituz) { snprintf(loc->data_errors, sizeof(loc->data_errors), "This station location is configured with invalid ITU zone %d.", bad_ituz); } tqslTrace("tqsl_load_loc", "data_errors=%s", loc->data_errors); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getStationDataEnc(tQSL_StationDataEnc *sdata) { char *dbuf = NULL; size_t dlen = 0; gzFile in = NULL; #ifdef _WIN32 wchar_t *fn = utf8_to_wchar(tqsl_station_data_filename().c_str()); int fd = _wopen(fn, _O_RDONLY|_O_BINARY); free_wchar(fn); if (fd != -1) in = gzdopen(fd, "rb"); #else in = gzopen(tqsl_station_data_filename().c_str(), "rb"); #endif if (!in) { if (errno == ENOENT) { *sdata = NULL; tqslTrace("tqsl_getStationDataEnc", "File %s does not exist", tqsl_station_data_filename().c_str()); return 0; } tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; strncpy(tQSL_ErrorFile, tqsl_station_data_filename().c_str(), sizeof tQSL_ErrorFile); tqslTrace("tqsl_getStationDataEnc", "File %s open error %s", tqsl_station_data_filename().c_str(), strerror(tQSL_Error) ); return 1; } char buf[2048]; int rcount; while ((rcount = gzread(in, buf, sizeof buf)) > 0) { dlen += rcount; } dbuf = reinterpret_cast(malloc(dlen + 2)); if (!dbuf) { tqslTrace("tqsl_getStationDataEnc", "memory allocation error %d", dlen+2); return 1; } *sdata = dbuf; gzrewind(in); while ((rcount = gzread(in, dbuf, sizeof buf)) > 0) { dbuf += rcount; } *dbuf = '\0'; gzclose(in); return 0; } DLLEXPORT int CALLCONVENTION tqsl_freeStationDataEnc(tQSL_StationDataEnc sdata) { if (sdata) free(sdata); return 0; //can never fail } DLLEXPORT int CALLCONVENTION tqsl_mergeStationLocations(const char *locdata) { XMLElement new_data; XMLElement old_data; XMLElement new_top_el; XMLElement old_top_el; vector locnames; tqslTrace("tqsl_mergeStationLocations", NULL); // Load the current station data if (tqsl_load_station_data(old_top_el)) { tqslTrace("tqsl_mergeStationLocations", "error loading station data"); return 1; } // Parse the data to be merged new_top_el.parseString(locdata); if (!new_top_el.getFirstElement(new_data)) new_data.setElementName("StationDataFile"); if (!old_top_el.getFirstElement(old_data)) old_data.setElementName("StationDataFile"); // Build a list of existing station locations XMLElementList& namelist = old_data.getElementList(); XMLElementList::iterator nameiter; XMLElement locname; for (nameiter = namelist.find("StationData"); nameiter != namelist.end(); nameiter++) { if (nameiter->first != "StationData") break; pair rval = nameiter->second->getAttribute("name"); if (rval.second) { locnames.push_back(rval.first); } } // Iterate the new locations XMLElementList& ellist = new_data.getElementList(); XMLElementList::iterator ep; old_data.setPretext(old_data.getPretext() + " "); for (ep = ellist.find("StationData"); ep != ellist.end(); ep++) { if (ep->first != "StationData") break; pair rval = ep->second->getAttribute("name"); bool found = false; if (rval.second) { for (size_t j = 0; j < locnames.size(); j++) { if (locnames[j] == rval.first) { found = true; break; } } } if (!found) { // Add this one to the station data file XMLElement *newtop = new XMLElement("StationData"); newtop->setPretext("\n "); newtop->setAttribute("name", rval.first); newtop->setText("\n "); XMLElement el; bool elok = ep->second->getFirstElement(el); while (elok) { XMLElement *sub = new XMLElement; sub->setPretext(newtop->getPretext() + " "); sub->setElementName(el.getElementName()); sub->setText(el.getText()); newtop->addElement(sub); elok = ep->second->getNextElement(el); } old_data.addElement(newtop); old_data.setText("\n"); } } return tqsl_dump_station_data(old_data); } // Move a station location to or from the trash static int tqsl_move_station_location(const char *name, bool fromtrash) { tqslTrace("tqsl_move_station_location", "name=%s, fromtrash=%d", name, fromtrash); XMLElement from_top_el; XMLElement to_top_el; if (tqsl_load_station_data(from_top_el, fromtrash)) { tqslTrace("tqsl_move_station_location", "error %d loading data", tQSL_Error); return 1; } if (tqsl_load_station_data(to_top_el, !fromtrash)) { tqslTrace("tqsl_move_station_location", "error %d loading data", tQSL_Error); return 1; } XMLElement from_sfile; XMLElement to_sfile; if (!from_top_el.getFirstElement(from_sfile)) from_sfile.setElementName("StationDataFile"); if (!to_top_el.getFirstElement(to_sfile)) to_sfile.setElementName("StationDataFile"); XMLElementList& from_ellist = from_sfile.getElementList(); XMLElementList::iterator from_ep; for (from_ep = from_ellist.find("StationData"); from_ep != from_ellist.end(); from_ep++) { if (from_ep->first != "StationData") break; pair from_rval = from_ep->second->getAttribute("name"); if (from_rval.second && !strcasecmp(from_rval.first.c_str(), name)) { // Match, move it. // First, delete any old backup for this station location XMLElementList& to_ellist = to_sfile.getElementList(); XMLElementList::iterator to_ep; for (to_ep = to_ellist.find("StationData"); to_ep != to_ellist.end(); to_ep++) { if (to_ep->first != "StationData") break; pair to_rval = to_ep->second->getAttribute("name"); if (to_rval.second && !strcasecmp(to_rval.first.c_str(), name)) { to_ellist.erase(to_ep); break; } } // Now add it to the target XMLElement *newtop = new XMLElement("StationData"); newtop->setPretext("\n "); newtop->setAttribute("name", from_rval.first); newtop->setText("\n "); XMLElement el; bool elok = from_ep->second->getFirstElement(el); while (elok) { XMLElement *sub = new XMLElement; sub->setPretext(newtop->getPretext() + " "); sub->setElementName(el.getElementName()); sub->setText(el.getText()); newtop->addElement(sub); elok = from_ep->second->getNextElement(el); } to_sfile.addElement(newtop); to_sfile.setText("\n"); tqsl_dump_station_data(to_sfile, !fromtrash); from_ellist.erase(from_ep); return tqsl_dump_station_data(from_sfile, fromtrash); } } tqslTrace("tqsl_move_station_location", "location not found"); tQSL_Error = TQSL_LOCATION_NOT_FOUND; return 1; } DLLEXPORT int CALLCONVENTION tqsl_deleteStationLocation(const char *name) { tqslTrace("tqsl_deleteStationLocation", "name=%s", name); return tqsl_move_station_location(name, false); } DLLEXPORT int CALLCONVENTION tqsl_restoreStationLocation(const char *name) { tqslTrace("tqsl_restoreStationLocation", "name=%s", name); return tqsl_move_station_location(name, true); } DLLEXPORT int CALLCONVENTION tqsl_getStationLocation(tQSL_Location *locp, const char *name) { if (tqsl_initStationLocationCapture(locp)) { tqslTrace("tqsl_getStationLocation", "name=%s error=%d", name, tQSL_Error); return 1; } TQSL_LOCATION *loc; if (!(loc = check_loc(*locp))) { tqslTrace("tqsl_getStationLocation", "loc error %d", tQSL_Error); return 1; } loc->name = name; XMLElement top_el; if (tqsl_load_station_data(top_el)) { tqslTrace("tqsl_getStationLocation", "load station data error %d", tQSL_Error); return 1; } XMLElement sfile; if (!top_el.getFirstElement(sfile)) sfile.setElementName("StationDataFile"); XMLElementList& ellist = sfile.getElementList(); bool exists = false; XMLElementList::iterator ep; for (ep = ellist.find("StationData"); ep != ellist.end(); ep++) { if (ep->first != "StationData") break; pair rval = ep->second->getAttribute("name"); if (rval.second && !strcasecmp(trim(rval.first).c_str(), trim(loc->name).c_str())) { exists = true; break; } } if (!exists) { tQSL_Error = TQSL_LOCATION_NOT_FOUND; tqslTrace("tqsl_getStationLocation", "location %s does not exist", name); return 1; } return tqsl_load_loc(loc, ep, false); } DLLEXPORT int CALLCONVENTION tqsl_getStationLocationErrors(tQSL_Location locp, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getStationLocation", "loc error %d", tQSL_Error); return 1; } if (buf == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; tqslTrace("tqsl_getStationLocation", "buf = NULL"); return 1; } strncpy(buf, loc->data_errors, bufsiz); buf[bufsiz-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocations(tQSL_Location locp, int *nloc) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getNumStationLocations", "loc error %d", tQSL_Error); return 1; } if (nloc == NULL) { tqslTrace("tqsl_getNumStationLocations", "arg error nloc=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } loc->names.clear(); XMLElement top_el; if (tqsl_load_station_data(top_el)) { tqslTrace("tqsl_getNumStationLocations", "error %d loading station data", tQSL_Error); return 1; } XMLElement sfile; if (top_el.getFirstElement(sfile)) { XMLElement sd; bool ok = sfile.getFirstElement("StationData", sd); while (ok && sd.getElementName() == "StationData") { pair name = sd.getAttribute("name"); if (name.second) { XMLElement xc; string call; if (sd.getFirstElement("CALL", xc)) call = xc.getText(); loc->names.push_back(TQSL_NAME(name.first, call)); } ok = sfile.getNextElement(sd); } } *nloc = loc->names.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName(tQSL_Location locp, int idx, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getStationLocationName", "loc error %d", tQSL_Error); return 1; } if (buf == NULL || idx < 0 || idx >= static_cast(loc->names.size())) { tqslTrace("tqsl_getStationLocationName", "arg error buf=0x%lx, idx=%d", buf, idx); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(buf, loc->names[idx].name.c_str(), bufsiz); buf[bufsiz-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCallSign(tQSL_Location locp, int idx, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getStationLocationCallSign", "loc error %d", tQSL_Error); return 1; } if (buf == NULL || idx < 0 || idx >= static_cast(loc->names.size())) { tqslTrace("tqsl_getStationLocationCallSign", "arg error buf=0x%lx, idx=%d", buf, idx); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(buf, loc->names[idx].call.c_str(), bufsiz); buf[bufsiz-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField(tQSL_Location locp, const char *name, char *namebuf, int bufsize) { int old_page; TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getStationLocationField", "loc error %d", tQSL_Error); return 1; } if (name == NULL || namebuf == NULL) { tqslTrace("tqsl_getStationLocationField", "arg error name=0x%lx, namebuf=0x%lx", name, namebuf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (tqsl_getStationLocationCapturePage(loc, &old_page)) { tqslTrace("tqsl_getStationLocationField", "get cap page error %d", tQSL_Error); return 1; } string find = name; tqsl_setStationLocationCapturePage(loc, 1); do { int numf; if (tqsl_getNumLocationField(loc, &numf)) { tqslTrace("tqsl_getStationLocationField", "error getting num fields %d", tQSL_Error); return 1; } for (int i = 0; i < numf; i++) { TQSL_LOCATION_FIELD& field = loc->pagelist[loc->page-1].fieldlist[i]; if (find == field.gabbi_name) { // Found it switch (field.input_type) { case TQSL_LOCATION_FIELD_DDLIST: case TQSL_LOCATION_FIELD_LIST: if (field.data_type == TQSL_LOCATION_FIELD_INT) { char numbuf[20]; if (static_cast(field.items.size()) <= field.idx) { strncpy(namebuf, field.cdata.c_str(), bufsize); } else if (field.idx == 0 && field.items[field.idx].label == "[None]") { strncpy(namebuf, "", bufsize); } else { snprintf(numbuf, sizeof numbuf, "%d", field.items[field.idx].ivalue); strncpy(namebuf, numbuf, bufsize); } } else if (field.idx < 0 || field.idx >= static_cast(field.items.size())) { // Allow CALL to not be in the items list if (field.idx == -1 && i == 0) strncpy(namebuf, field.cdata.c_str(), bufsize); else strncpy(namebuf, "", bufsize); } else { if (field.items[field.idx].label == "") { strncpy(namebuf, field.items[field.idx].text.c_str(), bufsize); } else { strncpy(namebuf, field.items[field.idx].label.c_str(), bufsize); } } break; case TQSL_LOCATION_FIELD_TEXT: field.cdata = trim(field.cdata); if (field.flags & TQSL_LOCATION_FIELD_UPPER) field.cdata = string_toupper(field.cdata); strncpy(namebuf, field.cdata.c_str(), bufsize); break; } goto done; } } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; if (tqsl_nextStationLocationCapture(loc)) { tqslTrace("tqsl_getStationLocationField", "error in nextStationLocationCapture %d", tQSL_Error); return 1; } } while (1); strncpy(namebuf, "", bufsize); // Did not find it done: tqsl_setStationLocationCapturePage(loc, old_page); return 0; } static int tqsl_location_to_xml(TQSL_LOCATION *loc, XMLElement& sd) { int old_page; if (tqsl_getStationLocationCapturePage(loc, &old_page)) { tqslTrace("tqsl_location_to_xml", "get_sta_loc_cap_page error %d", tQSL_Error); return 1; } tqsl_setStationLocationCapturePage(loc, 1); do { int numf; if (tqsl_getNumLocationField(loc, &numf)) { tqslTrace("tqsl_location_to_xml", "get num loc field error %d", tQSL_Error); return 1; } for (int i = 0; i < numf; i++) { TQSL_LOCATION_FIELD& field = loc->pagelist[loc->page-1].fieldlist[i]; XMLElement *fd = new XMLElement; fd->setPretext(sd.getPretext() + " "); fd->setElementName(field.gabbi_name); switch (field.input_type) { case TQSL_LOCATION_FIELD_DDLIST: case TQSL_LOCATION_FIELD_LIST: if (field.idx < 0 || field.idx >= static_cast(field.items.size())) { fd->setText(""); if (field.gabbi_name == "CALL") { fd->setText("NONE"); } } else if (field.data_type == TQSL_LOCATION_FIELD_INT) { char numbuf[20]; snprintf(numbuf, sizeof numbuf, "%d", field.items[field.idx].ivalue); fd->setText(numbuf); } else { fd->setText(field.items[field.idx].text); } break; case TQSL_LOCATION_FIELD_TEXT: field.cdata = trim(field.cdata); if (field.flags & TQSL_LOCATION_FIELD_UPPER) field.cdata = string_toupper(field.cdata); fd->setText(field.cdata); break; } if (strcmp(fd->getText().c_str(), "")) sd.addElement(fd); } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; if (tqsl_nextStationLocationCapture(loc)) return 1; } while (1); tqsl_setStationLocationCapturePage(loc, old_page); return 0; } DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCaptureName(tQSL_Location locp, const char *name) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_setStationLocationCaptureName", "loc error %d", tQSL_Error); return 1; } if (name == NULL) { tqslTrace("tqsl_setStationLocationCaptureName", "arg error name=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } loc->name = name; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCaptureName(tQSL_Location locp, char *namebuf, int bufsize) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_getStationLocationCaptureName", "loc error %d", tQSL_Error); return 1; } if (namebuf == NULL) { tqslTrace("tqsl_getStationLocationCaptureName", "arg error namebuf=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(namebuf, loc->name.c_str(), bufsize); namebuf[bufsize-1] = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_saveStationLocationCapture(tQSL_Location locp, int overwrite) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp))) { tqslTrace("tqsl_saveStationLocationCaptureName", "loc error %d", tQSL_Error); return 1; } if (loc->name == "") { tqslTrace("tqsl_saveStationLocationCaptureName", "name empty"); tQSL_Error = TQSL_EXPECTED_NAME; return 1; } XMLElement top_el; if (tqsl_load_station_data(top_el)) { tqslTrace("tqsl_saveStationLocationCaptureName", "error %d loading station data", tQSL_Error); return 1; } XMLElement sfile; if (!top_el.getFirstElement(sfile)) sfile.setElementName("StationDataFile"); XMLElementList& ellist = sfile.getElementList(); bool exists = false; XMLElementList::iterator ep; for (ep = ellist.find("StationData"); ep != ellist.end(); ep++) { if (ep->first != "StationData") break; pair rval = ep->second->getAttribute("name"); if (rval.second && !strcasecmp(rval.first.c_str(), loc->name.c_str())) { exists = true; break; } } if (exists && !overwrite) { tqslTrace("tqsl_saveStationLocationCaptureName", "exists, no overwrite"); tQSL_Error = TQSL_NAME_EXISTS; return 1; } XMLElement *sd = new XMLElement("StationData"); sd->setPretext("\n "); if (tqsl_location_to_xml(loc, *sd)) { tqslTrace("tqsl_saveStationLocationCaptureName", "error in loc_to_xml %d", tQSL_Error); return 1; } sd->setAttribute("name", loc->name); sd->setText("\n "); // If 'exists', ep points to the existing station record if (exists) ellist.erase(ep); sfile.addElement(sd); sfile.setText("\n"); return tqsl_dump_station_data(sfile); } DLLEXPORT int CALLCONVENTION tqsl_signQSORecord(tQSL_Cert cert, tQSL_Location locp, TQSL_QSO_RECORD *rec, unsigned char *sig, int *siglen) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_signQSORecord", "loc error %d", tQSL_Error); return 1; } if (make_sign_data(loc)) { tqslTrace("tqsl_signQSORecord", "error %d making sign data", tQSL_Error); return 1; } XMLElement specfield; bool ok = tCONTACT_sign.getFirstElement(specfield); string rec_sign_data = loc->signdata; while (ok) { string eln = specfield.getElementName(); const char *elname = eln.c_str(); const char *value = 0; char buf[100]; if (!strcmp(elname, "CALL")) { value = rec->callsign; } else if (!strcmp(elname, "BAND")) { value = rec->band; } else if (!strcmp(elname, "BAND_RX")) { value = rec->rxband; } else if (!strcmp(elname, "MODE")) { value = rec->mode; } else if (!strcmp(elname, "FREQ")) { value = rec->freq; } else if (!strcmp(elname, "FREQ_RX")) { value = rec->rxfreq; } else if (!strcmp(elname, "PROP_MODE")) { value = rec->propmode; } else if (!strcmp(elname, "SAT_NAME")) { value = rec->satname; } else if (!strcmp(elname, "QSO_DATE")) { if (tqsl_isDateValid(&(rec->date))) value = tqsl_convertDateToText(&(rec->date), buf, sizeof buf); } else if (!strcmp(elname, "QSO_TIME")) { if (tqsl_isTimeValid(&(rec->time))) value = tqsl_convertTimeToText(&(rec->time), buf, sizeof buf); } else { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Unknown field in signing specification: %s", elname); tqslTrace("tqsl_signQSORecord", "field err %s", tQSL_CustomError); return 1; } if (value == 0 || value[0] == 0) { pair attr = specfield.getAttribute("required"); if (attr.second && strtol(attr.first.c_str(), NULL, 10)) { string err = specfield.getElementName() + " field required by signature specification not found"; tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, err.c_str(), sizeof tQSL_CustomError); tqslTrace("tqsl_signQSORecord", "val err %s", tQSL_CustomError); return 1; } } else { string v(value); rec_sign_data += trim(v); } ok = tCONTACT_sign.getNextElement(specfield); } return tqsl_signDataBlock(cert, (const unsigned char *)rec_sign_data.c_str(), rec_sign_data.size(), sig, siglen); } DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCERT(tQSL_Cert cert, int uid) { static string s; s = ""; char buf[3000]; if (tqsl_getCertificateEncoded(cert, buf, sizeof buf)) return 0; char *cp = strstr(buf, "-----END CERTIFICATE-----"); if (cp) *cp = 0; if ((cp = strstr(buf, "\n"))) cp++; else cp = buf; s = "tCERT\n"; char sbuf[10], lbuf[40]; snprintf(sbuf, sizeof sbuf, "%d", uid); snprintf(lbuf, sizeof lbuf, "%s\n", static_cast(strlen(sbuf)), sbuf); s += lbuf; snprintf(lbuf, sizeof lbuf, "", static_cast(strlen(cp))); s += lbuf; s += cp; s += "\n"; return s.c_str(); //KC2YWE 1/26 - dangerous but might work since s is static } DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItSTATION(tQSL_Location locp, int uid, int certuid) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getGABBItSTATION", "loc error %d", tQSL_Error); return 0; } unsigned char *buf = 0; int bufsiz = 0; loc->tSTATION = "tSTATION\n"; char sbuf[10], lbuf[40]; snprintf(sbuf, sizeof sbuf, "%d", uid); snprintf(lbuf, sizeof lbuf, "%s\n", static_cast(strlen(sbuf)), sbuf); loc->tSTATION += lbuf; snprintf(sbuf, sizeof sbuf, "%d", certuid); snprintf(lbuf, sizeof lbuf, "%s\n", static_cast(strlen(sbuf)), sbuf); loc->tSTATION += lbuf; int old_page = loc->page; tqsl_setStationLocationCapturePage(loc, 1); do { TQSL_LOCATION_PAGE& p = loc->pagelist[loc->page-1]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD& f = p.fieldlist[i]; string s; if (f.input_type == TQSL_LOCATION_FIELD_BADZONE) // Don't output these to tSTATION continue; if (f.input_type == TQSL_LOCATION_FIELD_DDLIST || f.input_type == TQSL_LOCATION_FIELD_LIST) { if (f.idx < 0 || f.idx >= static_cast(f.items.size())) { s = ""; } else { s = f.items[f.idx].text; } } else if (f.data_type == TQSL_LOCATION_FIELD_INT) { char buf[20]; snprintf(buf, sizeof buf, "%d", f.idata); s = buf; } else { s = f.cdata; } if (s.size() == 0) continue; int wantsize = s.size() + f.gabbi_name.size() + 20; if (buf == 0 || bufsiz < wantsize) { if (buf != 0) delete[] buf; buf = new unsigned char[wantsize]; bufsiz = wantsize; } if (tqsl_adifMakeField(f.gabbi_name.c_str(), 0, (unsigned char *)s.c_str(), s.size(), buf, bufsiz)) { delete[] buf; return 0; } loc->tSTATION += (const char *)buf; loc->tSTATION += "\n"; } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; tqsl_nextStationLocationCapture(loc); } while (1); tqsl_setStationLocationCapturePage(loc, old_page); if (buf != 0) delete[] buf; loc->tSTATION += "\n"; return loc->tSTATION.c_str(); } DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCONTACTData(tQSL_Cert cert, tQSL_Location locp, TQSL_QSO_RECORD *qso, int stationuid, char* signdata, int sdlen) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getGABBItCONTACTData", "loc error %d", tQSL_Error); return 0; } if (make_sign_data(loc)) { tqslTrace("tqsl_getGABBItCONTACTData", "make_sign_data error %d", tQSL_Error); return 0; } XMLElement specfield; bool ok = tCONTACT_sign.getFirstElement(specfield); string rec_sign_data = loc->signdata; loc->qso_details = ""; while(ok) { string en = specfield.getElementName(); const char *elname = en.c_str(); const char *value = 0; char buf[100]; if (!strcmp(elname, "CALL")) { value = qso->callsign; } else if (!strcmp(elname, "BAND")) { value = qso->band; } else if (!strcmp(elname, "BAND_RX")) { value = qso->rxband; } else if (!strcmp(elname, "MODE")) { value = qso->mode; } else if (!strcmp(elname, "FREQ")) { value = qso->freq; } else if (!strcmp(elname, "FREQ_RX")) { value = qso->rxfreq; } else if (!strcmp(elname, "PROP_MODE")) { value = qso->propmode; } else if (!strcmp(elname, "SAT_NAME")) { value = qso->satname; } else if (!strcmp(elname, "QSO_DATE")) { if (tqsl_isDateValid(&(qso->date))) value = tqsl_convertDateToText(&(qso->date), buf, sizeof buf); } else if (!strcmp(elname, "QSO_TIME")) { if (tqsl_isTimeValid(&(qso->time))) value = tqsl_convertTimeToText(&(qso->time), buf, sizeof buf); } else { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Unknown field in signing specification: %s", elname); tqslTrace("tqsl_getGABBItCONTACTData", "field err %s", tQSL_CustomError); return 0; } if (value == 0 || value[0] == 0) { pair attr = specfield.getAttribute("required"); if (attr.second && strtol(attr.first.c_str(), NULL, 10)) { string err = specfield.getElementName() + " field required by signature specification not found"; tQSL_Error = TQSL_CUSTOM_ERROR; strncpy(tQSL_CustomError, err.c_str(), sizeof tQSL_CustomError); tqslTrace("tqsl_getGABBItCONTACTData", "field err %s", tQSL_CustomError); return 0; } } else { string v(value); rec_sign_data += trim(v); loc->qso_details += trim(v); } ok = tCONTACT_sign.getNextElement(specfield); } unsigned char sig[129]; int siglen = sizeof sig; rec_sign_data = string_toupper(rec_sign_data); if (tqsl_signDataBlock(cert, (const unsigned char *)rec_sign_data.c_str(), rec_sign_data.size(), sig, &siglen)) return 0; char b64[512]; if (tqsl_encodeBase64(sig, siglen, b64, sizeof b64)) return 0; loc->tCONTACT = "tCONTACT\n"; char sbuf[10], lbuf[40]; snprintf(sbuf, sizeof sbuf, "%d", stationuid); snprintf(lbuf, sizeof lbuf, "%s\n", static_cast(strlen(sbuf)), sbuf); loc->tCONTACT += lbuf; char buf[256]; tqsl_adifMakeField("CALL", 0, (const unsigned char *)qso->callsign, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; tqsl_adifMakeField("BAND", 0, (const unsigned char *)qso->band, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; tqsl_adifMakeField("MODE", 0, (const unsigned char *)qso->mode, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; // Optional fields if (qso->freq[0] != 0) { tqsl_adifMakeField("FREQ", 0, (const unsigned char *)qso->freq, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; } if (qso->rxfreq[0] != 0) { tqsl_adifMakeField("FREQ_RX", 0, (const unsigned char *)qso->rxfreq, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; } if (qso->propmode[0] != 0) { tqsl_adifMakeField("PROP_MODE", 0, (const unsigned char *)qso->propmode, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; } if (qso->satname[0] != 0) { tqsl_adifMakeField("SAT_NAME", 0, (const unsigned char *)qso->satname, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; } if (qso->rxband[0] != 0) { tqsl_adifMakeField("BAND_RX", 0, (const unsigned char *)qso->rxband, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; } // Date and Time char date_buf[40] = ""; tqsl_convertDateToText(&(qso->date), date_buf, sizeof date_buf); tqsl_adifMakeField("QSO_DATE", 0, (const unsigned char *)date_buf, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; date_buf[0] = 0; tqsl_convertTimeToText(&(qso->time), date_buf, sizeof date_buf); tqsl_adifMakeField("QSO_TIME", 0, (const unsigned char *)date_buf, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; tqsl_adifMakeField(loc->sigspec.c_str(), '6', (const unsigned char *)b64, -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; // Signature tqsl_adifMakeField("SIGNDATA", 0, (const unsigned char *)rec_sign_data.c_str(), -1, (unsigned char *)buf, sizeof buf); loc->tCONTACT += buf; loc->tCONTACT += "\n"; loc->tCONTACT += "\n"; if (signdata) strncpy(signdata, rec_sign_data.c_str(), sdlen); return loc->tCONTACT.c_str(); } DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCONTACT(tQSL_Cert cert, tQSL_Location locp, TQSL_QSO_RECORD *qso, int stationuid) { return tqsl_getGABBItCONTACTData(cert, locp, qso, stationuid, NULL, 0); } DLLEXPORT int CALLCONVENTION tqsl_getLocationCallSign(tQSL_Location locp, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getLocationCallSign", "loc error %d", tQSL_Error); return 1; } if (buf == NULL || bufsiz <= 0) { tqslTrace("tqsl_getLocationCallSign", "arg error buf=0x%lx, bufsiz=%d", buf, bufsiz); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_LOCATION_PAGE& p = loc->pagelist[0]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD f = p.fieldlist[i]; if (f.gabbi_name == "CALL") { strncpy(buf, f.cdata.c_str(), bufsiz); buf[bufsiz-1] = 0; if (static_cast(f.cdata.size()) >= bufsiz) { tqslTrace("tqsl_getLocationCallSign", "buf error req=%d avail=%d", static_cast(f.cdata.size()), bufsiz); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } return 0; } } tQSL_Error = TQSL_CALL_NOT_FOUND; return 1; } DLLEXPORT int CALLCONVENTION tqsl_setLocationCallSign(tQSL_Location locp, const char *buf, int dxcc) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_setLocationCallSign", "loc error %d", tQSL_Error); return 1; } if (buf == NULL) { tqslTrace("tqsl_setLocationCallSign", "arg error buf=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_LOCATION_PAGE& p = loc->pagelist[0]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD f = p.fieldlist[i]; if (f.gabbi_name == "CALL") { for (int j = 0; j < static_cast(f.items.size()); j++) { if (f.items[j].text == buf) { loc->pagelist[0].fieldlist[i].idx = j; loc->pagelist[0].fieldlist[i].cdata = buf; loc->newflags = true; loc->newDXCC = dxcc; break; } } return 0; } } tQSL_Error = TQSL_CALL_NOT_FOUND; return 1; } DLLEXPORT int CALLCONVENTION tqsl_getLocationField(tQSL_Location locp, const char *field, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getLocationField", "loc error %d", tQSL_Error); return 1; } if (buf == NULL || bufsiz <= 0) { tqslTrace("tqsl_getLocationField", "arg error buf=0x%lx, bufsiz=%d", buf, bufsiz); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *buf = '\0'; int old_page = loc->page; tqsl_setStationLocationCapturePage(loc, 1); do { TQSL_LOCATION_PAGE& p = loc->pagelist[loc->page-1]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD f = p.fieldlist[i]; if (f.gabbi_name == field) { if ((f.gabbi_name == "ITUZ" || f.gabbi_name == "CQZ") && f.cdata == "0") { buf[0] = '\0'; } else { strncpy(buf, f.cdata.c_str(), bufsiz); } buf[bufsiz-1] = 0; if (static_cast(f.cdata.size()) >= bufsiz) { tqslTrace("tqsl_getLocationField", "buf error req=%d avail=%d", static_cast(f.cdata.size()), bufsiz); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } tqsl_setStationLocationCapturePage(loc, old_page); return 0; } } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; tqsl_nextStationLocationCapture(loc); } while (1); tQSL_Error = TQSL_CALL_NOT_FOUND; return 1; } DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel(tQSL_Location locp, const char *field, char *buf, int bufsiz) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getLocationFieldLabel", "loc error %d", tQSL_Error); return 1; } if (buf == NULL || bufsiz <= 0) { tqslTrace("tqsl_getLocationFieldLabel", "arg error buf=0x%lx, bufsiz=%d", buf, bufsiz); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *buf = '\0'; int old_page = loc->page; tqsl_setStationLocationCapturePage(loc, 1); do { TQSL_LOCATION_PAGE& p = loc->pagelist[loc->page-1]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD f = p.fieldlist[i]; if (f.gabbi_name == field) { if ((f.gabbi_name == "ITUZ" || f.gabbi_name == "CQZ") && f.cdata == "0") { buf[0] = '\0'; } else { if (static_cast(f.items.size()) > f.idx) strncpy(buf, f.items[f.idx].label.c_str(), bufsiz); } buf[bufsiz-1] = 0; if (static_cast(f.label.size()) >= bufsiz) { tqslTrace("tqsl_getLocationFieldLabel", "buf error req=%d avail=%d", static_cast(f.cdata.size()), bufsiz); tQSL_Error = TQSL_BUFFER_ERROR; return 1; } tqsl_setStationLocationCapturePage(loc, old_page); return 0; } } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; tqsl_nextStationLocationCapture(loc); } while (1); tQSL_Error = TQSL_CALL_NOT_FOUND; return 1; } // Replaces all occurrences of 'from' with 'to' in string 'str' static void replaceAll(string& str, const string& from, const string& to) { if (from.empty()) { return; } size_t start_pos = 0; while((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' } } static bool fuzzy_match(string userInput, string field) { // First upcase string left = string_toupper(userInput); string right = string_toupper(field); // Strip spaces replaceAll(left, " ", ""); replaceAll(right, " ", ""); // Strip apostraphes replaceAll(left, "'", ""); replaceAll(right, "'", ""); // Strip hyphens replaceAll(left, "-", ""); replaceAll(right, "-", ""); // Alaska fixes replaceAll(left, "CITYANDBOROUGH", ""); replaceAll(right, "CITYANDBOROUGH", ""); replaceAll(left, "BOROUGH", ""); replaceAll(right, "BOROUGH", ""); replaceAll(left, "CENSUSAREA", ""); replaceAll(right, "CENSUSAREA", ""); replaceAll(left, "MUNICIPALITY", ""); replaceAll(right, "MUNICIPALITY", ""); // Normalize saints replaceAll(left, "ST.", "SAINT"); replaceAll(right, "ST.", "SAINT"); replaceAll(left, "STE.", "SAINTE"); replaceAll(right, "STE.", "SAINTE"); // One-offs replaceAll(left, "DOÑAANA", "DONAANA"); replaceAll(right, "DOÑAANA", "DONAANA"); replaceAll(left, "BRISTOLCITY", "BRISTOL"); replaceAll(right, "BRISTOLCITY", "BRISTOL"); replaceAll(left, "SALEMCITY", "SALEM"); replaceAll(right, "SALEMCITY", "SALEM"); return (left == right); } DLLEXPORT int CALLCONVENTION tqsl_setLocationField(tQSL_Location locp, const char *field, const char *buf) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_setLocationField", "loc error %d", tQSL_Error); return 1; } if (buf == NULL) { tqslTrace("tqsl_setLocationField", "arg error buf=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } int old_page = loc->page; tqsl_setStationLocationCapturePage(loc, 1); do { TQSL_LOCATION_PAGE& p = loc->pagelist[loc->page-1]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD *pf = &p.fieldlist[i]; if (pf->gabbi_name == field) { bool found = false; bool adifVal = false; pf->cdata = string(buf).substr(0, pf->data_len); if (pf->flags & TQSL_LOCATION_FIELD_UPPER) pf->cdata = string_toupper(pf->cdata); if (pf->input_type == TQSL_LOCATION_FIELD_DDLIST || pf->input_type == TQSL_LOCATION_FIELD_LIST) { if (pf->cdata == "") { pf->idx = 0; pf->idata = pf->items[0].ivalue; } else { for (int i = 0; i < static_cast(pf->items.size()); i++) { if (string_toupper(pf->items[i].text) == string_toupper(pf->cdata)) { pf->cdata = pf->items[i].text; pf->idx = i; pf->idata = pf->items[i].ivalue; found = true; break; } if (fuzzy_match(pf->items[i].label, pf->cdata)) { strncpy(tQSL_CustomError, pf->items[i].text.c_str(), sizeof tQSL_CustomError); pf->cdata = pf->items[i].text; pf->idx = i; pf->idata = pf->items[i].ivalue; found = true; adifVal = true; break; } } // This was being used to force-add fields to enumerations, but that's wrong. // Keeping it around in case it's useful later. // if (!found) { // TQSL_LOCATION_ITEM item; // item.text = buf; // item.ivalue = strtol(buf, NULL, 10); // pf->items.push_back(item); // pf->idx = pf->items.size() - 1; // pf->idata = item.ivalue; // } } } else if (pf->data_type == TQSL_LOCATION_FIELD_INT) { pf->idata = strtol(buf, NULL, 10); } tqsl_setStationLocationCapturePage(loc, old_page); if (adifVal) return -2; if (!found) return -1; return 0; } } int rval; if (tqsl_hasNextStationLocationCapture(loc, &rval) || !rval) break; tqsl_nextStationLocationCapture(loc); } while (1); tqsl_setStationLocationCapturePage(loc, old_page); tQSL_Error = TQSL_CALL_NOT_FOUND; return 1; } DLLEXPORT int CALLCONVENTION tqsl_getLocationDXCCEntity(tQSL_Location locp, int *dxcc) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getLocationDXCCEntity", "loc error %d", tQSL_Error); return 1; } if (dxcc == NULL) { tqslTrace("tqsl_getLocationDXCCEntity", "arg err dxcc=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } TQSL_LOCATION_PAGE& p = loc->pagelist[0]; for (int i = 0; i < static_cast(p.fieldlist.size()); i++) { TQSL_LOCATION_FIELD f = p.fieldlist[i]; if (f.gabbi_name == "DXCC") { if (f.idx < 0 || f.idx >= static_cast(f.items.size())) break; // No matching DXCC entity *dxcc = f.items[f.idx].ivalue; return 0; } } tqslTrace("tqsl_getLocationDXCCEntity", "name not found"); tQSL_Error = TQSL_NAME_NOT_FOUND; return 1; } DLLEXPORT int CALLCONVENTION tqsl_getNumProviders(int *n) { if (n == NULL) { tqslTrace("tqsl_getNumProviders", "arg error n=null"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } vector plist; if (tqsl_load_provider_list(plist)) { tqslTrace("tqsl_getNumProviders", "error loading providers %d", tQSL_Error); return 1; } if (plist.size() == 0) { tqslTrace("tqsl_getNumProviders", "prov not found"); tQSL_Error = TQSL_PROVIDER_NOT_FOUND; return 1; } *n = plist.size(); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getProvider(int idx, TQSL_PROVIDER *provider) { if (provider == NULL || idx < 0) { tqslTrace("tqsl_getProvider", "arg error provider=0x%lx, idx=%d", provider, idx); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } vector plist; if (tqsl_load_provider_list(plist)) { tqslTrace("tqsl_getProvider", "err %d loading list", tQSL_Error); return 1; } if (idx >= static_cast(plist.size())) { tqslTrace("tqsl_getProvider", "prov not found"); tQSL_Error = TQSL_PROVIDER_NOT_FOUND; return 1; } *provider = plist[idx]; return 0; } DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile(const char *file, int(*cb)(int type, const char *, void *), void *userdata) { bool foundcerts = false; tQSL_ImportCall[0] = '\0'; tQSL_ImportSerial = 0; int rval = 0; if (file == NULL) { tqslTrace("tqsl_importTQSLFile", "file=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } XMLElement topel; int status = topel.parseFile(file); if (status) { strncpy(tQSL_ErrorFile, file, sizeof tQSL_ErrorFile); if (status == XML_PARSE_SYSTEM_ERROR) { tQSL_Error = TQSL_FILE_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_importTQSLFile", "system error file=%s err=%s", file, strerror(tQSL_Errno)); } else { tQSL_Error = TQSL_FILE_SYNTAX_ERROR; tqslTrace("tqsl_importTQSLFile", "file %s syntax error", file); } return 1; } XMLElement tqsldata; if (!topel.getFirstElement("tqsldata", tqsldata)) { strncpy(tQSL_ErrorFile, file, sizeof tQSL_ErrorFile); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; return 1; } XMLElement section; bool stat = tqsldata.getFirstElement("tqslcerts", section); if (stat) { XMLElement cert; bool cstat = section.getFirstElement("rootcert", cert); while (cstat) { foundcerts = true; if (tqsl_import_cert(cert.getText().c_str(), ROOTCERT, cb, userdata)) { tqslTrace("tqsl_importTQSLFile", "duplicate/expired root cert"); } cstat = section.getNextElement(cert); } cstat = section.getFirstElement("cacert", cert); while (cstat) { foundcerts = true; if (tqsl_import_cert(cert.getText().c_str(), CACERT, cb, userdata)) { tqslTrace("tqsl_importTQSLFile", "duplicate/expired ca cert"); } cstat = section.getNextElement(cert); } cstat = section.getFirstElement("usercert", cert); while (cstat) { foundcerts = true; if (tqsl_import_cert(cert.getText().c_str(), USERCERT, cb, userdata)) { tqslTrace("tqsl_importTQSLFile", "error importing user cert"); tQSL_Error = TQSL_CERT_ERROR; rval = 1; } cstat = section.getNextElement(cert); } } // If any of the user certificates failed import, return the error status. if (rval) { return rval; } stat = tqsldata.getFirstElement("tqslconfig", section); if (stat) { // Check to make sure we aren't overwriting newer version int major = strtol(section.getAttribute("majorversion").first.c_str(), NULL, 10); int minor = strtol(section.getAttribute("minorversion").first.c_str(), NULL, 10); int curmajor, curminor; if (tqsl_getConfigVersion(&curmajor, &curminor)) { tqslTrace("tqsl_importTQSLFile", "Get config ver error %d", tQSL_Error); return 1; } if (major < curmajor) { if (foundcerts) { tqslTrace("tqsl_importTQSLFile", "Suppressing update from V%d.%d to V%d.%d", curmajor, curminor, major, minor); return rval; } tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "This configuration file (V%d.%d) is older than the currently installed one (V%d.%d). It will not be installed.", major, minor, curmajor, curminor); tqslTrace("tqsl_importTQSLFile", "Config update error: %s", tQSL_CustomError); return 1; } if (major == curmajor) { if (minor == curminor) { // Same rev as already installed tqslTrace("tqsl_importTQSLFile", "Suppressing update from V%d.%d to V%d.%d", curmajor, curminor, major, minor); return rval; } if (minor < curminor) { if (foundcerts) { tqslTrace("tqsl_importTQSLFile", "Suppressing update from V%d.%d to V%d.%d", curmajor, curminor, major, minor); return rval; } tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "This configuration file (V%d.%d) is older than the currently installed one (V%d.%d). It will not be installed.", major, minor, curmajor, curminor); tqslTrace("tqsl_importTQSLFile", "Config update error: %s", tQSL_CustomError); return rval; } } // Save the configuration file ofstream out; #ifdef _WIN32 string fn = string(tQSL_BaseDir) + "\\config.xml"; #else string fn = string(tQSL_BaseDir) + "/config.xml"; #endif out.exceptions(ios::failbit | ios::eofbit | ios::badbit); try { #ifdef _WIN32 wchar_t *wfn = utf8_to_wchar(fn.c_str()); out.open(wfn); free_wchar(wfn); #else out.open(fn.c_str()); #endif out << section << endl; out.close(); } catch(exception& x) { tQSL_Error = TQSL_CUSTOM_ERROR; snprintf(tQSL_CustomError, sizeof tQSL_CustomError, "Error writing new configuration file (%s): %s/%s", fn.c_str(), x.what(), strerror(errno)); tqslTrace("tqsl_importTQSLFile", "I/O error: %s", tQSL_CustomError); if (cb) return (*cb)(TQSL_CERT_CB_RESULT | TQSL_CERT_CB_ERROR | TQSL_CERT_CB_CONFIG, fn.c_str(), userdata); if (tQSL_Error == 0) { tQSL_Error = TQSL_CERT_ERROR; } return 1; } // Clear stored config data to force re-reading new config DXCCMap.clear(); DXCCList.clear(); DeletedMap.clear(); DXCCZoneMap.clear(); DXCCStartMap.clear(); DXCCEndMap.clear(); BandList.clear(); ModeList.clear(); PropModeList.clear(); SatelliteList.clear(); tqsl_page_map.clear(); tqsl_field_map.clear(); tqsl_adif_map.clear(); tqsl_adif_mode_map.clear(); tqsl_adif_submode_map.clear(); tqsl_cabrillo_map.clear(); tqsl_cabrillo_user_map.clear(); tqsl_xml_config.clear(); // Now reload it all tqsl_load_xml_config(); string version = "Configuration V" + section.getAttribute("majorversion").first + "." + section.getAttribute("minorversion").first + "\n" + fn; if (cb) { int cbret = (*cb)(TQSL_CERT_CB_RESULT | TQSL_CERT_CB_LOADED | TQSL_CERT_CB_CONFIG, version.c_str(), userdata); if (cbret || rval) { if (tQSL_Error == 0) { tQSL_Error = TQSL_CERT_ERROR; } return 1; } } } if (rval && tQSL_Error == 0) { tQSL_Error = TQSL_CERT_ERROR; } return rval; } /* * Get the first user certificate from a .tq6 file */ DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile(const char *file, long *serial) { XMLElement topel; if (file == NULL || serial == NULL) { tqslTrace("tqsl_getSerialFromTQSLFile", "Arg error file=0x%lx, serial=0x%lx", file, serial); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } int status = topel.parseFile(file); if (status) { strncpy(tQSL_ErrorFile, file, sizeof tQSL_ErrorFile); if (status == XML_PARSE_SYSTEM_ERROR) { tQSL_Error = TQSL_FILE_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_getSerialFromTQSLFile", "parse error %d, error %s", tQSL_Error, strerror(tQSL_Errno)); } else { tQSL_Error = TQSL_FILE_SYNTAX_ERROR; tqslTrace("tqsl_getSerialFromTQSLFile", "parse syntax error %d", tQSL_Error); } return 1; } XMLElement tqsldata; if (!topel.getFirstElement("tqsldata", tqsldata)) { strncpy(tQSL_ErrorFile, file, sizeof tQSL_ErrorFile); tqslTrace("tqsl_getSerialFromTQSLFile", "parse syntax error %d", tQSL_Error); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; return 1; } XMLElement section; bool stat = tqsldata.getFirstElement("tqslcerts", section); if (stat) { XMLElement cert; bool cstat = section.getFirstElement("usercert", cert); if (cstat) { if (tqsl_get_pem_serial(cert.getText().c_str(), serial)) { strncpy(tQSL_ErrorFile, file, sizeof tQSL_ErrorFile); tqslTrace("tqsl_getSerialFromTQSLFile", "parse syntax error %d", tQSL_Error); tQSL_Error = TQSL_FILE_SYNTAX_ERROR; return 1; } return 0; } } tqslTrace("tqsl_getSerialFromTQSLFile", "no usercert in file %s", file); return 1; } DLLEXPORT int CALLCONVENTION tqsl_getDeletedStationLocations(char ***locp, int *nloc) { if (locp == NULL) { tqslTrace("tqsl_getDeletedStationLocations", "arg error locp=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (nloc == NULL) { tqslTrace("tqsl_getDeletedStationLocations", "arg error nloc=NULL"); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *locp = NULL; *nloc = 0; vector namelist; XMLElement top_el; if (tqsl_load_station_data(top_el, true)) { tqslTrace("tqsl_getDeletedStationLocations", "error %d loading station data", tQSL_Error); return 1; } XMLElement sfile; if (top_el.getFirstElement(sfile)) { XMLElement sd; bool ok = sfile.getFirstElement("StationData", sd); while (ok && sd.getElementName() == "StationData") { pair name = sd.getAttribute("name"); if (name.second) { namelist.push_back(name.first); } ok = sfile.getNextElement(sd); } } *nloc = namelist.size(); if (*nloc == 0) { *locp = NULL; return 0; } *locp = reinterpret_cast(calloc(*nloc, sizeof(**locp))); vector::iterator it; char **p = *locp; for (it = namelist.begin(); it != namelist.end(); it++) { *p++ = strdup((*it).c_str()); } return 0; } DLLEXPORT void CALLCONVENTION tqsl_freeDeletedLocationList(char** list, int nloc) { if (!list) return; for (int i = 0; i < nloc; i++) if (list[i]) free(list[i]); if (list) free(list); } DLLEXPORT int CALLCONVENTION tqsl_getLocationQSODetails(tQSL_Location locp, char *buf, int buflen) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getLocationQSODetails", "loc error %d", tQSL_Error); return 1; } if (buf == NULL) { tqslTrace("tqsl_getLocationQSODetails", "Argument error, buf = 0x%lx", buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(buf, loc->qso_details.c_str(), buflen); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getLocationStationDetails(tQSL_Location locp, char *buf, int buflen) { TQSL_LOCATION *loc; if (!(loc = check_loc(locp, false))) { tqslTrace("tqsl_getLocationStationDetails", "loc error %d", tQSL_Error); return 1; } if (buf == NULL) { tqslTrace("tqsl_getLocationStationDetails", "Argument error, buf = 0x%lx", buf); tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } strncpy(buf, loc->loc_details.c_str(), buflen); return 0; } tqsl-2.7.2/src/load_cert.cpp0000644000175000017500000000201114534122221015720 0ustar rmurphyrmurphy/*************************************************************************** load_cert.cpp - description ------------------- begin : Sat Dec 14 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "sysconfig.h" #endif #include #include #include "tqsllib.h" using std::string; using std::ios; using std::cerr; using std::cout; using std::endl; int cb(int, const char *msg, void *) { cout << msg << endl; return 0; } int main(int argc, char *argv[]) { if (tqsl_init()) { cerr << tqsl_getErrorString() << endl; return EXIT_FAILURE; } for (int i = 1; i < argc; i++) { if (tqsl_importTQSLFile(argv[i], cb, 0)) { cerr << tqsl_getErrorString() << endl; return EXIT_FAILURE; } } return EXIT_SUCCESS; } tqsl-2.7.2/src/gen_crq.cpp0000644000175000017500000000752014534122221015414 0ustar rmurphyrmurphy/*************************************************************************** gen_crq.cpp - description ------------------- begin : Sat Dec 14 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ Generates a set of certificate-request files. ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "sysconfig.h" #endif #include #include #include #include #include #include #ifdef HAVE_GETOPT_H #include #endif #include #include #include "tqsllib.h" #include "tqslexc.h" using std::cerr; using std::endl; int usage() { std::cerr << "Usage: -e email -d dxcc [-c sign_call] [-x sign_dxcc] call1 [call2 ...]" << endl; exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { string sign_call, email_addr; int dxcc = 0, sign_dxcc = 0; tQSL_Cert sign_cert = 0; try { if (tqsl_init()) throw tqslexc(); int c; while ((c = getopt(argc, argv, "c:x:e:d:")) != -1) { switch (c) { case 'c': sign_call = optarg; break; case 'x': sign_dxcc = strtol(optarg, NULL, 10); break; case 'd': dxcc = strtol(optarg, NULL, 10); break; case 'e': email_addr = optarg; break; default: usage(); } } if (optind >= argc || email_addr == "" || dxcc == 0) usage(); if (sign_call != "") { // if (sign_dxcc == 0) // usage(); tQSL_Cert *list; int ncerts; if (tqsl_selectCertificates(&list, &ncerts, sign_call.c_str(), sign_dxcc, 0, 0, 1)) throw tqslexc(); if (ncerts < 1) { string erm = "No signing certificate found for " + sign_call; if (sign_dxcc) { const char *entity; tqsl_getDXCCEntityName(sign_dxcc, &entity); erm += " with DXCC Entity="; erm += entity; } throw myexc(erm); } sign_cert = *list; } else if (sign_dxcc != 0) { usage(); } if (sign_cert) { char buf[512]; long serial; int cdxcc; if (tqsl_getCertificateIssuer(sign_cert, buf, sizeof buf)) throw tqslexc(); if (tqsl_getCertificateSerial(sign_cert, &serial)) throw tqslexc(); if (tqsl_getCertificateDXCCEntity(sign_cert, &cdxcc)) throw tqslexc(); std::cout << "Signing certificate issuer: " << buf << endl; std::cout << "Signing certificate serial: " << serial << endl; std::cout << " Signing certificate DXCC: " << cdxcc << endl; if (tqsl_beginSigning(sign_cert, const_cast(""), 0, 0)) throw tqslexc(); } TQSL_CERT_REQ crq; memset(&crq, 0, sizeof crq); strncpy(crq.name, "Ish Kabibble", sizeof crq.name); strncpy(crq.address1, "1 No Place", sizeof crq.address1); strncpy(crq.city, "City", sizeof crq.city); strncpy(crq.state, "ST", sizeof crq.state); strncpy(crq.country, "USA", sizeof crq.country); strncpy(crq.emailAddress, email_addr.c_str(), sizeof crq.emailAddress); crq.dxccEntity = dxcc; tqsl_initDate(&crq.qsoNotBefore, "1945-11-15"); crq.signer = sign_cert; for (; optind < argc; optind++) { string call = argv[optind]; strncpy(crq.callSign, call.c_str(), sizeof crq.callSign); for (char *cp = argv[optind]; *cp; cp++) { if (*cp == '/') *cp = '_'; } string filename = string(argv[optind]) + ".tq5"; std::cout << "Creating CRQ for " << crq.callSign << " DXCC=" << crq.dxccEntity << endl; if (tqsl_createCertRequest(filename.c_str(), &crq, 0, 0)) throw tqslexc(); } return EXIT_SUCCESS; } catch(exception& x) { std::cerr << "Aborting: " << x.what() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } tqsl-2.7.2/src/dumptqsldata.cpp0000644000175000017500000000407014534122221016476 0ustar rmurphyrmurphy/*************************************************************************** dumptqsldata.c - description ------------------- begin : Mon Mar 3 2003 copyright : (C) 2003 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ /* Dumps the config data from the TQSL library */ #include #include #include "tqsllib.h" void errchk(int stat) { if (stat) { printf("ERROR: %s\n", tqsl_getErrorString()); exit(1); } } int main() { int count, i; const char *cp1, *cp2; tQSL_Date start, end; int low, high; char buf1[20], buf2[20]; errchk(tqsl_init()); puts("===== MODES =====\n Mode Group"); errchk(tqsl_getNumMode(&count)); for (i = 0; i < count; i++) { errchk(tqsl_getMode(i, &cp1, &cp2)); printf(" %-10.10s %s\n", cp1, cp2); } puts("\n===== BANDS =====\n Band Spectrum Low High"); errchk(tqsl_getNumBand(&count)); for (i = 0; i < count; i++) { errchk(tqsl_getBand(i, &cp1, &cp2, &low, &high)); printf(" %-10.10s %-8.8s %-8d %d\n", cp1, cp2, low, high); } puts("\n===== DXCC =====\n Entity Name"); errchk(tqsl_getNumDXCCEntity(&count)); for (i = 0; i < count; i++) { errchk(tqsl_getDXCCEntity(i, &low, &cp1)); printf(" %-6d %s\n", low, cp1); } puts("\n===== PROP_MODES =====\n Mode Descrip"); errchk(tqsl_getNumPropagationMode(&count)); for (i = 0; i < count; i++) { errchk(tqsl_getPropagationMode(i, &cp1, &cp2)); printf(" %-6s %s\n", cp1, cp2); } puts("\n===== SATELLITES =====\n Sat Start Date End Date Descrip"); errchk(tqsl_getNumSatellite(&count)); for (i = 0; i < count; i++) { errchk(tqsl_getSatellite(i, &cp1, &cp2, &start, &end)); buf1[0] = buf2[0] = '\0'; tqsl_convertDateToText(&start, buf1, sizeof buf1); tqsl_convertDateToText(&end, buf2, sizeof buf2); printf(" %-6s %-10s %-10s %s\n", cp1, buf1, buf2, cp2); } return 0; } tqsl-2.7.2/src/doxygen/0000755000175000017500000000000014534122221014743 5ustar rmurphyrmurphytqsl-2.7.2/src/doxygen/html/0000755000175000017500000000000014534122221015707 5ustar rmurphyrmurphytqsl-2.7.2/src/doxygen/html/tqsllib_8h_source.html0000644000175000017500000077062414534122221022246 0ustar rmurphyrmurphy TrustedQSL Library API: tqsllib.h Source File
TrustedQSL Library API
tqsllib.h
Go to the documentation of this file.
1 /***************************************************************************
2  tqsllib.h - description
3  -------------------
4  begin : Mon May 20 2002
5  copyright : (C) 2002 by ARRL
6  author : Jon Bloom
7  email : jbloom@arrl.org
8  revision : $Id: tqsllib.h,v 1.14 2013/03/01 13:26:44 k1mu Exp $
9  ***************************************************************************/
10 
11 #ifndef TQSLLIB_H
12 #define TQSLLIB_H
13 
14 #if defined(_WIN32) && !defined(TQSL_NODLL)
15  #ifdef TQSLLIB_DEF
16  #define DLLEXPORT __declspec(dllexport)
17  #define DLLEXPORTDATA __declspec(dllexport)
18  #define CALLCONVENTION __stdcall
19  #else
20  #define DLLEXPORT __declspec(dllimport)
21  #define DLLEXPORTDATA __declspec(dllimport)
22  #define CALLCONVENTION __stdcall
23  #endif
24 #else
25  #define DLLEXPORT
26  #define DLLEXPORTDATA
27  #define CALLCONVENTION
28  #include <limits.h>
29 #endif
30 
31 #include "adif.h"
32 #include "cabrillo.h"
33 
38 #ifndef PATH_MAX // Should be set by <limits.h>
39 #define PATH_MAX 4096
40 #endif
41 
42 /* Sizes */
43 #define TQSL_MAX_PATH_LEN PATH_MAX
44 #define TQSL_PASSWORD_MAX 80
45 #define TQSL_NAME_ELEMENT_MAX 256
46 #define TQSL_CALLSIGN_MAX 20
47 #define TQSL_CRQ_NAME_MAX 60
48 #define TQSL_CRQ_ADDR_MAX 80
49 #define TQSL_CRQ_CITY_MAX 80
50 #define TQSL_CRQ_STATE_MAX 80
51 #define TQSL_CRQ_POSTAL_MAX 20
52 #define TQSL_CRQ_COUNTRY_MAX 80
53 #define TQSL_CRQ_EMAIL_MAX 180
54 #define TQSL_BAND_MAX 6
55 #define TQSL_MODE_MAX 16
56 #define TQSL_FREQ_MAX 20
57 #define TQSL_SATNAME_MAX 20
58 #define TQSL_PROPMODE_MAX 20
59 #define TQSL_STATE_MAX 30
60 #define TQSL_GRID_MAX 30
61 #define TQSL_CNTY_MAX 30
62 #define TQSL_COUNTRY_MAX 60
63 #define TQSL_ZONE_MAX 5
64 #define TQSL_IOTA_MAX 10
65 
66 #define TQSL_CERT_CB_USER 0
67 #define TQSL_CERT_CB_CA 1
68 #define TQSL_CERT_CB_ROOT 2
69 #define TQSL_CERT_CB_PKEY 3
70 #define TQSL_CERT_CB_CONFIG 4
71 #define TQSL_CERT_CB_CERT_TYPE(x) ((x) & 0xf)
72 #define TQSL_CERT_CB_MILESTONE 0
73 #define TQSL_CERT_CB_RESULT 0x10
74 #define TQSL_CERT_CB_CALL_TYPE(x) ((x) & TQSL_CERT_CB_RESULT)
75 #define TQSL_CERT_CB_PROMPT 0
76 #define TQSL_CERT_CB_DUPLICATE 0x100
77 #define TQSL_CERT_CB_ERROR 0x200
78 #define TQSL_CERT_CB_LOADED 0x300
79 #define TQSL_CERT_CB_RESULT_TYPE(x) ((x) & 0x0f00)
80 
81 typedef void * tQSL_Cert;
82 typedef void * tQSL_Location;
83 typedef char * tQSL_StationDataEnc;
84 
86 typedef struct {
87  int year;
88  int month;
89  int day;
90 } tQSL_Date;
91 
93 typedef struct {
94  int hour;
95  int minute;
96  int second;
97 } tQSL_Time;
98 
100 typedef struct tqsl_provider_st {
106 
108 typedef struct tqsl_cert_req_st {
125  char renew;
127 
129 typedef struct {
130  char callsign[TQSL_CALLSIGN_MAX+1];
131  char band[TQSL_BAND_MAX+1];
132  char mode[TQSL_MODE_MAX+1];
133  char submode[TQSL_MODE_MAX+1];
136  char freq[TQSL_FREQ_MAX+1];
137  char rxfreq[TQSL_FREQ_MAX+1];
138  char rxband[TQSL_BAND_MAX+1];
139  char propmode[TQSL_PROPMODE_MAX+1];
140  char satname[TQSL_SATNAME_MAX+1];
142  bool mode_set;
143  bool band_set;
144  bool date_set;
145  bool time_set;
146  char my_state[TQSL_STATE_MAX+1];
147  char my_gridsquare[TQSL_GRID_MAX+1];
148  char my_vucc_grids[TQSL_GRID_MAX+1];
149  char my_county[TQSL_CNTY_MAX+1];
150  char my_cnty_state[TQSL_STATE_MAX+1];
151  char my_country[TQSL_COUNTRY_MAX+1];
152  char my_cq_zone[TQSL_ZONE_MAX+1];
153  char my_itu_zone[TQSL_ZONE_MAX+1];
154  int my_dxcc;
155  char my_call[TQSL_CALLSIGN_MAX+1];
156 #ifdef USE_OWNER_CALLSIGN
157  char my_owner[TQSL_CALLSIGN_MAX+1];
158 #endif
159  char my_operator[TQSL_CALLSIGN_MAX+1];
160  char my_iota[TQSL_IOTA_MAX+1];
162 
164 DLLEXPORTDATA extern const char *tQSL_BaseDir;
166 DLLEXPORTDATA extern const char *tQSL_RsrcDir;
167 
168 #ifdef __cplusplus
169 extern "C" {
170 #endif
171 
177 
179 DLLEXPORTDATA extern int tQSL_Error;
187 DLLEXPORTDATA extern char tQSL_CustomError[256];
189 DLLEXPORTDATA extern int tQSL_Errno;
191 DLLEXPORTDATA extern char tQSL_ImportCall[256];
193 DLLEXPORTDATA extern long tQSL_ImportSerial;
195 DLLEXPORTDATA extern FILE* tQSL_DiagFile;
196 
202 
213 
218 
224 
232 DLLEXPORT int CALLCONVENTION tqsl_encodeBase64(const unsigned char *data, int datalen, char *output, int outputlen);
233 
242 DLLEXPORT int CALLCONVENTION tqsl_decodeBase64(const char *input, unsigned char *data, int *datalen);
243 
250 DLLEXPORT int CALLCONVENTION tqsl_initDate(tQSL_Date *date, const char *str);
251 
258 DLLEXPORT int CALLCONVENTION tqsl_initTime(tQSL_Time *time, const char *str);
259 
270 
276 DLLEXPORT int CALLCONVENTION tqsl_subtractDates(const tQSL_Date *a, const tQSL_Date *b, int *diff);
277 
282 DLLEXPORT char* CALLCONVENTION tqsl_convertDateToText(const tQSL_Date *date, char *buf, int bufsiz);
283 
289 
295 
301 
306 DLLEXPORT char* CALLCONVENTION tqsl_convertTimeToText(const tQSL_Time *time, char *buf, int bufsiz);
307 
310 DLLEXPORT int CALLCONVENTION tqsl_getVersion(int *major, int *minor);
311 
314 DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion(int *major, int *minor);
315 
344 #define TQSL_SELECT_CERT_WITHKEYS 1
345 #define TQSL_SELECT_CERT_EXPIRED 2
346 #define TQSL_SELECT_CERT_SUPERCEDED 4
347 
376  const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flag);
377 
389 DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates(tQSL_Cert **certlist, int *ncerts, const char *type);
390 
400  int idx);
401 
405 
409 
413 
417 
420 DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded(tQSL_Cert cert, char *buf, int bufsiz);
421 
424 DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded(const char *callsign, const char *type, const char *keybuf, const char *certbuf);
425 
429 
433 DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt(tQSL_Cert cert, char *serial, int serialsiz);
434 
439 
450 
491 
502 
512 
522 
532 
542 
552 
564 
576 
588 
600 
612 
624 
625 #define TQSL_PK_TYPE_ERR 0
626 #define TQSL_PK_TYPE_NONE 1
627 #define TQSL_PK_TYPE_UNENC 2
628 #define TQSL_PK_TYPE_ENC 3
629 
645 
646 
651 
658 
659 #define TQSL_CERT_STATUS_UNK 0
660 #define TQSL_CERT_STATUS_SUP 1
661 #define TQSL_CERT_STATUS_EXP 2
662 #define TQSL_CERT_STATUS_OK 3
663 #define TQSL_CERT_STATUS_INV 4
664 
680 
685 DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus(long serial, const char *status);
686 
687 /* int tqsl_checkCertificate(tQSL_Cert); */
688 
706 DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile(const char *file, int(*cb)(int type, const char *message, void *userdata), void *user);
707 
716 DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile(const char *file, long *serial);
717 
721 
727 
741  int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user);
742 
750 DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File(tQSL_Cert cert, const char *filename, const char *p12password);
751 
760 DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64(tQSL_Cert cert, char *base64, int b64len, const char *p12password);
761 
764 DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File(const char *filename, const char *p12password, const char *password,
765  int (*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type , const char *message, void *userdata), void *user);
766 
769 DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64(const char *base64, const char *p12password, const char *password,
770  int (*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type , const char *message, void *userdata), void *user);
771 
773 DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates(char ***calls, int *ncall, const char *filter);
774 
777 
780 
784 
807 DLLEXPORT int CALLCONVENTION tqsl_beginSigning(tQSL_Cert cert, char *password, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user);
808 
814 
820 
826 DLLEXPORT int CALLCONVENTION tqsl_signDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int *siglen);
827 
832 DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int siglen);
833 
841 DLLEXPORT int CALLCONVENTION tqsl_signQSORecord(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *rec, unsigned char *sig, int *siglen);
842 
848 
953 /* Location field input types */
954 
955 #define TQSL_LOCATION_FIELD_TEXT 1
956 #define TQSL_LOCATION_FIELD_DDLIST 2
957 #define TQSL_LOCATION_FIELD_LIST 3
958 #define TQSL_LOCATION_FIELD_BADZONE 4
959 
960 /* Location field data types */
961 #define TQSL_LOCATION_FIELD_CHAR 1
962 #define TQSL_LOCATION_FIELD_INT 2
963 
966 
972 
975 
979 
982 
988 
993 
996 
999 
1002 
1005 
1008 
1011 
1014 
1022 
1025 
1028 
1031 
1033 DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName(tQSL_Location loc, int idx, char *buf, int bufsiz);
1034 
1037 
1039 DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField(tQSL_Location locp, const char *name, char *namebuf, int bufsize);
1040 
1046 
1054 
1059 
1063 
1066 
1069 
1072 
1075 
1078 
1081 
1084 
1086 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel(tQSL_Location loc, int field_num, char *buf, int bufsiz);
1087 
1090 
1092 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI(tQSL_Location loc, int field_num, char *buf, int bufsiz);
1093 
1101 
1104 
1106 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel(tQSL_Location loc, int field_num, char *buf, int bufsiz);
1107 
1110 
1112 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI(tQSL_Location loc, int field_num, char *buf, int bufsiz);
1113 
1120 
1126 
1136 
1139 
1146 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData(tQSL_Location loc, int field_num, char *buf, int bufsiz);
1147 
1154 
1160 
1163 
1165 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem(tQSL_Location loc, int field_num, int item_idx, char *buf, int bufsiz);
1166 
1168 DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData(tQSL_Location loc, int field_num, const char *buf);
1169 
1173 
1179 
1185 
1188 
1191 
1193 DLLEXPORT int CALLCONVENTION tqsl_getLocationField(tQSL_Location locp, const char *field, char *buf, int bufsiz);
1194 
1196 DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel(tQSL_Location locp, const char *field, char *buf, int bufsiz);
1197 
1199 DLLEXPORT int CALLCONVENTION tqsl_setLocationField(tQSL_Location locp, const char *field, const char *buf);
1200 
1203 
1206 
1209 
1211 DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo(const char *callsign, const char *json);
1212 
1214 DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo(const char *callsign, char **buf);
1215 
1219 
1222 DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity(int index, int *number, const char **name);
1223 
1226 DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName(int number, const char **name);
1227 
1230 DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap(int number, const char **zonemap);
1231 
1235 
1239 
1242 DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted(int number, int *deleted);
1243 
1246 
1256 DLLEXPORT int CALLCONVENTION tqsl_getBand(int index, const char **name, const char **spectrum, int *low, int *high);
1257 
1260 
1268 DLLEXPORT int CALLCONVENTION tqsl_getMode(int index, const char **mode, const char **group);
1269 
1272 
1278 DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry(int index, const char **mode);
1279 
1282 
1290 DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode(int index, const char **name, const char **descrip);
1291 
1294 
1304 DLLEXPORT int CALLCONVENTION tqsl_getSatellite(int index, const char **name, const char **descrip,
1305  tQSL_Date *start, tQSL_Date *end);
1306 
1310 
1321 DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry(const char *contest, int field, int contest_type);
1322 
1334 DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry(const char *contest, int *fieldnum, int *contest_type);
1335 
1339 
1342 DLLEXPORT int CALLCONVENTION tqsl_setADIFMode(const char *adif_item, const char *mode);
1343 
1346 DLLEXPORT int CALLCONVENTION tqsl_getADIFMode(const char *adif_item, char *mode, int nmode);
1347 
1350 DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode(const char *adif_item, char *mode, char *submode, int nmode);
1351 
1362 
1373 DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItSTATION(tQSL_Location loc, int uid, int certuid);
1374 
1388  int stationuid);
1389 
1404  int stationuid, char *signdata, int sdlen);
1405 
1412 DLLEXPORT void CALLCONVENTION tqslTrace(const char *name, const char *format, ...);
1423 
1424 #ifdef _WIN32
1425 DLLEXPORT wchar_t* CALLCONVENTION utf8_to_wchar(const char* str);
1426 DLLEXPORT char* CALLCONVENTION wchar_to_utf8(const wchar_t* str, bool forceUTF8);
1427 DLLEXPORT void CALLCONVENTION free_wchar(wchar_t* ptr);
1428 #endif
1429 
1430 #ifdef __cplusplus
1431 }
1432 #endif
1433 
1434 /* Useful defines */
1435 #define TQSL_MAX_PW_LENGTH 32
1436 
1437 #endif /* TQSLLIB_H */
TQSL_ADIF_GET_FIELD_ERROR
Response values returned from tqsl_getADIFField()
Definition: adif.h:52
TQSL_CABRILLO_ERROR_TYPE
Cabrillo status values.
Definition: cabrillo.h:40
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress1(tQSL_Cert cert, char *str, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateAROName(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File(const char *filename, const char *p12password, const char *password, int(*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type, const char *message, void *userdata), void *user)
DLLEXPORT int CALLCONVENTION tqsl_deleteCertificate(tQSL_Cert cert)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCity(tQSL_Cert cert, char *str, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File(tQSL_Cert cert, const char *filename, const char *p12password)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestState(tQSL_Cert cert, char *str, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getSelectedCertificate(tQSL_Cert *cert, const tQSL_Cert **certlist, int idx)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganizationalUnit(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_isCertificateSuperceded(tQSL_Cert cert, int *status)
DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates(tQSL_Cert **certlist, int *ncerts, const char *type)
DLLEXPORT int CALLCONVENTION tqsl_getCertificatePrivateKeyType(tQSL_Cert cert)
DLLEXPORT int CALLCONVENTION tqsl_restoreCallsignCertificate(const char *callsign)
DLLEXPORT int CALLCONVENTION tqsl_createCertRequest(const char *filename, TQSL_CERT_REQ *req, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user)
DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded(const char *callsign, const char *type, const char *keybuf, const char *certbuf)
DLLEXPORT int CALLCONVENTION tqsl_selectCertificates(tQSL_Cert **certlist, int *ncerts, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flag)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialLength(tQSL_Cert cert)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotAfterDate(tQSL_Cert cert, tQSL_Date *date)
DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile(const char *file, long *serial)
DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64(const char *base64, const char *p12password, const char *password, int(*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type, const char *message, void *userdata), void *user)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerial(tQSL_Cert cert, long *serial)
DLLEXPORT int CALLCONVENTION tqsl_getNumProviders(int *n)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganization(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotBeforeDate(tQSL_Cert cert, tQSL_Date *date)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotAfterDate(tQSL_Cert cert, tQSL_Date *date)
DLLEXPORT int CALLCONVENTION tqsl_isCertificateExpired(tQSL_Cert cert, int *status)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateEmailAddress(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotBeforeDate(tQSL_Cert cert, tQSL_Date *date)
DLLEXPORT int CALLCONVENTION tqsl_getProvider(int idx, TQSL_PROVIDER *provider)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestPostalCode(tQSL_Cert cert, char *str, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateCallSign(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT void CALLCONVENTION tqsl_freeCertificateList(tQSL_Cert *list, int ncerts)
DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateStatus(long serial)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateKeyOnly(tQSL_Cert cert, int *keyonly)
DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64(tQSL_Cert cert, char *base64, int b64len, const char *p12password)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress2(tQSL_Cert cert, char *str, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuer(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateEncoded(tQSL_Cert cert, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateDXCCEntity(tQSL_Cert cert, int *dxcc)
DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile(const char *file, int(*cb)(int type, const char *message, void *userdata), void *user)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCountry(tQSL_Cert cert, char *str, int bufsiz)
DLLEXPORT void CALLCONVENTION tqsl_freeCertificate(tQSL_Cert cert)
DLLEXPORT void CALLCONVENTION tqsl_freeDeletedCertificateList(char **list, int nloc)
DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus(long serial, const char *status)
DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt(tQSL_Cert cert, char *serial, int serialsiz)
DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates(char ***calls, int *ncall, const char *filter)
DLLEXPORT int CALLCONVENTION tqsl_getADIFMode(const char *adif_item, char *mode, int nmode)
DLLEXPORT int CALLCONVENTION tqsl_initStationLocationCapture(tQSL_Location *locp)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldFlags(tQSL_Location loc, int field_num, int *flags)
DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData(tQSL_Location loc, int field_num, const char *buf)
DLLEXPORT int CALLCONVENTION tqsl_getNumSatellite(int *number)
DLLEXPORT int CALLCONVENTION tqsl_saveStationLocationCapture(tQSL_Location loc, int overwrite)
DLLEXPORT int CALLCONVENTION tqsl_getNumMode(int *number)
DLLEXPORT int CALLCONVENTION tqsl_getDXCCEndDate(int number, tQSL_Date *d)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocation(tQSL_Location *loc, const char *name)
DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIndex(tQSL_Location loc, int field_num, int dat)
DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocationCapturePages(tQSL_Location loc, int *npages)
DLLEXPORT int CALLCONVENTION tqsl_getStationDataEnc(tQSL_StationDataEnc *sdata)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize(tQSL_Location loc, int field_num, int *rval)
DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocations(tQSL_Location loc, int *nloc)
DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIntData(tQSL_Location loc, int field_num, int dat)
DLLEXPORT int CALLCONVENTION tqsl_setLocationField(tQSL_Location locp, const char *field, const char *buf)
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCONTACT(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataType(tQSL_Location loc, int field_num, int *type)
DLLEXPORT int CALLCONVENTION tqsl_freeStationDataEnc(tQSL_StationDataEnc sdata)
DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry(int index, const char **mode)
DLLEXPORT int CALLCONVENTION tqsl_endStationLocationCapture(tQSL_Location *locp)
DLLEXPORT int CALLCONVENTION tqsl_getPrevStationLocationCapturePage(tQSL_Location loc, int *page)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCapturePage(tQSL_Location loc, int *page)
DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCaptureName(tQSL_Location loc, const char *name)
DLLEXPORT int CALLCONVENTION tqsl_getNumADIFMode(int *number)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationErrors(tQSL_Location loc, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getDeletedStationLocations(char ***locp, int *nloc)
DLLEXPORT int CALLCONVENTION tqsl_getNextStationLocationCapturePage(tQSL_Location loc, int *page)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI(tQSL_Location loc, int field_num, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName(int number, const char **name)
DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCapturePage(tQSL_Location loc, int page)
DLLEXPORT int CALLCONVENTION tqsl_setLocationCallSign(tQSL_Location loc, const char *buf, int dxcc)
DLLEXPORT int CALLCONVENTION tqsl_hasNextStationLocationCapture(tQSL_Location loc, int *rval)
DLLEXPORT int CALLCONVENTION tqsl_getLocationField(tQSL_Location locp, const char *field, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel(tQSL_Location loc, int field_num, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity(int index, int *number, const char **name)
DLLEXPORT int CALLCONVENTION tqsl_getDXCCStartDate(int number, tQSL_Date *d)
DLLEXPORT int CALLCONVENTION tqsl_getNumLocationFieldListItems(tQSL_Location loc, int field_num, int *rval)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIntData(tQSL_Location loc, int field_num, int *dat)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem(tQSL_Location loc, int field_num, int item_idx, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getCurrentStationLocationCapturePage(tQSL_Location loc, int *page)
DLLEXPORT int CALLCONVENTION tqsl_prevStationLocationCapture(tQSL_Location loc)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCallSign(tQSL_Location loc, int idx, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getLocationStationDetails(tQSL_Location locp, char *buf, int buflen)
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItSTATION(tQSL_Location loc, int uid, int certuid)
DLLEXPORT int CALLCONVENTION tqsl_getMode(int index, const char **mode, const char **group)
DLLEXPORT int CALLCONVENTION tqsl_updateStationLocationCapture(tQSL_Location loc)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCaptureName(tQSL_Location loc, char *namebuf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getLocationQSODetails(tQSL_Location locp, char *buf, int buflen)
DLLEXPORT int CALLCONVENTION tqsl_getNumBand(int *number)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldInputType(tQSL_Location loc, int field_num, int *type)
DLLEXPORT int CALLCONVENTION tqsl_restoreStationLocation(const char *name)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData(tQSL_Location loc, int field_num, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_nextStationLocationCapture(tQSL_Location loc)
DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCertFlags(tQSL_Location loc, int flags)
DLLEXPORT int CALLCONVENTION tqsl_getBand(int index, const char **name, const char **spectrum, int *low, int *high)
DLLEXPORT int CALLCONVENTION tqsl_deleteStationLocation(const char *name)
DLLEXPORT int CALLCONVENTION tqsl_setADIFMode(const char *adif_item, const char *mode)
DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo(const char *callsign, char **buf)
DLLEXPORT int CALLCONVENTION tqsl_clearADIFModes()
DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry(const char *contest, int field, int contest_type)
DLLEXPORT int CALLCONVENTION tqsl_clearCabrilloMap()
DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField(tQSL_Location loc, int *numf)
DLLEXPORT int CALLCONVENTION tqsl_getNumDXCCEntity(int *number)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize(tQSL_Location loc, int field_num, int *rval)
DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode(const char *adif_item, char *mode, char *submode, int nmode)
DLLEXPORT int CALLCONVENTION tqsl_getLocationCallSign(tQSL_Location loc, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel(tQSL_Location locp, const char *field, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldChanged(tQSL_Location loc, int field_num, int *changed)
DLLEXPORT int CALLCONVENTION tqsl_mergeStationLocations(const char *locdata)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField(tQSL_Location locp, const char *name, char *namebuf, int bufsize)
DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap(int number, const char **zonemap)
DLLEXPORT int CALLCONVENTION tqsl_getSatellite(int index, const char **name, const char **descrip, tQSL_Date *start, tQSL_Date *end)
DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry(const char *contest, int *fieldnum, int *contest_type)
DLLEXPORT int CALLCONVENTION tqsl_getNumPropagationMode(int *number)
DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo(const char *callsign, const char *json)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLength(tQSL_Location loc, int field_num, int *rval)
DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode(int index, const char **name, const char **descrip)
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCONTACTData(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid, char *signdata, int sdlen)
DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted(int number, int *deleted)
DLLEXPORT int CALLCONVENTION tqsl_hasPrevStationLocationCapture(tQSL_Location loc, int *rval)
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName(tQSL_Location loc, int idx, char *buf, int bufsiz)
DLLEXPORT void CALLCONVENTION tqsl_freeDeletedLocationList(char **list, int nloc)
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCERT(tQSL_Cert cert, int uid)
DLLEXPORT int CALLCONVENTION tqsl_getLocationDXCCEntity(tQSL_Location loc, int *dxcc)
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIndex(tQSL_Location loc, int field_num, int *dat)
DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int siglen)
DLLEXPORT int CALLCONVENTION tqsl_getMaxSignatureSize(tQSL_Cert cert, int *sigsize)
DLLEXPORT int CALLCONVENTION tqsl_signDataBlock(tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int *siglen)
DLLEXPORT int CALLCONVENTION tqsl_beginSigning(tQSL_Cert cert, char *password, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user)
DLLEXPORT int CALLCONVENTION tqsl_endSigning(tQSL_Cert cert)
DLLEXPORT int CALLCONVENTION tqsl_checkSigningStatus(tQSL_Cert cert)
DLLEXPORT int CALLCONVENTION tqsl_signQSORecord(tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *rec, unsigned char *sig, int *siglen)
DLLEXPORTDATA TQSL_ADIF_GET_FIELD_ERROR tQSL_ADIF_Error
The ADIF error code.
DLLEXPORTDATA FILE * tQSL_DiagFile
Diagnostic log file.
DLLEXPORT int CALLCONVENTION tqsl_decodeBase64(const char *input, unsigned char *data, int *datalen)
DLLEXPORT int CALLCONVENTION tqsl_getVersion(int *major, int *minor)
DLLEXPORT int CALLCONVENTION tqsl_compareDates(const tQSL_Date *a, const tQSL_Date *b)
DLLEXPORT int CALLCONVENTION tqsl_init()
DLLEXPORTDATA char tQSL_CustomError[256]
Custom error message string.
DLLEXPORT const char *CALLCONVENTION tqsl_getErrorString()
DLLEXPORT int CALLCONVENTION tqsl_isDateValid(const tQSL_Date *d)
DLLEXPORT int CALLCONVENTION tqsl_subtractDates(const tQSL_Date *a, const tQSL_Date *b, int *diff)
DLLEXPORT int CALLCONVENTION tqsl_isTimeValid(const tQSL_Time *t)
DLLEXPORT int CALLCONVENTION tqsl_isDateNull(const tQSL_Date *d)
DLLEXPORT int CALLCONVENTION tqsl_setDirectory(const char *dir)
DLLEXPORT int CALLCONVENTION tqsl_encodeBase64(const unsigned char *data, int datalen, char *output, int outputlen)
DLLEXPORT int CALLCONVENTION tqsl_initTime(tQSL_Time *time, const char *str)
DLLEXPORT char *CALLCONVENTION tqsl_convertDateToText(const tQSL_Date *date, char *buf, int bufsiz)
DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion(int *major, int *minor)
DLLEXPORT char *CALLCONVENTION tqsl_convertTimeToText(const tQSL_Time *time, char *buf, int bufsiz)
DLLEXPORTDATA long tQSL_ImportSerial
Serial number of recent certificate import.
DLLEXPORTDATA int tQSL_Error
Error code from most recent tQSL library call.
DLLEXPORTDATA TQSL_CABRILLO_ERROR_TYPE tQSL_Cabrillo_Error
The ADIF error code.
DLLEXPORT int CALLCONVENTION tqsl_initDate(tQSL_Date *date, const char *str)
DLLEXPORT const char *CALLCONVENTION tqsl_getErrorString_v(int err)
DLLEXPORTDATA char tQSL_ErrorFile[TQSL_MAX_PATH_LEN]
File name of file giving error. (May be empty.)
DLLEXPORTDATA int tQSL_Errno
System errno - stored when tQSL_Error == TQSL_SYSTEM_ERROR.
DLLEXPORTDATA char tQSL_ImportCall[256]
Callsign used in import - used for missing public key error.
Definition: tqsllib.h:129
bool time_set
QSO specifies a time.
Definition: tqsllib.h:145
bool date_set
QSO specifies a date.
Definition: tqsllib.h:144
bool mode_set
QSO specifies a mode.
Definition: tqsllib.h:142
tQSL_Date date
QSO date.
Definition: tqsllib.h:134
bool callsign_set
QSO specifies a call worked.
Definition: tqsllib.h:141
bool band_set
QSO specifies a band or frequency.
Definition: tqsllib.h:143
int my_dxcc
QSO specifies MY_DXCC.
Definition: tqsllib.h:154
tQSL_Time time
QSO time.
Definition: tqsllib.h:135
Definition: tqsllib.h:86
int month
Numeric month.
Definition: tqsllib.h:88
int year
Numeric year.
Definition: tqsllib.h:87
int day
Numeric day.
Definition: tqsllib.h:89
Definition: tqsllib.h:93
int second
Time seconds field.
Definition: tqsllib.h:96
int hour
Time hour field.
Definition: tqsllib.h:94
int minute
Time minute field.
Definition: tqsllib.h:95
Definition: tqsllib.h:108
char password[TQSL_PASSWORD_MAX+1]
Password.
Definition: tqsllib.h:123
char renew
Rewewal reference.
Definition: tqsllib.h:125
char address2[TQSL_CRQ_ADDR_MAX+1]
Address 2.
Definition: tqsllib.h:114
tQSL_Date qsoNotAfter
QSOs not after date.
Definition: tqsllib.h:122
tQSL_Cert signer
Signing cert.
Definition: tqsllib.h:124
char callSign[TQSL_CALLSIGN_MAX+1]
Callsign.
Definition: tqsllib.h:111
char state[TQSL_CRQ_STATE_MAX+1]
State.
Definition: tqsllib.h:116
char postalCode[TQSL_CRQ_POSTAL_MAX+1]
Postal Code.
Definition: tqsllib.h:117
char providerUnit[TQSL_NAME_ELEMENT_MAX+1]
Provider unit.
Definition: tqsllib.h:110
tQSL_Date qsoNotBefore
QSOs not before date.
Definition: tqsllib.h:121
char name[TQSL_CRQ_NAME_MAX+1]
Name.
Definition: tqsllib.h:112
char address1[TQSL_CRQ_ADDR_MAX+1]
Address 1.
Definition: tqsllib.h:113
int dxccEntity
DXCC Entity code.
Definition: tqsllib.h:120
char city[TQSL_CRQ_CITY_MAX+1]
City.
Definition: tqsllib.h:115
char country[TQSL_CRQ_COUNTRY_MAX+1]
Country.
Definition: tqsllib.h:118
char emailAddress[TQSL_CRQ_EMAIL_MAX+1]
e-mail
Definition: tqsllib.h:119
char providerName[TQSL_NAME_ELEMENT_MAX+1]
< Cert request data
Definition: tqsllib.h:109
Definition: tqsllib.h:100
char emailAddress[TQSL_NAME_ELEMENT_MAX+1]
Provider e-mail.
Definition: tqsllib.h:103
char url[TQSL_NAME_ELEMENT_MAX+1]
Provider URL.
Definition: tqsllib.h:104
char organizationName[TQSL_NAME_ELEMENT_MAX+1]
Provider name.
Definition: tqsllib.h:101
char organizationalUnitName[TQSL_NAME_ELEMENT_MAX+1]
Provider unit.
Definition: tqsllib.h:102
#define CALLCONVENTION
Symbol exports - Windows only.
Definition: tqsllib.h:27
void * tQSL_Location
Opaque location type.
Definition: tqsllib.h:82
#define TQSL_ZONE_MAX
Max length of a zone number.
Definition: tqsllib.h:63
#define TQSL_MODE_MAX
Max length of a mode name.
Definition: tqsllib.h:55
#define TQSL_GRID_MAX
Max length of a grid set.
Definition: tqsllib.h:60
#define TQSL_CRQ_POSTAL_MAX
Max length of request zip.
Definition: tqsllib.h:51
DLLEXPORT int CALLCONVENTION tqsl_openDiagFile(const char *file)
#define TQSL_COUNTRY_MAX
Max length of a country name.
Definition: tqsllib.h:62
DLLEXPORT void CALLCONVENTION tqslTrace(const char *name, const char *format,...)
#define TQSL_CRQ_STATE_MAX
Max length of request state.
Definition: tqsllib.h:50
#define TQSL_CRQ_COUNTRY_MAX
Max length of req entity.
Definition: tqsllib.h:52
DLLEXPORT void CALLCONVENTION tqsl_closeDiagFile(void)
#define TQSL_IOTA_MAX
Max length of a IOTA identifier.
Definition: tqsllib.h:64
#define TQSL_MAX_PATH_LEN
Max length of a FS path.
Definition: tqsllib.h:43
#define DLLEXPORTDATA
Symbol exports - Windows only.
Definition: tqsllib.h:26
#define TQSL_PASSWORD_MAX
Max password length.
Definition: tqsllib.h:44
DLLEXPORTDATA const char * tQSL_BaseDir
Base directory for tQSL library working files.
#define DLLEXPORT
Symbol exports - Windows only.
Definition: tqsllib.h:25
DLLEXPORT int CALLCONVENTION tqsl_diagFileOpen(void)
struct tqsl_provider_st TQSL_PROVIDER
#define TQSL_PROPMODE_MAX
Max length of a prop mode.
Definition: tqsllib.h:58
char * tQSL_StationDataEnc
Opaque station data type.
Definition: tqsllib.h:83
#define TQSL_NAME_ELEMENT_MAX
Max Org name length.
Definition: tqsllib.h:45
void * tQSL_Cert
Opaque certificate type.
Definition: tqsllib.h:81
#define TQSL_STATE_MAX
Max length of a state name.
Definition: tqsllib.h:59
#define TQSL_CALLSIGN_MAX
Max callsign length.
Definition: tqsllib.h:46
#define TQSL_CNTY_MAX
Max length of a county name.
Definition: tqsllib.h:61
#define TQSL_CRQ_EMAIL_MAX
Max length of req email.
Definition: tqsllib.h:53
#define TQSL_SATNAME_MAX
Max length of a sat name.
Definition: tqsllib.h:57
DLLEXPORTDATA const char * tQSL_RsrcDir
Directory for resources bundled with tqsl executable.
struct tqsl_cert_req_st TQSL_CERT_REQ
#define TQSL_BAND_MAX
Max length of a band name.
Definition: tqsllib.h:54
#define TQSL_FREQ_MAX
Max length of a frequency.
Definition: tqsllib.h:56
#define TQSL_CRQ_NAME_MAX
Max length of request name.
Definition: tqsllib.h:47
#define TQSL_CRQ_CITY_MAX
Max length of request city.
Definition: tqsllib.h:49
#define TQSL_CRQ_ADDR_MAX
Max length of request addr.
Definition: tqsllib.h:48
tqsl-2.7.2/src/doxygen/html/tqsllib_8h.html0000644000175000017500000047067614534122221020672 0ustar rmurphyrmurphy TrustedQSL Library API: tqsllib.h File Reference
TrustedQSL Library API
tqsllib.h File Reference
#include <limits.h>
#include "adif.h"
#include "cabrillo.h"

Go to the source code of this file.

Classes

struct  tQSL_Date
 
struct  tQSL_Time
 
struct  tqsl_provider_st
 
struct  tqsl_cert_req_st
 
struct  TQSL_QSO_RECORD
 

Macros

#define DLLEXPORT
 Symbol exports - Windows only.
 
#define DLLEXPORTDATA
 Symbol exports - Windows only.
 
#define CALLCONVENTION
 Symbol exports - Windows only.
 
#define PATH_MAX   4096
 
#define TQSL_MAX_PATH_LEN   PATH_MAX
 Max length of a FS path.
 
#define TQSL_PASSWORD_MAX   80
 Max password length.
 
#define TQSL_NAME_ELEMENT_MAX   256
 Max Org name length.
 
#define TQSL_CALLSIGN_MAX   20
 Max callsign length.
 
#define TQSL_CRQ_NAME_MAX   60
 Max length of request name.
 
#define TQSL_CRQ_ADDR_MAX   80
 Max length of request addr.
 
#define TQSL_CRQ_CITY_MAX   80
 Max length of request city.
 
#define TQSL_CRQ_STATE_MAX   80
 Max length of request state.
 
#define TQSL_CRQ_POSTAL_MAX   20
 Max length of request zip.
 
#define TQSL_CRQ_COUNTRY_MAX   80
 Max length of req entity.
 
#define TQSL_CRQ_EMAIL_MAX   180
 Max length of req email.
 
#define TQSL_BAND_MAX   6
 Max length of a band name.
 
#define TQSL_MODE_MAX   16
 Max length of a mode name.
 
#define TQSL_FREQ_MAX   20
 Max length of a frequency.
 
#define TQSL_SATNAME_MAX   20
 Max length of a sat name.
 
#define TQSL_PROPMODE_MAX   20
 Max length of a prop mode.
 
#define TQSL_STATE_MAX   30
 Max length of a state name.
 
#define TQSL_GRID_MAX   30
 Max length of a grid set.
 
#define TQSL_CNTY_MAX   30
 Max length of a county name.
 
#define TQSL_COUNTRY_MAX   60
 Max length of a country name.
 
#define TQSL_ZONE_MAX   5
 Max length of a zone number.
 
#define TQSL_IOTA_MAX   10
 Max length of a IOTA identifier.
 
#define TQSL_CERT_CB_USER   0
 Callback is for user cert.
 
#define TQSL_CERT_CB_CA   1
 Callback is for CA cert.
 
#define TQSL_CERT_CB_ROOT   2
 Callback is for root cert.
 
#define TQSL_CERT_CB_PKEY   3
 Callback is for private key.
 
#define TQSL_CERT_CB_CONFIG   4
 Callback for config file.
 
#define TQSL_CERT_CB_CERT_TYPE(x)   ((x) & 0xf)
 Type of the cert.
 
#define TQSL_CERT_CB_MILESTONE   0
 New certificate.
 
#define TQSL_CERT_CB_RESULT   0x10
 Cert import result.
 
#define TQSL_CERT_CB_CALL_TYPE(x)   ((x) & TQSL_CERT_CB_RESULT)
 Callback type.
 
#define TQSL_CERT_CB_PROMPT   0
 Callback prompt.
 
#define TQSL_CERT_CB_DUPLICATE   0x100
 Dupe cert callback.
 
#define TQSL_CERT_CB_ERROR   0x200
 Error import callback.
 
#define TQSL_CERT_CB_LOADED   0x300
 Cert loaded callback.
 
#define TQSL_CERT_CB_RESULT_TYPE(x)   ((x) & 0x0f00)
 Result type mask.
 
#define TQSL_SELECT_CERT_WITHKEYS   1
 Private keys only (no cert)
 
#define TQSL_SELECT_CERT_EXPIRED   2
 Include expired certs.
 
#define TQSL_SELECT_CERT_SUPERCEDED   4
 Include superseded certs.
 
#define TQSL_PK_TYPE_ERR   0
 Error retrieving private key.
 
#define TQSL_PK_TYPE_NONE   1
 No private key.
 
#define TQSL_PK_TYPE_UNENC   2
 Private key is not encrypted.
 
#define TQSL_PK_TYPE_ENC   3
 Private key is encrypted.
 
#define TQSL_CERT_STATUS_UNK   0
 Status is unknown.
 
#define TQSL_CERT_STATUS_SUP   1
 Certificate is superceded.
 
#define TQSL_CERT_STATUS_EXP   2
 Certificate is expired.
 
#define TQSL_CERT_STATUS_OK   3
 Certificate is valid.
 
#define TQSL_CERT_STATUS_INV   4
 Invalid serial number.
 
#define TQSL_LOCATION_FIELD_TEXT   1
 Text type input field.
 
#define TQSL_LOCATION_FIELD_DDLIST   2
 Dropdown list input field.
 
#define TQSL_LOCATION_FIELD_LIST   3
 List type input field.
 
#define TQSL_LOCATION_FIELD_BADZONE   4
 Used to return zone selection errors.
 
#define TQSL_LOCATION_FIELD_CHAR   1
 Character field.
 
#define TQSL_LOCATION_FIELD_INT   2
 Integer field.
 
#define TQSL_MAX_PW_LENGTH   32
 Password buffer length.
 

Typedefs

typedef void * tQSL_Cert
 Opaque certificate type.
 
typedef void * tQSL_Location
 Opaque location type.
 
typedef char * tQSL_StationDataEnc
 Opaque station data type.
 
typedef struct tqsl_provider_st TQSL_PROVIDER
 
typedef struct tqsl_cert_req_st TQSL_CERT_REQ
 

Functions

DLLEXPORT int CALLCONVENTION tqsl_init ()
 
DLLEXPORT int CALLCONVENTION tqsl_setDirectory (const char *dir)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getErrorString ()
 
DLLEXPORT const char *CALLCONVENTION tqsl_getErrorString_v (int err)
 
DLLEXPORT int CALLCONVENTION tqsl_encodeBase64 (const unsigned char *data, int datalen, char *output, int outputlen)
 
DLLEXPORT int CALLCONVENTION tqsl_decodeBase64 (const char *input, unsigned char *data, int *datalen)
 
DLLEXPORT int CALLCONVENTION tqsl_initDate (tQSL_Date *date, const char *str)
 
DLLEXPORT int CALLCONVENTION tqsl_initTime (tQSL_Time *time, const char *str)
 
DLLEXPORT int CALLCONVENTION tqsl_compareDates (const tQSL_Date *a, const tQSL_Date *b)
 
DLLEXPORT int CALLCONVENTION tqsl_subtractDates (const tQSL_Date *a, const tQSL_Date *b, int *diff)
 
DLLEXPORT char *CALLCONVENTION tqsl_convertDateToText (const tQSL_Date *date, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_isDateValid (const tQSL_Date *d)
 
DLLEXPORT int CALLCONVENTION tqsl_isDateNull (const tQSL_Date *d)
 
DLLEXPORT int CALLCONVENTION tqsl_isTimeValid (const tQSL_Time *t)
 
DLLEXPORT char *CALLCONVENTION tqsl_convertTimeToText (const tQSL_Time *time, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getVersion (int *major, int *minor)
 
DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion (int *major, int *minor)
 
DLLEXPORT int CALLCONVENTION tqsl_selectCertificates (tQSL_Cert **certlist, int *ncerts, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flag)
 
DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates (tQSL_Cert **certlist, int *ncerts, const char *type)
 
DLLEXPORT int CALLCONVENTION tqsl_getSelectedCertificate (tQSL_Cert *cert, const tQSL_Cert **certlist, int idx)
 
DLLEXPORT int CALLCONVENTION tqsl_isCertificateExpired (tQSL_Cert cert, int *status)
 
DLLEXPORT int CALLCONVENTION tqsl_isCertificateSuperceded (tQSL_Cert cert, int *status)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateKeyOnly (tQSL_Cert cert, int *keyonly)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateEncoded (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded (const char *callsign, const char *type, const char *keybuf, const char *certbuf)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerial (tQSL_Cert cert, long *serial)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt (tQSL_Cert cert, char *serial, int serialsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialLength (tQSL_Cert cert)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuer (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganization (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganizationalUnit (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateCallSign (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateAROName (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateEmailAddress (tQSL_Cert cert, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotBeforeDate (tQSL_Cert cert, tQSL_Date *date)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotAfterDate (tQSL_Cert cert, tQSL_Date *date)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotBeforeDate (tQSL_Cert cert, tQSL_Date *date)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotAfterDate (tQSL_Cert cert, tQSL_Date *date)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateDXCCEntity (tQSL_Cert cert, int *dxcc)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress1 (tQSL_Cert cert, char *str, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress2 (tQSL_Cert cert, char *str, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCity (tQSL_Cert cert, char *str, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestState (tQSL_Cert cert, char *str, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestPostalCode (tQSL_Cert cert, char *str, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCountry (tQSL_Cert cert, char *str, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificatePrivateKeyType (tQSL_Cert cert)
 
DLLEXPORT void CALLCONVENTION tqsl_freeCertificate (tQSL_Cert cert)
 
DLLEXPORT void CALLCONVENTION tqsl_freeCertificateList (tQSL_Cert *list, int ncerts)
 
DLLEXPORT int CALLCONVENTION tqsl_getCertificateStatus (long serial)
 
DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus (long serial, const char *status)
 
DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile (const char *file, int(*cb)(int type, const char *message, void *userdata), void *user)
 
DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile (const char *file, long *serial)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumProviders (int *n)
 
DLLEXPORT int CALLCONVENTION tqsl_getProvider (int idx, TQSL_PROVIDER *provider)
 
DLLEXPORT int CALLCONVENTION tqsl_createCertRequest (const char *filename, TQSL_CERT_REQ *req, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user)
 
DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File (tQSL_Cert cert, const char *filename, const char *p12password)
 
DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64 (tQSL_Cert cert, char *base64, int b64len, const char *p12password)
 
DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File (const char *filename, const char *p12password, const char *password, int(*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type, const char *message, void *userdata), void *user)
 
DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64 (const char *base64, const char *p12password, const char *password, int(*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type, const char *message, void *userdata), void *user)
 
DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates (char ***calls, int *ncall, const char *filter)
 
DLLEXPORT void CALLCONVENTION tqsl_freeDeletedCertificateList (char **list, int nloc)
 
DLLEXPORT int CALLCONVENTION tqsl_restoreCallsignCertificate (const char *callsign)
 
DLLEXPORT int CALLCONVENTION tqsl_deleteCertificate (tQSL_Cert cert)
 
DLLEXPORT int CALLCONVENTION tqsl_beginSigning (tQSL_Cert cert, char *password, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user)
 
DLLEXPORT int CALLCONVENTION tqsl_checkSigningStatus (tQSL_Cert cert)
 
DLLEXPORT int CALLCONVENTION tqsl_getMaxSignatureSize (tQSL_Cert cert, int *sigsize)
 
DLLEXPORT int CALLCONVENTION tqsl_signDataBlock (tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int *siglen)
 
DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock (tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int siglen)
 
DLLEXPORT int CALLCONVENTION tqsl_signQSORecord (tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *rec, unsigned char *sig, int *siglen)
 
DLLEXPORT int CALLCONVENTION tqsl_endSigning (tQSL_Cert cert)
 
DLLEXPORT int CALLCONVENTION tqsl_initStationLocationCapture (tQSL_Location *locp)
 
DLLEXPORT int CALLCONVENTION tqsl_endStationLocationCapture (tQSL_Location *locp)
 
DLLEXPORT int CALLCONVENTION tqsl_updateStationLocationCapture (tQSL_Location loc)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocationCapturePages (tQSL_Location loc, int *npages)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCapturePage (tQSL_Location loc, int *page)
 
DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCapturePage (tQSL_Location loc, int page)
 
DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCertFlags (tQSL_Location loc, int flags)
 
DLLEXPORT int CALLCONVENTION tqsl_nextStationLocationCapture (tQSL_Location loc)
 
DLLEXPORT int CALLCONVENTION tqsl_getNextStationLocationCapturePage (tQSL_Location loc, int *page)
 
DLLEXPORT int CALLCONVENTION tqsl_prevStationLocationCapture (tQSL_Location loc)
 
DLLEXPORT int CALLCONVENTION tqsl_getPrevStationLocationCapturePage (tQSL_Location loc, int *page)
 
DLLEXPORT int CALLCONVENTION tqsl_getCurrentStationLocationCapturePage (tQSL_Location loc, int *page)
 
DLLEXPORT int CALLCONVENTION tqsl_hasNextStationLocationCapture (tQSL_Location loc, int *rval)
 
DLLEXPORT int CALLCONVENTION tqsl_hasPrevStationLocationCapture (tQSL_Location loc, int *rval)
 
DLLEXPORT int CALLCONVENTION tqsl_saveStationLocationCapture (tQSL_Location loc, int overwrite)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCaptureName (tQSL_Location loc, char *namebuf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCaptureName (tQSL_Location loc, const char *name)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocations (tQSL_Location loc, int *nloc)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName (tQSL_Location loc, int idx, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCallSign (tQSL_Location loc, int idx, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField (tQSL_Location locp, const char *name, char *namebuf, int bufsize)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocation (tQSL_Location *loc, const char *name)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationLocationErrors (tQSL_Location loc, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getStationDataEnc (tQSL_StationDataEnc *sdata)
 
DLLEXPORT int CALLCONVENTION tqsl_freeStationDataEnc (tQSL_StationDataEnc sdata)
 
DLLEXPORT int CALLCONVENTION tqsl_mergeStationLocations (const char *locdata)
 
DLLEXPORT int CALLCONVENTION tqsl_deleteStationLocation (const char *name)
 
DLLEXPORT int CALLCONVENTION tqsl_restoreStationLocation (const char *name)
 
DLLEXPORT int CALLCONVENTION tqsl_getDeletedStationLocations (char ***locp, int *nloc)
 
DLLEXPORT void CALLCONVENTION tqsl_freeDeletedLocationList (char **list, int nloc)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField (tQSL_Location loc, int *numf)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize (tQSL_Location loc, int field_num, int *rval)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel (tQSL_Location loc, int field_num, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize (tQSL_Location loc, int field_num, int *rval)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI (tQSL_Location loc, int field_num, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldInputType (tQSL_Location loc, int field_num, int *type)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataType (tQSL_Location loc, int field_num, int *type)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldFlags (tQSL_Location loc, int field_num, int *flags)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLength (tQSL_Location loc, int field_num, int *rval)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData (tQSL_Location loc, int field_num, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIntData (tQSL_Location loc, int field_num, int *dat)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIndex (tQSL_Location loc, int field_num, int *dat)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumLocationFieldListItems (tQSL_Location loc, int field_num, int *rval)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem (tQSL_Location loc, int field_num, int item_idx, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData (tQSL_Location loc, int field_num, const char *buf)
 
DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIntData (tQSL_Location loc, int field_num, int dat)
 
DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIndex (tQSL_Location loc, int field_num, int dat)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldChanged (tQSL_Location loc, int field_num, int *changed)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationCallSign (tQSL_Location loc, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_setLocationCallSign (tQSL_Location loc, const char *buf, int dxcc)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationField (tQSL_Location locp, const char *field, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel (tQSL_Location locp, const char *field, char *buf, int bufsiz)
 
DLLEXPORT int CALLCONVENTION tqsl_setLocationField (tQSL_Location locp, const char *field, const char *buf)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationDXCCEntity (tQSL_Location loc, int *dxcc)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationQSODetails (tQSL_Location locp, char *buf, int buflen)
 
DLLEXPORT int CALLCONVENTION tqsl_getLocationStationDetails (tQSL_Location locp, char *buf, int buflen)
 
DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo (const char *callsign, const char *json)
 
DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo (const char *callsign, char **buf)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumDXCCEntity (int *number)
 
DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity (int index, int *number, const char **name)
 
DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName (int number, const char **name)
 
DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap (int number, const char **zonemap)
 
DLLEXPORT int CALLCONVENTION tqsl_getDXCCStartDate (int number, tQSL_Date *d)
 
DLLEXPORT int CALLCONVENTION tqsl_getDXCCEndDate (int number, tQSL_Date *d)
 
DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted (int number, int *deleted)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumBand (int *number)
 
DLLEXPORT int CALLCONVENTION tqsl_getBand (int index, const char **name, const char **spectrum, int *low, int *high)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumMode (int *number)
 
DLLEXPORT int CALLCONVENTION tqsl_getMode (int index, const char **mode, const char **group)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumADIFMode (int *number)
 
DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry (int index, const char **mode)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumPropagationMode (int *number)
 
DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode (int index, const char **name, const char **descrip)
 
DLLEXPORT int CALLCONVENTION tqsl_getNumSatellite (int *number)
 
DLLEXPORT int CALLCONVENTION tqsl_getSatellite (int index, const char **name, const char **descrip, tQSL_Date *start, tQSL_Date *end)
 
DLLEXPORT int CALLCONVENTION tqsl_clearCabrilloMap ()
 
DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry (const char *contest, int field, int contest_type)
 
DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry (const char *contest, int *fieldnum, int *contest_type)
 
DLLEXPORT int CALLCONVENTION tqsl_clearADIFModes ()
 
DLLEXPORT int CALLCONVENTION tqsl_setADIFMode (const char *adif_item, const char *mode)
 
DLLEXPORT int CALLCONVENTION tqsl_getADIFMode (const char *adif_item, char *mode, int nmode)
 
DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode (const char *adif_item, char *mode, char *submode, int nmode)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCERT (tQSL_Cert cert, int uid)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItSTATION (tQSL_Location loc, int uid, int certuid)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCONTACT (tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCONTACTData (tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid, char *signdata, int sdlen)
 
DLLEXPORT void CALLCONVENTION tqslTrace (const char *name, const char *format,...)
 
DLLEXPORT void CALLCONVENTION tqsl_closeDiagFile (void)
 
DLLEXPORT int CALLCONVENTION tqsl_diagFileOpen (void)
 
DLLEXPORT int CALLCONVENTION tqsl_openDiagFile (const char *file)
 

Variables

DLLEXPORTDATA const char * tQSL_BaseDir
 Base directory for tQSL library working files.
 
DLLEXPORTDATA const char * tQSL_RsrcDir
 Directory for resources bundled with tqsl executable.
 
DLLEXPORTDATA int tQSL_Error
 Error code from most recent tQSL library call. More...
 
DLLEXPORTDATA TQSL_ADIF_GET_FIELD_ERROR tQSL_ADIF_Error
 The ADIF error code.
 
DLLEXPORTDATA TQSL_CABRILLO_ERROR_TYPE tQSL_Cabrillo_Error
 The ADIF error code.
 
DLLEXPORTDATA char tQSL_ErrorFile [TQSL_MAX_PATH_LEN]
 File name of file giving error. (May be empty.)
 
DLLEXPORTDATA char tQSL_CustomError [256]
 Custom error message string.
 
DLLEXPORTDATA int tQSL_Errno
 System errno - stored when tQSL_Error == TQSL_SYSTEM_ERROR.
 
DLLEXPORTDATA char tQSL_ImportCall [256]
 Callsign used in import - used for missing public key error.
 
DLLEXPORTDATA long tQSL_ImportSerial
 Serial number of recent certificate import.
 
DLLEXPORTDATA FILE * tQSL_DiagFile
 Diagnostic log file.
 

Detailed Description

tQSL library functions.

Typedef Documentation

◆ TQSL_CERT_REQ

Certificate request data

◆ TQSL_PROVIDER

Certificate provider data

Function Documentation

◆ tqsl_closeDiagFile()

DLLEXPORT void CALLCONVENTION tqsl_closeDiagFile ( void  )

Close the diagnostic trace file (if it is open)

◆ tqsl_diagFileOpen()

DLLEXPORT int CALLCONVENTION tqsl_diagFileOpen ( void  )

Close the diagnostic trace file (if it is open)

◆ tqsl_openDiagFile()

DLLEXPORT int CALLCONVENTION tqsl_openDiagFile ( const char *  file)

Returns true if the log file is open

◆ tqslTrace()

DLLEXPORT void CALLCONVENTION tqslTrace ( const char *  name,
const char *  format,
  ... 
)

Output to a diagnostic trace file (if one is opened.

  • name is the name of the function being executed
tqsl-2.7.2/src/doxygen/html/tqsllib.css0000644000175000017500000000211614534122221020073 0ustar rmurphyrmurphyBODY { font-family: Helvetica,Arial,sans-serif; font-size: small } H1 { text-align: center; font-size: x-large } H2 { font-size: large } CODE { font-size: medium } A.qindex {} A.qindexRef {} A.el { text-decoration: none; font-weight: bold; } A.elRef { font-weight: bold } A.code { text-decoration: none; font-weight: normal; color: #4444ee } A.codeRef { font-weight: normal; color: #4444ee } A:link { color: #0000ff } A:visited { color: #0066cc } DL.el { margin-left: -1cm } DIV.fragment { width: 100%; border: none; background-color: #eeeeee } DIV.ah { background-color: black; margin-bottom: 3; margin-top: 3 } TD.md { background-color: #f2f2ff } DIV.groupHeader { margin-left: 16; margin-top: 12; margin-bottom: 6; font-weight: bold } DIV.groupText { margin-left: 16; font-style: italic; font-size: smaller } FONT.keyword { color: #008000 } FONT.keywordtype { color: #604020 } FONT.keywordflow { color: #e08000 } FONT.comment { color: #800000 } FONT.preprocessor { color: #806020 } FONT.stringliteral { color: #002080 } FONT.charliteral { color: #008080 } TD { font-size: small } tqsl-2.7.2/src/doxygen/html/tqsllib-doc_8h_source.html0000644000175000017500000000672314534122221023001 0ustar rmurphyrmurphy TrustedQSL Library API: tqsllib-doc.h Source File
TrustedQSL Library API
tqsllib-doc.h
1 /***************************************************************************
2  tqsllib-doc.h - description
3  -------------------
4  begin : Tue Jun 4 2002
5  copyright : (C) 2002 by ARRL
6  author : Jon Bloom
7  email : jbloom@arrl.org
8  revision : $Id$
9  ***************************************************************************/
10 
tqsl-2.7.2/src/doxygen/html/tqslerrno_8h_source.html0000644000175000017500000003201114534122221022602 0ustar rmurphyrmurphy TrustedQSL Library API: tqslerrno.h Source File
TrustedQSL Library API
tqslerrno.h
Go to the documentation of this file.
1 /***************************************************************************
2  tqslerrno.h - description
3  -------------------
4  begin : Tue May 28 2002
5  copyright : (C) 2002 by ARRL
6  author : Jon Bloom
7  email : jbloom@arrl.org
8  revision : $Id$
9  ***************************************************************************/
10 
11 #ifndef __TQSLERRNO_H
12 #define __TQSLERRNO_H
13 
18 #define TQSL_NO_ERROR 0
19 #define TQSL_SYSTEM_ERROR 1
20 #define TQSL_OPENSSL_ERROR 2
21 #define TQSL_ADIF_ERROR 3
22 #define TQSL_CUSTOM_ERROR 4
23 #define TQSL_CABRILLO_ERROR 5
24 #define TQSL_OPENSSL_VERSION_ERROR 6
25 #define TQSL_ERROR_ENUM_BASE 16
26 #define TQSL_ALLOC_ERROR 16
27 #define TQSL_RANDOM_ERROR 17
28 #define TQSL_ARGUMENT_ERROR 18
29 #define TQSL_OPERATOR_ABORT 19
30 #define TQSL_NOKEY_ERROR 20
31 #define TQSL_BUFFER_ERROR 21
32 #define TQSL_INVALID_DATE 22
33 #define TQSL_SIGNINIT_ERROR 23
34 #define TQSL_PASSWORD_ERROR 24
35 #define TQSL_EXPECTED_NAME 25
36 #define TQSL_NAME_EXISTS 26
37 #define TQSL_NAME_NOT_FOUND 27
38 #define TQSL_INVALID_TIME 28
39 #define TQSL_CERT_DATE_MISMATCH 29
40 #define TQSL_PROVIDER_NOT_FOUND 30
41 #define TQSL_CERT_KEY_ONLY 31
42 #define TQSL_CONFIG_ERROR 32
43 #define TQSL_CERT_NOT_FOUND 33
44 #define TQSL_PKCS12_ERROR 34
45 #define TQSL_CERT_TYPE_ERROR 35
46 #define TQSL_DATE_OUT_OF_RANGE 36
47 #define TQSL_DUPLICATE_QSO 37
48 #define TQSL_DB_ERROR 38
49 #define TQSL_LOCATION_NOT_FOUND 39
50 #define TQSL_CALL_NOT_FOUND 40
51 #define TQSL_CONFIG_SYNTAX_ERROR 41
52 #define TQSL_FILE_SYSTEM_ERROR 42
53 #define TQSL_FILE_SYNTAX_ERROR 43
54 #define TQSL_CERT_ERROR 44
55 #define TQSL_CERT_MISMATCH 45
56 #define TQSL_LOCATION_MISMATCH 46
57 
58 #endif /* __TQSLERRNO_H */
tqsl-2.7.2/src/doxygen/html/tqslerrno_8h.html0000644000175000017500000006277614534122221021247 0ustar rmurphyrmurphy TrustedQSL Library API: tqslerrno.h File Reference
TrustedQSL Library API
tqslerrno.h File Reference

Go to the source code of this file.

Macros

#define TQSL_NO_ERROR   0
 No error.
 
#define TQSL_SYSTEM_ERROR   1
 System Error.
 
#define TQSL_OPENSSL_ERROR   2
 Error in OpenSSL calls.
 
#define TQSL_ADIF_ERROR   3
 ADIF Errors.
 
#define TQSL_CUSTOM_ERROR   4
 Custom errors - output to tQSL_CustomError.
 
#define TQSL_CABRILLO_ERROR   5
 Cabrillo handler error.
 
#define TQSL_OPENSSL_VERSION_ERROR   6
 OpenSSL version obsolete.
 
#define TQSL_ERROR_ENUM_BASE   16
 Base for enumerated errors.
 
#define TQSL_ALLOC_ERROR   16
 Memory allocation error.
 
#define TQSL_RANDOM_ERROR   17
 Error initializing random number generator.
 
#define TQSL_ARGUMENT_ERROR   18
 Invalid arguments.
 
#define TQSL_OPERATOR_ABORT   19
 Aborted by operator.
 
#define TQSL_NOKEY_ERROR   20
 No key available.
 
#define TQSL_BUFFER_ERROR   21
 Insufficient buffer space.
 
#define TQSL_INVALID_DATE   22
 Date string invalid.
 
#define TQSL_SIGNINIT_ERROR   23
 Error initializing signing routine.
 
#define TQSL_PASSWORD_ERROR   24
 Invalid password.
 
#define TQSL_EXPECTED_NAME   25
 Name expected but not supplied.
 
#define TQSL_NAME_EXISTS   26
 Entity name exists already.
 
#define TQSL_NAME_NOT_FOUND   27
 Entity name does not exist.
 
#define TQSL_INVALID_TIME   28
 Time format is invalid.
 
#define TQSL_CERT_DATE_MISMATCH   29
 Certificate date mismatch.
 
#define TQSL_PROVIDER_NOT_FOUND   30
 Certificate provider unknown.
 
#define TQSL_CERT_KEY_ONLY   31
 No signed public key is installed.
 
#define TQSL_CONFIG_ERROR   32
 There is an error in the configuration file.
 
#define TQSL_CERT_NOT_FOUND   33
 The certificate could not be found.
 
#define TQSL_PKCS12_ERROR   34
 There is an error parsing the .p12 file.
 
#define TQSL_CERT_TYPE_ERROR   35
 The certificate type is invalid.
 
#define TQSL_DATE_OUT_OF_RANGE   36
 The date is out of the valid range.
 
#define TQSL_DUPLICATE_QSO   37
 This QSO is already uploaded.
 
#define TQSL_DB_ERROR   38
 The dupe database could not be accessed.
 
#define TQSL_LOCATION_NOT_FOUND   39
 The station location is invalid.
 
#define TQSL_CALL_NOT_FOUND   40
 The callsign could not be located.
 
#define TQSL_CONFIG_SYNTAX_ERROR   41
 The config file has a syntax error.
 
#define TQSL_FILE_SYSTEM_ERROR   42
 There was a file system I/O error.
 
#define TQSL_FILE_SYNTAX_ERROR   43
 The file format is invalid.
 
#define TQSL_CERT_ERROR   44
 Callsign certificate could not be installed.
 
#define TQSL_CERT_MISMATCH   45
 Callsign Certificate does not match QSO details.
 
#define TQSL_LOCATION_MISMATCH   46
 Station Location does not match QSO details.
 

Detailed Description

tQSL_Error values

tqsl-2.7.2/src/doxygen/html/tqslconvert_8h_source.html0000644000175000017500000007247014534122221023152 0ustar rmurphyrmurphy TrustedQSL Library API: tqslconvert.h Source File
TrustedQSL Library API
tqslconvert.h
Go to the documentation of this file.
1 /***************************************************************************
2  convert.h - description
3  -------------------
4  begin : Sun Nov 17 2002
5  copyright : (C) 2002 by ARRL
6  author : Jon Bloom
7  email : jbloom@arrl.org
8  revision : $Id$
9  ***************************************************************************/
10 
11 #ifndef __tqslconvert_h
12 #define __tqslconvert_h
13 
14 #include "tqsllib.h"
15 
27 typedef void * tQSL_Converter;
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
42 
53  tQSL_Cert *certs, int ncerts, tQSL_Location loc);
54 
65  tQSL_Cert *certs, int ncerts, tQSL_Location loc);
66 
69 
79 
80 #define TQSL_LOC_IGNORE 0
81 #define TQSL_LOC_REPORT 1
82 #define TQSL_LOC_UPDATE 2
83 
90 
108 
116 
124 
131 
139 tqsl_getDuplicateRecords(tQSL_Converter convp, char *key, char *data, int keylen);
140 
149 tqsl_getDuplicateRecordsV2(tQSL_Converter convp, char *key, char *data, int keylen);
150 
158 tqsl_putDuplicateRecord(tQSL_Converter convp, const char *key, const char *data, int keylen);
159 
169  tQSL_Date *end);
170 
193 
196 
200 
206 
209 #ifdef __cplusplus
210 }
211 #endif
212 
213 #endif /* __tqslconvert_h */
214 
DLLEXPORT int CALLCONVENTION tqsl_converterCommit(tQSL_Converter convp)
void * tQSL_Converter
Definition: tqslconvert.h:27
DLLEXPORT const char *CALLCONVENTION tqsl_getConverterRecordText(tQSL_Converter conv)
DLLEXPORT int CALLCONVENTION tqsl_setConverterQTHDetails(tQSL_Converter conv, int logverify)
DLLEXPORT int CALLCONVENTION tqsl_converterRollBack(tQSL_Converter convp)
DLLEXPORT int CALLCONVENTION tqsl_endConverter(tQSL_Converter *conv)
DLLEXPORT int CALLCONVENTION tqsl_setConverterAppName(tQSL_Converter convp, const char *app)
DLLEXPORT int CALLCONVENTION tqsl_putDuplicateRecord(tQSL_Converter convp, const char *key, const char *data, int keylen)
DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowBadCall(tQSL_Converter conv, int allow)
DLLEXPORT const char *CALLCONVENTION tqsl_getConverterGABBI(tQSL_Converter conv)
DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecords(tQSL_Converter convp, char *key, char *data, int keylen)
DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecordsV2(tQSL_Converter convp, char *key, char *data, int keylen)
DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreSeconds(tQSL_Converter convp, int ignore)
DLLEXPORT int CALLCONVENTION tqsl_beginADIFConverter(tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc)
DLLEXPORT int CALLCONVENTION tqsl_beginConverter(tQSL_Converter *convp)
DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowDuplicates(tQSL_Converter convp, int ignore)
DLLEXPORT int CALLCONVENTION tqsl_beginCabrilloConverter(tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc)
DLLEXPORT int CALLCONVENTION tqsl_setADIFConverterDateFilter(tQSL_Converter conv, tQSL_Date *start, tQSL_Date *end)
DLLEXPORT int CALLCONVENTION tqsl_getConverterCert(tQSL_Converter conv, tQSL_Cert *certp)
DLLEXPORT int CALLCONVENTION tqsl_getConverterLine(tQSL_Converter conv, int *lineno)
Definition: tqsllib.h:86
#define CALLCONVENTION
Symbol exports - Windows only.
Definition: tqsllib.h:27
void * tQSL_Location
Opaque location type.
Definition: tqsllib.h:82
#define DLLEXPORT
Symbol exports - Windows only.
Definition: tqsllib.h:25
void * tQSL_Cert
Opaque certificate type.
Definition: tqsllib.h:81
tqsl-2.7.2/src/doxygen/html/tqslconvert_8h.html0000644000175000017500000004415514534122221021571 0ustar rmurphyrmurphy TrustedQSL Library API: tqslconvert.h File Reference
TrustedQSL Library API
tqslconvert.h File Reference
#include "tqsllib.h"

Go to the source code of this file.

Macros

#define TQSL_LOC_IGNORE   0
 Ignore MY_ ADIF fields.
 
#define TQSL_LOC_REPORT   1
 Report on MY_ ADIF fields not matching cert/location.
 
#define TQSL_LOC_UPDATE   2
 Update Cert/Loc to track MY_ ADIF fields.
 

Typedefs

typedef void * tQSL_Converter
 

Functions

DLLEXPORT int CALLCONVENTION tqsl_beginConverter (tQSL_Converter *convp)
 
DLLEXPORT int CALLCONVENTION tqsl_beginADIFConverter (tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc)
 
DLLEXPORT int CALLCONVENTION tqsl_beginCabrilloConverter (tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc)
 
DLLEXPORT int CALLCONVENTION tqsl_endConverter (tQSL_Converter *conv)
 
DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowBadCall (tQSL_Converter conv, int allow)
 
DLLEXPORT int CALLCONVENTION tqsl_setConverterQTHDetails (tQSL_Converter conv, int logverify)
 
DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowDuplicates (tQSL_Converter convp, int ignore)
 
DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreSeconds (tQSL_Converter convp, int ignore)
 
DLLEXPORT int CALLCONVENTION tqsl_setConverterAppName (tQSL_Converter convp, const char *app)
 
DLLEXPORT int CALLCONVENTION tqsl_converterRollBack (tQSL_Converter convp)
 
DLLEXPORT int CALLCONVENTION tqsl_converterCommit (tQSL_Converter convp)
 
DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecords (tQSL_Converter convp, char *key, char *data, int keylen)
 
DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecordsV2 (tQSL_Converter convp, char *key, char *data, int keylen)
 
DLLEXPORT int CALLCONVENTION tqsl_putDuplicateRecord (tQSL_Converter convp, const char *key, const char *data, int keylen)
 
DLLEXPORT int CALLCONVENTION tqsl_setADIFConverterDateFilter (tQSL_Converter conv, tQSL_Date *start, tQSL_Date *end)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getConverterGABBI (tQSL_Converter conv)
 
DLLEXPORT int CALLCONVENTION tqsl_getConverterCert (tQSL_Converter conv, tQSL_Cert *certp)
 
DLLEXPORT int CALLCONVENTION tqsl_getConverterLine (tQSL_Converter conv, int *lineno)
 
DLLEXPORT const char *CALLCONVENTION tqsl_getConverterRecordText (tQSL_Converter conv)
 

Detailed Description

tQSL library converter functions.

tqsl-2.7.2/src/doxygen/html/tabs.css0000644000175000017500000002174014534122221017356 0ustar rmurphyrmurphy.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0 1px 1px rgba(255,255,255,0.9);color:#283a5d;outline:0}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a.current{color:#d23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace!important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px;border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0;border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media(min-width:768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283a5d transparent transparent transparent;background:transparent;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;-moz-border-radius:0!important;-webkit-border-radius:0;border-radius:0!important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a:hover span.sub-arrow{border-color:white transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;-moz-border-radius:5px!important;-webkit-border-radius:5px;border-radius:5px!important;-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0!important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent white}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #d23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#d23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px!important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}}tqsl-2.7.2/src/doxygen/html/tab_s.png0000644000175000017500000000027014534122221017504 0ustar rmurphyrmurphyPNG  IHDR$[IDATx݁ @@ѣ?Q"%If6[HQ<]dr s?O=w'F -~rÍ[芭m֬ݯнF)Y% `n,9B!ь\<#IENDB`tqsl-2.7.2/src/doxygen/html/tab_h.png0000644000175000017500000000026114534122221017471 0ustar rmurphyrmurphyPNG  IHDR$[xIDATxM@~ΒEv"!d*rGq={SݧH uO^[_Xvyұ=VCff{R%_rug(?gh\i>|sIENDB`tqsl-2.7.2/src/doxygen/html/tab_b.png0000644000175000017500000000025114534122221017462 0ustar rmurphyrmurphyPNG  IHDR$[pIDATxM EǻԸu`V0}:t]Ds䮂u|x>1&m8SxLU޲iEOsnxKN~jIENDB`tqsl-2.7.2/src/doxygen/html/tab_a.png0000644000175000017500000000021614534122221017462 0ustar rmurphyrmurphyPNG  IHDR$[UIDATxK 0C'o([Ž%x#٩ We# 3t I 3+E~\D9wM}Y_A4Y}IENDB`tqsl-2.7.2/src/doxygen/html/sync_on.png0000644000175000017500000000151514534122221020067 0ustar rmurphyrmurphyPNG  IHDRw=IDATx_HTY8i4-g6&kQ)!0URKڅ/PE>K-+K.YdEPaAZSܝ;3wgfsWK.Da'q_k DQCg 0Y:qZ)~L0HV z-C%g68%wUϿ }? ?3 K@h aaUe s~2&&B*Alji*˨,oƣT,d[3-*> LɟfkҠw#*AEjKUy>&{8m5Ki jjD*Nigw7DmzK۾M!k?o_lX#~XӑR*EՂדE;6e"Q(=Ezæ5Kؼָ_ 1zBJ X96jL^7{J1i@%8'7M_\Q#Uy Wo x8sv|Sn q_m >b[JX,4[T{Ratjjzz'ȶiIws KC^Y%6ꈺ]vhiWvh'̂|[^YrD=ѝlU_?]Y(N8f1qn-etm 0}b%׌=0?1s08;_ W|%\Zð >舽lnp.a{ )t; b n652?>Oдunm`׭ZWjC~>־0+ {{fMŕټ` ݛ%uA6,]kWu]7ihu1 l Ҷ̺:\cxhRQt$ fd<4B[fd7=.M9//O a},j?.5ښm?X2#d p(?c!a1ޗةܾ7dK:)3],H+ku<|`LhC7e םt H$^2%l.aeÉ|s }D^hz~Rá]|#@חև[k<|(*ݹdtM:,]' X_n| /cfOIENDB`tqsl-2.7.2/src/doxygen/html/structtqsl__provider__st.html0000644000175000017500000001237314534122221023751 0ustar rmurphyrmurphy TrustedQSL Library API: tqsl_provider_st Struct Reference
TrustedQSL Library API
tqsl_provider_st Struct Reference

#include <tqsllib.h>

Public Attributes

char organizationName [TQSL_NAME_ELEMENT_MAX+1]
 Provider name.
 
char organizationalUnitName [TQSL_NAME_ELEMENT_MAX+1]
 Provider unit.
 
char emailAddress [TQSL_NAME_ELEMENT_MAX+1]
 Provider e-mail.
 
char url [TQSL_NAME_ELEMENT_MAX+1]
 Provider URL.
 

Detailed Description

Certificate provider data


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtqsl__provider__st-members.html0000644000175000017500000000613614534122221025401 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tqsl_provider_st Member List
tqsl-2.7.2/src/doxygen/html/structtqsl__cert__req__st.html0000644000175000017500000003400414534122221024055 0ustar rmurphyrmurphy TrustedQSL Library API: tqsl_cert_req_st Struct Reference
TrustedQSL Library API
tqsl_cert_req_st Struct Reference

#include <tqsllib.h>

Public Attributes

char providerName [TQSL_NAME_ELEMENT_MAX+1]
 < Cert request data More...
 
char providerUnit [TQSL_NAME_ELEMENT_MAX+1]
 Provider unit.
 
char callSign [TQSL_CALLSIGN_MAX+1]
 Callsign.
 
char name [TQSL_CRQ_NAME_MAX+1]
 Name.
 
char address1 [TQSL_CRQ_ADDR_MAX+1]
 Address 1.
 
char address2 [TQSL_CRQ_ADDR_MAX+1]
 Address 2.
 
char city [TQSL_CRQ_CITY_MAX+1]
 City.
 
char state [TQSL_CRQ_STATE_MAX+1]
 State.
 
char postalCode [TQSL_CRQ_POSTAL_MAX+1]
 Postal Code.
 
char country [TQSL_CRQ_COUNTRY_MAX+1]
 Country.
 
char emailAddress [TQSL_CRQ_EMAIL_MAX+1]
 e-mail
 
int dxccEntity
 DXCC Entity code.
 
tQSL_Date qsoNotBefore
 QSOs not before date.
 
tQSL_Date qsoNotAfter
 QSOs not after date.
 
char password [TQSL_PASSWORD_MAX+1]
 Password.
 
tQSL_Cert signer
 Signing cert.
 
char renew
 Rewewal reference.
 

Detailed Description

Certificate request data

Member Data Documentation

◆ providerName

char tqsl_cert_req_st::providerName[TQSL_NAME_ELEMENT_MAX+1]

< Cert request data

Provider name


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtqsl__cert__req__st-members.html0000644000175000017500000001456214534122221025514 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tqsl_cert_req_st Member List
tqsl-2.7.2/src/doxygen/html/structtqsl__cabrilloField.html0000644000175000017500000001144414534122221024003 0ustar rmurphyrmurphy TrustedQSL Library API: tqsl_cabrilloField Struct Reference
TrustedQSL Library API
tqsl_cabrilloField Struct Reference

#include <cabrillo.h>

Public Attributes

char name [TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX+1]
 < Cabrillo field More...
 
char value [TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX+1]
 Field value.
 

Detailed Description

Cabrillo field data:

  • name - ADIF field name
  • value - Field content

Member Data Documentation

◆ name

char tqsl_cabrilloField::name[TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX+1]

< Cabrillo field

Field name


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtqsl__cabrilloField-members.html0000644000175000017500000000512014534122221025425 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tqsl_cabrilloField Member List

This is the complete list of members for tqsl_cabrilloField, including all inherited members.

nametqsl_cabrilloField
valuetqsl_cabrilloField
tqsl-2.7.2/src/doxygen/html/structtqsl__adifFieldResults.html0000644000175000017500000001566714534122221024514 0ustar rmurphyrmurphy TrustedQSL Library API: tqsl_adifFieldResults Struct Reference
TrustedQSL Library API
tqsl_adifFieldResults Struct Reference

#include <adif.h>

Public Attributes

char name [TQSL_ADIF_FIELD_NAME_LENGTH_MAX+1]
 Field name.
 
char size [TQSL_ADIF_FIELD_SIZE_LENGTH_MAX+1]
 Size.
 
char type [TQSL_ADIF_FIELD_TYPE_LENGTH_MAX+1]
 Type.
 
unsigned char * data
 data
 
unsigned int adifNameIndex
 Name index.
 
void * userPointer
 User pointer.
 
int line_no
 Input line where the tag was found.
 

Detailed Description

Field returned from parsing


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtqsl__adifFieldResults-members.html0000644000175000017500000000765614534122221026143 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tqsl_adifFieldResults Member List
tqsl-2.7.2/src/doxygen/html/structtqsl__adifFieldDefinitions.html0000644000175000017500000001703514534122221025315 0ustar rmurphyrmurphy TrustedQSL Library API: tqsl_adifFieldDefinitions Struct Reference
TrustedQSL Library API
tqsl_adifFieldDefinitions Struct Reference

#include <adif.h>

Public Attributes

char name [TQSL_ADIF_FIELD_NAME_LENGTH_MAX+1]
 Field name.
 
char type [TQSL_ADIF_FIELD_TYPE_LENGTH_MAX+1]
 Field type.
 
TQSL_ADIF_RANGE_TYPE rangeType
 Range type.
 
unsigned int max_length
 Max length.
 
long signed min_value
 Min value.
 
long signed max_value
 Max value.
 
const char ** enumStrings
 Enumerated values.
 
void * userPointer
 user poitner
 

Detailed Description

An ADIF field definition


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtqsl__adifFieldDefinitions-members.html0000644000175000017500000001045414534122221026743 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tqsl_adifFieldDefinitions Member List
tqsl-2.7.2/src/doxygen/html/structtQSL__Time.html0000644000175000017500000001035114534122221022002 0ustar rmurphyrmurphy TrustedQSL Library API: tQSL_Time Struct Reference
TrustedQSL Library API
tQSL_Time Struct Reference

#include <tqsllib.h>

Public Attributes

int hour
 Time hour field.
 
int minute
 Time minute field.
 
int second
 Time seconds field.
 

Detailed Description

Struct that holds h-m-s


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtQSL__Time-members.html0000644000175000017500000000535514534122221023442 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tQSL_Time Member List

This is the complete list of members for tQSL_Time, including all inherited members.

hourtQSL_Time
minutetQSL_Time
secondtQSL_Time
tqsl-2.7.2/src/doxygen/html/structtQSL__Date.html0000644000175000017500000001032714534122221021764 0ustar rmurphyrmurphy TrustedQSL Library API: tQSL_Date Struct Reference
TrustedQSL Library API
tQSL_Date Struct Reference

#include <tqsllib.h>

Public Attributes

int year
 Numeric year.
 
int month
 Numeric month.
 
int day
 Numeric day.
 

Detailed Description

Struct that holds y-m-d


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structtQSL__Date-members.html0000644000175000017500000000535114534122221023415 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
tQSL_Date Member List

This is the complete list of members for tQSL_Date, including all inherited members.

daytQSL_Date
monthtQSL_Date
yeartQSL_Date
tqsl-2.7.2/src/doxygen/html/structTQSL__QSO__RECORD.html0000644000175000017500000005031614534122221022710 0ustar rmurphyrmurphy TrustedQSL Library API: TQSL_QSO_RECORD Struct Reference
TrustedQSL Library API
TQSL_QSO_RECORD Struct Reference

#include <tqsllib.h>

Public Attributes

char callsign [TQSL_CALLSIGN_MAX+1]
 QSO callsign.
 
char band [TQSL_BAND_MAX+1]
 QSO band.
 
char mode [TQSL_MODE_MAX+1]
 QSO mode.
 
char submode [TQSL_MODE_MAX+1]
 QSO submode.
 
tQSL_Date date
 QSO date.
 
tQSL_Time time
 QSO time.
 
char freq [TQSL_FREQ_MAX+1]
 QSO frequency.
 
char rxfreq [TQSL_FREQ_MAX+1]
 QSO receive frequency.
 
char rxband [TQSL_BAND_MAX+1]
 QSO RX band.
 
char propmode [TQSL_PROPMODE_MAX+1]
 QSO prop mode.
 
char satname [TQSL_SATNAME_MAX+1]
 QSO satellite name.
 
bool callsign_set
 QSO specifies a call worked.
 
bool mode_set
 QSO specifies a mode.
 
bool band_set
 QSO specifies a band or frequency.
 
bool date_set
 QSO specifies a date.
 
bool time_set
 QSO specifies a time.
 
char my_state [TQSL_STATE_MAX+1]
 QSO specifies MY_STATE.
 
char my_gridsquare [TQSL_GRID_MAX+1]
 QSO specifies MY_GRIDSQUARE.
 
char my_vucc_grids [TQSL_GRID_MAX+1]
 QSO specifies MY_VUCC_GRIDS.
 
char my_county [TQSL_CNTY_MAX+1]
 QSO specifies MY_CNTY.
 
char my_cnty_state [TQSL_STATE_MAX+1]
 QSO specifies a state with MY_CNTY.
 
char my_country [TQSL_COUNTRY_MAX+1]
 QSO specifies MY_COUNTRY.
 
char my_cq_zone [TQSL_ZONE_MAX+1]
 QSO specifies MY_CQ_ZONE.
 
char my_itu_zone [TQSL_ZONE_MAX+1]
 QSO specifies MY_ITU_ZONE.
 
int my_dxcc
 QSO specifies MY_DXCC.
 
char my_call [TQSL_CALLSIGN_MAX+1]
 Station Callsign.
 
char my_operator [TQSL_CALLSIGN_MAX+1]
 Operator's callsign.
 
char my_iota [TQSL_IOTA_MAX+1]
 QSO specifies MY_IOTA_.
 

Detailed Description

QSO data


The documentation for this struct was generated from the following file:
tqsl-2.7.2/src/doxygen/html/structTQSL__QSO__RECORD-members.html0000644000175000017500000002174714534122221024346 0ustar rmurphyrmurphy TrustedQSL Library API: Member List
TrustedQSL Library API
TQSL_QSO_RECORD Member List
tqsl-2.7.2/src/doxygen/html/splitbar.png0000644000175000017500000000047214534122221020240 0ustar rmurphyrmurphyPNG  IHDRMIDATxݡJCa( %4 bȘͶ3v^EL ,b;{Ï/aYկq:\IIIIIIIIIIIIIIIIII-l揊_t/ϻYQVYivk_ۣI@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$C[V=[fIENDB`tqsl-2.7.2/src/doxygen/html/open.png0000644000175000017500000000017314534122221017357 0ustar rmurphyrmurphyPNG  IHDR BIDATx 0 ׬ՙ\39b!9{|I>$#ߴ8/z/>2[giU,/~\ 9ٸIENDB`tqsl-2.7.2/src/doxygen/html/nav_h.png0000644000175000017500000000014214534122221017505 0ustar rmurphyrmurphyPNG  IHDR ,@)IDATxA @BQۛТ) ) aܿoRlIENDB`tqsl-2.7.2/src/doxygen/html/nav_g.png0000644000175000017500000000013714534122221017510 0ustar rmurphyrmurphyPNG  IHDR1&IDATx1 OHf_ ->~M iMS<IENDB`tqsl-2.7.2/src/doxygen/html/nav_f.png0000644000175000017500000000023114534122221017502 0ustar rmurphyrmurphyPNG  IHDR8`IDATxK Eі[BmkHprӼ.ꎤR6Z VIE5jliIJ0/u޿6sH yIENDB`tqsl-2.7.2/src/doxygen/html/modules.html0000644000175000017500000000664314534122221020256 0ustar rmurphyrmurphy TrustedQSL Library API: Modules
TrustedQSL Library API
Modules
tqsl-2.7.2/src/doxygen/html/menudata.js0000644000175000017500000000765614534122221020061 0ustar rmurphyrmurphy/* @licstart The following is the entire license notice for the JavaScript code in this file. The MIT License (MIT) Copyright (C) 1997-2020 by Dimitri van Heesch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @licend The above is the entire license notice for the JavaScript code in this file */ var menudata={children:[ {text:"Main Page",url:"index.html"}, {text:"Modules",url:"modules.html"}, {text:"Classes",url:"annotated.html",children:[ {text:"Class List",url:"annotated.html"}, {text:"Class Members",url:"functions.html",children:[ {text:"All",url:"functions.html",children:[ {text:"a",url:"functions.html#index_a"}, {text:"b",url:"functions.html#index_b"}, {text:"c",url:"functions.html#index_c"}, {text:"d",url:"functions.html#index_d"}, {text:"e",url:"functions.html#index_e"}, {text:"f",url:"functions.html#index_f"}, {text:"h",url:"functions.html#index_h"}, {text:"l",url:"functions.html#index_l"}, {text:"m",url:"functions.html#index_m"}, {text:"n",url:"functions.html#index_n"}, {text:"o",url:"functions.html#index_o"}, {text:"p",url:"functions.html#index_p"}, {text:"q",url:"functions.html#index_q"}, {text:"r",url:"functions.html#index_r"}, {text:"s",url:"functions.html#index_s"}, {text:"t",url:"functions.html#index_t"}, {text:"u",url:"functions.html#index_u"}, {text:"v",url:"functions.html#index_v"}, {text:"y",url:"functions.html#index_y"}]}, {text:"Variables",url:"functions_vars.html",children:[ {text:"a",url:"functions_vars.html#index_a"}, {text:"b",url:"functions_vars.html#index_b"}, {text:"c",url:"functions_vars.html#index_c"}, {text:"d",url:"functions_vars.html#index_d"}, {text:"e",url:"functions_vars.html#index_e"}, {text:"f",url:"functions_vars.html#index_f"}, {text:"h",url:"functions_vars.html#index_h"}, {text:"l",url:"functions_vars.html#index_l"}, {text:"m",url:"functions_vars.html#index_m"}, {text:"n",url:"functions_vars.html#index_n"}, {text:"o",url:"functions_vars.html#index_o"}, {text:"p",url:"functions_vars.html#index_p"}, {text:"q",url:"functions_vars.html#index_q"}, {text:"r",url:"functions_vars.html#index_r"}, {text:"s",url:"functions_vars.html#index_s"}, {text:"t",url:"functions_vars.html#index_t"}, {text:"u",url:"functions_vars.html#index_u"}, {text:"v",url:"functions_vars.html#index_v"}, {text:"y",url:"functions_vars.html#index_y"}]}]}]}, {text:"Files",url:"files.html",children:[ {text:"File List",url:"files.html"}, {text:"File Members",url:"globals.html",children:[ {text:"All",url:"globals.html",children:[ {text:"c",url:"globals.html#index_c"}, {text:"d",url:"globals_d.html#index_d"}, {text:"t",url:"globals_t.html#index_t"}]}, {text:"Functions",url:"globals_func.html",children:[ {text:"t",url:"globals_func.html#index_t"}]}, {text:"Variables",url:"globals_vars.html"}, {text:"Typedefs",url:"globals_type.html"}, {text:"Enumerations",url:"globals_enum.html"}, {text:"Macros",url:"globals_defs.html",children:[ {text:"c",url:"globals_defs.html#index_c"}, {text:"d",url:"globals_defs.html#index_d"}, {text:"t",url:"globals_defs.html#index_t"}]}]}]}]} tqsl-2.7.2/src/doxygen/html/menu.js0000644000175000017500000000622614534122221017217 0ustar rmurphyrmurphy/* @licstart The following is the entire license notice for the JavaScript code in this file. The MIT License (MIT) Copyright (C) 1997-2020 by Dimitri van Heesch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @licend The above is the entire license notice for the JavaScript code in this file */ function initMenu(relPath,searchEnabled,serverSide,searchPage,search) { function makeTree(data,relPath) { var result=''; if ('children' in data) { result+=''; } return result; } $('#main-nav').append(makeTree(menudata,relPath)); $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); if (searchEnabled) { if (serverSide) { $('#main-menu').append('
  • '); } else { $('#main-menu').append('
  • '); } } $('#main-menu').smartmenus(); } /* @license-end */ tqsl-2.7.2/src/doxygen/html/jquery.js0000644000175000017500000052654114534122221017601 0ustar rmurphyrmurphy/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0a;a++)for(i in o[a])n=o[a][i],o[a].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=s.call(arguments,1),h=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(h=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):h=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))})),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
    "),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,(i>0||u>a(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var n=!1;t(document).on("mouseup",function(){n=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!n){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),n=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,n=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
    "),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
    "),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element },_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),m&&(p-=l),g&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable});/** * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler * Licensed under MIT * @author Ariel Flesler * @version 2.1.2 */ ;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1=f[g]?0:Math.min(f[g],n));!a&&1-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017 * http://www.smartmenus.org/ * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)),mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend($.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy(this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('
    ').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?(this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for(var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if((!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&(this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]")||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('')[0],$('')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"),a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i,downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2))&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0),canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})}return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$});tqsl-2.7.2/src/doxygen/html/index.html0000644000175000017500000000770014534122221017710 0ustar rmurphyrmurphy TrustedQSL Library API: Main Page
    TrustedQSL Library API
    TrustedQSL Library API Documentation

    The TrustedQSL library API is divided into several groups:

    • Certificate Handling API - Request, load and retrieve digital certificates
    • Data API - Manage station-location data and produce signed data records
    • Converter API - Convert and sign ADIF and Cabrillo log files
    • Utility API - Functions to operate on objects, set system parameters, and report errors
    • Signing API - Low-level digital signing
    • ADIF API - Low-level parsing and creation of ADIF files
    • Cabrillo API - Low-level parsing of Cabrillo files.

    Most of the library functions return an integer value that is zero if there is no error and 1 if there is an error. The specific error can be determined by examining tQSL_Error and, possibly, tQSL_ADIF_Error, tQSL_Cabrillo_Error, tQSL_ErrorFile and tQSL_CustomError. The tqsl_getErrorString() and tqsl_getErrorString_v() functions can be used to get error text strings.

    tqsl-2.7.2/src/doxygen/html/group__Util.html0000644000175000017500000011704214534122221021072 0ustar rmurphyrmurphy TrustedQSL Library API: Utility API
    TrustedQSL Library API
    Utility API

    Functions

    DLLEXPORT int CALLCONVENTION tqsl_init ()
     
    DLLEXPORT int CALLCONVENTION tqsl_setDirectory (const char *dir)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getErrorString ()
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getErrorString_v (int err)
     
    DLLEXPORT int CALLCONVENTION tqsl_encodeBase64 (const unsigned char *data, int datalen, char *output, int outputlen)
     
    DLLEXPORT int CALLCONVENTION tqsl_decodeBase64 (const char *input, unsigned char *data, int *datalen)
     
    DLLEXPORT int CALLCONVENTION tqsl_initDate (tQSL_Date *date, const char *str)
     
    DLLEXPORT int CALLCONVENTION tqsl_initTime (tQSL_Time *time, const char *str)
     
    DLLEXPORT int CALLCONVENTION tqsl_compareDates (const tQSL_Date *a, const tQSL_Date *b)
     
    DLLEXPORT int CALLCONVENTION tqsl_subtractDates (const tQSL_Date *a, const tQSL_Date *b, int *diff)
     
    DLLEXPORT char *CALLCONVENTION tqsl_convertDateToText (const tQSL_Date *date, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_isDateValid (const tQSL_Date *d)
     
    DLLEXPORT int CALLCONVENTION tqsl_isDateNull (const tQSL_Date *d)
     
    DLLEXPORT int CALLCONVENTION tqsl_isTimeValid (const tQSL_Time *t)
     
    DLLEXPORT char *CALLCONVENTION tqsl_convertTimeToText (const tQSL_Time *time, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getVersion (int *major, int *minor)
     
    DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion (int *major, int *minor)
     

    Variables

    DLLEXPORTDATA int tQSL_Error
     Error code from most recent tQSL library call. More...
     
    DLLEXPORTDATA TQSL_ADIF_GET_FIELD_ERROR tQSL_ADIF_Error
     The ADIF error code.
     
    DLLEXPORTDATA TQSL_CABRILLO_ERROR_TYPE tQSL_Cabrillo_Error
     The ADIF error code.
     
    DLLEXPORTDATA char tQSL_ErrorFile [TQSL_MAX_PATH_LEN]
     File name of file giving error. (May be empty.)
     
    DLLEXPORTDATA char tQSL_CustomError [256]
     Custom error message string.
     
    DLLEXPORTDATA int tQSL_Errno
     System errno - stored when tQSL_Error == TQSL_SYSTEM_ERROR.
     
    DLLEXPORTDATA char tQSL_ImportCall [256]
     Callsign used in import - used for missing public key error.
     
    DLLEXPORTDATA long tQSL_ImportSerial
     Serial number of recent certificate import.
     
    DLLEXPORTDATA FILE * tQSL_DiagFile
     Diagnostic log file.
     

    Detailed Description

    Function Documentation

    ◆ tqsl_compareDates()

    DLLEXPORT int CALLCONVENTION tqsl_compareDates ( const tQSL_Date a,
    const tQSL_Date b 
    )

    Compare two tQSL_Date objects.

    Returns:

    • -1 if a < b
    • 0 if a == b
    • 1 if a > b

    ◆ tqsl_convertDateToText()

    DLLEXPORT char* CALLCONVENTION tqsl_convertDateToText ( const tQSL_Date date,
    char *  buf,
    int  bufsiz 
    )

    Converts a tQSL_Date object to a YYYY-MM-DD string.

    Returns a pointer to buf or NULL on error

    ◆ tqsl_convertTimeToText()

    DLLEXPORT char* CALLCONVENTION tqsl_convertTimeToText ( const tQSL_Time time,
    char *  buf,
    int  bufsiz 
    )

    Converts a tQSL_Time object to a HH:MM:SSZ string.

    Returns a pointer to buf or NULL on error

    ◆ tqsl_decodeBase64()

    DLLEXPORT int CALLCONVENTION tqsl_decodeBase64 ( const char *  input,
    unsigned char *  data,
    int *  datalen 
    )

    Decode Base64 text into binary data.

    • input = NUL-terminated text string of Base64-encoded data
    • data = pointer to output buffer
    • datalen = pointer to int containing the size of the output buffer in bytes

    Places the number of resulting data bytes into *datalen.

    ◆ tqsl_encodeBase64()

    DLLEXPORT int CALLCONVENTION tqsl_encodeBase64 ( const unsigned char *  data,
    int  datalen,
    char *  output,
    int  outputlen 
    )

    Encode a block of data into Base64 text.

    • data = block of data to encode
    • datalen = length of data in bytes
    • output = pointer to output buffer
    • outputlen = size of output buffer in bytes

    ◆ tqsl_getConfigVersion()

    DLLEXPORT int CALLCONVENTION tqsl_getConfigVersion ( int *  major,
    int *  minor 
    )

    Returns the configuration-file version. major and/or minor may be NULL.

    ◆ tqsl_getErrorString()

    DLLEXPORT const char* CALLCONVENTION tqsl_getErrorString ( )

    Gets the error string for the current tQSL library error and resets the error status. See tqsl_getErrorString_v().

    ◆ tqsl_getErrorString_v()

    DLLEXPORT const char* CALLCONVENTION tqsl_getErrorString_v ( int  err)

    Gets the error string corresponding to the given error number. The error string is available only until the next call to tqsl_getErrorString_v or tqsl_getErrorString.

    ◆ tqsl_getVersion()

    DLLEXPORT int CALLCONVENTION tqsl_getVersion ( int *  major,
    int *  minor 
    )

    Returns the library version. major and/or minor may be NULL.

    ◆ tqsl_init()

    DLLEXPORT int CALLCONVENTION tqsl_init ( )

    Initialize the tQSL library

    This function should be called prior to calling any other library functions.

    ◆ tqsl_initDate()

    DLLEXPORT int CALLCONVENTION tqsl_initDate ( tQSL_Date date,
    const char *  str 
    )

    Initialize a tQSL_Date object from a date string.

    The date string must be YYYY-MM-DD or YYYYMMDD format.

    Returns 0 on success, nonzero on failure

    ◆ tqsl_initTime()

    DLLEXPORT int CALLCONVENTION tqsl_initTime ( tQSL_Time time,
    const char *  str 
    )

    Initialize a tQSL_Time object from a time string.

    The time string must be HH[:]MM[[:]SS] format.

    Returns 0 on success, nonzero on failure

    ◆ tqsl_isDateNull()

    DLLEXPORT int CALLCONVENTION tqsl_isDateNull ( const tQSL_Date d)

    Test whether a tQSL_Date is empty (contains all zeroes)

    Returns 1 if the date is null

    ◆ tqsl_isDateValid()

    DLLEXPORT int CALLCONVENTION tqsl_isDateValid ( const tQSL_Date d)

    Test whether a tQSL_Date contains a valid date value

    Returns 1 if the date is valid

    ◆ tqsl_isTimeValid()

    DLLEXPORT int CALLCONVENTION tqsl_isTimeValid ( const tQSL_Time t)

    Test whether a tQSL_Time contains a valid time value

    Returns 1 if the time is valid

    ◆ tqsl_setDirectory()

    DLLEXPORT int CALLCONVENTION tqsl_setDirectory ( const char *  dir)

    Set the directory where the TQSL files are kept. May be called either before of after tqsl_init(), but should be called before calling any other functions in the library.

    Note that this is purely optional. The library will figure out an approriate directory if tqsl_setDirectory isn't called. Unless there is some particular need to set the directory explicitly, programs should refrain from doing so.

    ◆ tqsl_subtractDates()

    DLLEXPORT int CALLCONVENTION tqsl_subtractDates ( const tQSL_Date a,
    const tQSL_Date b,
    int *  diff 
    )

    Calculate the number of days between two tQSL_Date objects.

    Returns a positive result if the first date is earlier, otherwise negative.

    Variable Documentation

    ◆ tQSL_Error

    DLLEXPORTDATA int tQSL_Error
    extern

    Error code from most recent tQSL library call.

    The values for the error code are defined in tqslerrno.h

    tqsl-2.7.2/src/doxygen/html/group__Sign.html0000644000175000017500000004426314534122221021061 0ustar rmurphyrmurphy TrustedQSL Library API: Signing API
    TrustedQSL Library API
    Signing API

    Functions

    DLLEXPORT int CALLCONVENTION tqsl_beginSigning (tQSL_Cert cert, char *password, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user)
     
    DLLEXPORT int CALLCONVENTION tqsl_checkSigningStatus (tQSL_Cert cert)
     
    DLLEXPORT int CALLCONVENTION tqsl_getMaxSignatureSize (tQSL_Cert cert, int *sigsize)
     
    DLLEXPORT int CALLCONVENTION tqsl_signDataBlock (tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int *siglen)
     
    DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock (tQSL_Cert cert, const unsigned char *data, int datalen, unsigned char *sig, int siglen)
     
    DLLEXPORT int CALLCONVENTION tqsl_signQSORecord (tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *rec, unsigned char *sig, int *siglen)
     
    DLLEXPORT int CALLCONVENTION tqsl_endSigning (tQSL_Cert cert)
     

    Detailed Description

    The Signing API uses a tQSL_Cert (see Certificate Handling API) to digitally sign a block of data.

    Function Documentation

    ◆ tqsl_beginSigning()

    DLLEXPORT int CALLCONVENTION tqsl_beginSigning ( tQSL_Cert  cert,
    char *  password,
    int(*)(char *pwbuf, int pwsize, void *userdata)  pwcb,
    void *  user 
    )

    Initialize the tQSL_Cert object for use in signing.

    This produces an unencrypted copy of the private key in memory.

    if password is not NULL, it must point to the password to use to decrypt the private key. If password is NULL and pwcb is not NULL, pwcb is called to get the password. If the private key is encrypted and both password and pwcb are NULL, or if the supplied password fails to decrypt the key, a TQSL_PASSWORD_ERROR error is returned.

    pwcb parameters: pwbuf is a pointer to a buffer of pwsize chars. The buffer should be NUL-terminated.

    ◆ tqsl_checkSigningStatus()

    DLLEXPORT int CALLCONVENTION tqsl_checkSigningStatus ( tQSL_Cert  cert)

    Test whether the tQSL_Cert object is initialized for signing.

    Returns 0 if initialized. Sets tQSL_Error to TQSL_SIGNINIT_ERROR if not.

    ◆ tqsl_endSigning()

    DLLEXPORT int CALLCONVENTION tqsl_endSigning ( tQSL_Cert  cert)

    Terminate signing operations for this tQSL_Cert object.

    This zero-fills the unencrypted private key in memory.

    ◆ tqsl_getMaxSignatureSize()

    DLLEXPORT int CALLCONVENTION tqsl_getMaxSignatureSize ( tQSL_Cert  cert,
    int *  sigsize 
    )

    Get the maximum size of a signature block that will be produced when the tQSL_Cert is used to sign data. (Note that the size of the signature block is unaffected by the size of the data block being signed.)

    ◆ tqsl_signDataBlock()

    DLLEXPORT int CALLCONVENTION tqsl_signDataBlock ( tQSL_Cert  cert,
    const unsigned char *  data,
    int  datalen,
    unsigned char *  sig,
    int *  siglen 
    )

    Sign a data block.

    tqsl_beginSigning() must have been called for the tQSL_Cert object before calling this function.

    ◆ tqsl_signQSORecord()

    DLLEXPORT int CALLCONVENTION tqsl_signQSORecord ( tQSL_Cert  cert,
    tQSL_Location  loc,
    TQSL_QSO_RECORD rec,
    unsigned char *  sig,
    int *  siglen 
    )

    Sign a single QSO record

    tqsl_beginSigning() must have been called for the tQSL_Cert object before calling this function.

    loc must be a valid tQSL_Location object. See Data API.

    ◆ tqsl_verifyDataBlock()

    DLLEXPORT int CALLCONVENTION tqsl_verifyDataBlock ( tQSL_Cert  cert,
    const unsigned char *  data,
    int  datalen,
    unsigned char *  sig,
    int  siglen 
    )

    Verify a signed data block.

    tqsl_beginSigning() need not have been called.

    tqsl-2.7.2/src/doxygen/html/group__Data.html0000644000175000017500000053636414534122221021042 0ustar rmurphyrmurphy TrustedQSL Library API: Data API
    TrustedQSL Library API
    Data API

    Macros

    #define TQSL_LOCATION_FIELD_TEXT   1
     Text type input field.
     
    #define TQSL_LOCATION_FIELD_DDLIST   2
     Dropdown list input field.
     
    #define TQSL_LOCATION_FIELD_LIST   3
     List type input field.
     
    #define TQSL_LOCATION_FIELD_BADZONE   4
     Used to return zone selection errors.
     
    #define TQSL_LOCATION_FIELD_CHAR   1
     Character field.
     
    #define TQSL_LOCATION_FIELD_INT   2
     Integer field.
     

    Functions

    DLLEXPORT int CALLCONVENTION tqsl_initStationLocationCapture (tQSL_Location *locp)
     
    DLLEXPORT int CALLCONVENTION tqsl_endStationLocationCapture (tQSL_Location *locp)
     
    DLLEXPORT int CALLCONVENTION tqsl_updateStationLocationCapture (tQSL_Location loc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocationCapturePages (tQSL_Location loc, int *npages)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCapturePage (tQSL_Location loc, int *page)
     
    DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCapturePage (tQSL_Location loc, int page)
     
    DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCertFlags (tQSL_Location loc, int flags)
     
    DLLEXPORT int CALLCONVENTION tqsl_nextStationLocationCapture (tQSL_Location loc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNextStationLocationCapturePage (tQSL_Location loc, int *page)
     
    DLLEXPORT int CALLCONVENTION tqsl_prevStationLocationCapture (tQSL_Location loc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getPrevStationLocationCapturePage (tQSL_Location loc, int *page)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCurrentStationLocationCapturePage (tQSL_Location loc, int *page)
     
    DLLEXPORT int CALLCONVENTION tqsl_hasNextStationLocationCapture (tQSL_Location loc, int *rval)
     
    DLLEXPORT int CALLCONVENTION tqsl_hasPrevStationLocationCapture (tQSL_Location loc, int *rval)
     
    DLLEXPORT int CALLCONVENTION tqsl_saveStationLocationCapture (tQSL_Location loc, int overwrite)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCaptureName (tQSL_Location loc, char *namebuf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCaptureName (tQSL_Location loc, const char *name)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocations (tQSL_Location loc, int *nloc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName (tQSL_Location loc, int idx, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCallSign (tQSL_Location loc, int idx, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField (tQSL_Location locp, const char *name, char *namebuf, int bufsize)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocation (tQSL_Location *loc, const char *name)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationErrors (tQSL_Location loc, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getStationDataEnc (tQSL_StationDataEnc *sdata)
     
    DLLEXPORT int CALLCONVENTION tqsl_freeStationDataEnc (tQSL_StationDataEnc sdata)
     
    DLLEXPORT int CALLCONVENTION tqsl_mergeStationLocations (const char *locdata)
     
    DLLEXPORT int CALLCONVENTION tqsl_deleteStationLocation (const char *name)
     
    DLLEXPORT int CALLCONVENTION tqsl_restoreStationLocation (const char *name)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDeletedStationLocations (char ***locp, int *nloc)
     
    DLLEXPORT void CALLCONVENTION tqsl_freeDeletedLocationList (char **list, int nloc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField (tQSL_Location loc, int *numf)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize (tQSL_Location loc, int field_num, int *rval)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel (tQSL_Location loc, int field_num, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize (tQSL_Location loc, int field_num, int *rval)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI (tQSL_Location loc, int field_num, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldInputType (tQSL_Location loc, int field_num, int *type)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataType (tQSL_Location loc, int field_num, int *type)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldFlags (tQSL_Location loc, int field_num, int *flags)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLength (tQSL_Location loc, int field_num, int *rval)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData (tQSL_Location loc, int field_num, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIntData (tQSL_Location loc, int field_num, int *dat)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIndex (tQSL_Location loc, int field_num, int *dat)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumLocationFieldListItems (tQSL_Location loc, int field_num, int *rval)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem (tQSL_Location loc, int field_num, int item_idx, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData (tQSL_Location loc, int field_num, const char *buf)
     
    DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIntData (tQSL_Location loc, int field_num, int dat)
     
    DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIndex (tQSL_Location loc, int field_num, int dat)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldChanged (tQSL_Location loc, int field_num, int *changed)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationCallSign (tQSL_Location loc, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_setLocationCallSign (tQSL_Location loc, const char *buf, int dxcc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationField (tQSL_Location locp, const char *field, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel (tQSL_Location locp, const char *field, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_setLocationField (tQSL_Location locp, const char *field, const char *buf)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationDXCCEntity (tQSL_Location loc, int *dxcc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationQSODetails (tQSL_Location locp, char *buf, int buflen)
     
    DLLEXPORT int CALLCONVENTION tqsl_getLocationStationDetails (tQSL_Location locp, char *buf, int buflen)
     
    DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo (const char *callsign, const char *json)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo (const char *callsign, char **buf)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumDXCCEntity (int *number)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity (int index, int *number, const char **name)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName (int number, const char **name)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap (int number, const char **zonemap)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDXCCStartDate (int number, tQSL_Date *d)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDXCCEndDate (int number, tQSL_Date *d)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted (int number, int *deleted)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumBand (int *number)
     
    DLLEXPORT int CALLCONVENTION tqsl_getBand (int index, const char **name, const char **spectrum, int *low, int *high)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumMode (int *number)
     
    DLLEXPORT int CALLCONVENTION tqsl_getMode (int index, const char **mode, const char **group)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumADIFMode (int *number)
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry (int index, const char **mode)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumPropagationMode (int *number)
     
    DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode (int index, const char **name, const char **descrip)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumSatellite (int *number)
     
    DLLEXPORT int CALLCONVENTION tqsl_getSatellite (int index, const char **name, const char **descrip, tQSL_Date *start, tQSL_Date *end)
     
    DLLEXPORT int CALLCONVENTION tqsl_clearCabrilloMap ()
     
    DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry (const char *contest, int field, int contest_type)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry (const char *contest, int *fieldnum, int *contest_type)
     
    DLLEXPORT int CALLCONVENTION tqsl_clearADIFModes ()
     
    DLLEXPORT int CALLCONVENTION tqsl_setADIFMode (const char *adif_item, const char *mode)
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFMode (const char *adif_item, char *mode, int nmode)
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode (const char *adif_item, char *mode, char *submode, int nmode)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCERT (tQSL_Cert cert, int uid)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItSTATION (tQSL_Location loc, int uid, int certuid)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCONTACT (tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getGABBItCONTACTData (tQSL_Cert cert, tQSL_Location loc, TQSL_QSO_RECORD *qso, int stationuid, char *signdata, int sdlen)
     

    Detailed Description

    The Data API is used to form data into TrustedQSL records. A TrustedQSL record consists of a station record and a QSO record. Together, the two records fully describe one station's end of the QSO – just as a paper QSL card does.

    The station record contains the callsign and geographic location of the station submitting the QSO record. The library manages the station records. The tqsl_xxxStationLocationCapture functions are used to generate and save a station record. The intent is to provide an interface that makes a step-by-step system (such as a GUI "wizard") easily implemented.

    The tqsl_getStationLocation() function is used to retrieve station records.

    With the necessary station location available, a signed GABBI output file can be generated using the tqsl_getGABBIxxxxx functions:

    The GABBI format requires that the tCERT record contain an integer identifier that is unique within the GABBI file. Similarly, each tSTATION record must contain a unique identifier. Aditionally, the tSTATION record must reference the identifier of a preceding tCERT record. Finally, each tCONTACT record must reference a preceding tSTATION record. (A GABBI processor uses these identifiers and references to tie the station and contact records together and to verify their signature via the certificate.) It is the responsibility of the caller to supply these identifiers and to ensure that the supplied references match the tQSL_Cert and tQSL_Location used to create the referenced GABBI records.

    Station Location Generation

    The station-location generation process involves determining the values for a number of station-location parameters. Normally this will be done by prompting the user for the values. The responses given by the user may determine which later fields are required. For example, if the user indicates that the DXCC entity is UNITED STATES, a later field would ask for the US state. This field would not be required if the DXCC entity were not in the US.

    To accommodate the dynamic nature of the field requirements, the fields are ordered such that dependent fields are queried after the field(s) on which they depend. To make this process acceptable in a GUI system, the fields are grouped into pages, where multiple fields may be displayed on the same page. The grouping is such that which fields are within the page is not dependent on any of the values of the fields within the page. That is, a page of fields contains the same fields no matter what value any of the fields contains. (However, the values of fields within the page can depend on the values of fields that precede them in the page.)

    Here is a brief overview of the sequence of events involved in generating a station location interactively, one field at a time:

    1) Call tqsl_initStationLocationCapture() (new location) or tqsl_getStationLocation() (existing location).

    2) For field from 0 to tqsl_getNumLocationField():

    3) If tqsl_hasNextStationLocationCapture() returns 1, call tqsl_nextStationLocationCapture() and go back to step 2.

    In the case of a GUI system, you'll probably want to display the fields in pages. The sequence of events is a bit different:

    1) Call tqsl_initStationLocationCapture() (new location) or tqsl_getStationLocation() (existing location).

    2) For field from 0 to tqsl_getNumLocationField(),

    3) Each time the user changes a field, call tqsl_updateStationLocationCapture(). This may change the allowable selection for fields that follow the field the user changed, so the control for each of those fields should be updated as in step 2.

    4) Once the user has completed entries for the page, if tqsl_hasNextStationLocationCapture() returns 1, call tqsl_nextStationLocationCapture() and go back to step 2.

    N.B. The first two fields in the station-location capture process are always call sign and DXCC entity, in that order. As a practical matter, these two fields must match the corresponding fields in the available certificates. The library will therefore constrain the values of these fields to match what's available in the certificate store. See Certificate Handling API.

    Function Documentation

    ◆ tqsl_clearADIFModes()

    DLLEXPORT int CALLCONVENTION tqsl_clearADIFModes ( )

    Clear the map of ADIF modes

    ◆ tqsl_clearCabrilloMap()

    DLLEXPORT int CALLCONVENTION tqsl_clearCabrilloMap ( )

    Clear the map of Cabrillo contests.

    ◆ tqsl_deleteStationLocation()

    DLLEXPORT int CALLCONVENTION tqsl_deleteStationLocation ( const char *  name)

    Remove the stored station location by name.

    ◆ tqsl_endStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_endStationLocationCapture ( tQSL_Location locp)

    Release the station-location resources. This should be called for any tQSL_Location that was initialized via tqsl_initStationLocationCapture() or tqsl_getStationLocation()

    ◆ tqsl_freeDeletedLocationList()

    DLLEXPORT void CALLCONVENTION tqsl_freeDeletedLocationList ( char **  list,
    int  nloc 
    )

    Free the list of restorable station locations.

    ◆ tqsl_freeStationDataEnc()

    DLLEXPORT int CALLCONVENTION tqsl_freeStationDataEnc ( tQSL_StationDataEnc  sdata)

    Free the pointer returned by tqsl_getStationDataEnc(tQSL_StationDataEnc*)

    ◆ tqsl_getADIFMode()

    DLLEXPORT int CALLCONVENTION tqsl_getADIFMode ( const char *  adif_item,
    char *  mode,
    int  nmode 
    )

    Map an ADIF mode to its TQSL equivalent.

    ◆ tqsl_getADIFModeEntry()

    DLLEXPORT int CALLCONVENTION tqsl_getADIFModeEntry ( int  index,
    const char **  mode 
    )

    Get an ADIF mode by its index.

    mode - The ADIF mode name

    ◆ tqsl_getADIFSubMode()

    DLLEXPORT int CALLCONVENTION tqsl_getADIFSubMode ( const char *  adif_item,
    char *  mode,
    char *  submode,
    int  nmode 
    )

    Map a GABBI mode to its mode/submode pair.

    ◆ tqsl_getBand()

    DLLEXPORT int CALLCONVENTION tqsl_getBand ( int  index,
    const char **  name,
    const char **  spectrum,
    int *  low,
    int *  high 
    )

    Get a band by its index.

    name - The GAABI name of the band. spectrum - HF | VHF | UHF low - The low end of the band in kHz (HF) or MHz (VHF/UHF) high - The low high of the band in kHz (HF) or MHz (VHF/UHF)

    Note: spectrum, low and/or high may be NULL.

    ◆ tqsl_getCabrilloMapEntry()

    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloMapEntry ( const char *  contest,
    int *  fieldnum,
    int *  contest_type 
    )

    Get the mapping of a Cabrillo contest name (as found in the CONTEST line of a Cabrillo file) to a call-worked field number and the contest type.

    fieldnum will be set to 0 if the contest name isn't in the Cabrillo map. Otherwise it is set to the QSO line field number of the call-worked field, with field counting starting at 1.

    contest_type may be NULL. If not, it is set to the Cabrillo contest type (TQSL_CABRILLO_HF or TQSL_CABRILLO_VHF), defined in cabrillo.h.

    ◆ tqsl_getCallsignLocationInfo()

    DLLEXPORT int CALLCONVENTION tqsl_getCallsignLocationInfo ( const char *  callsign,
    char **  buf 
    )

    Retrieve the json results for a given callsign location Detail.

    ◆ tqsl_getCurrentStationLocationCapturePage()

    DLLEXPORT int CALLCONVENTION tqsl_getCurrentStationLocationCapturePage ( tQSL_Location  loc,
    int *  page 
    )

    Return the current page in the page sequence.

    ◆ tqsl_getDeletedStationLocations()

    DLLEXPORT int CALLCONVENTION tqsl_getDeletedStationLocations ( char ***  locp,
    int *  nloc 
    )

    Get the list of restorable station locations.

    ◆ tqsl_getDXCCDeleted()

    DLLEXPORT int CALLCONVENTION tqsl_getDXCCDeleted ( int  number,
    int *  deleted 
    )

    Get the deleted status of a DXCC Entity by its DXCC number.

    ◆ tqsl_getDXCCEndDate()

    DLLEXPORT int CALLCONVENTION tqsl_getDXCCEndDate ( int  number,
    tQSL_Date d 
    )

    Get the end date of a DXCC Entity by its DXCC number.

    ◆ tqsl_getDXCCEntity()

    DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntity ( int  index,
    int *  number,
    const char **  name 
    )

    Get a DXCC entity from the list of DXCC entities by its index.

    ◆ tqsl_getDXCCEntityName()

    DLLEXPORT int CALLCONVENTION tqsl_getDXCCEntityName ( int  number,
    const char **  name 
    )

    Get the name of a DXCC Entity by its DXCC number.

    ◆ tqsl_getDXCCStartDate()

    DLLEXPORT int CALLCONVENTION tqsl_getDXCCStartDate ( int  number,
    tQSL_Date d 
    )

    Get the start date of a DXCC Entity by its DXCC number.

    ◆ tqsl_getDXCCZoneMap()

    DLLEXPORT int CALLCONVENTION tqsl_getDXCCZoneMap ( int  number,
    const char **  zonemap 
    )

    Get the zonemap of a DXCC Entity by its DXCC number.

    ◆ tqsl_getGABBItCERT()

    DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCERT ( tQSL_Cert  cert,
    int  uid 
    )

    Get a GABBI record that contains the certificate.

    uid is the value for the CERT_UID field

    Returns the NULL pointer on error.

    N.B. On systems that distinguish text-mode files from binary-mode files, notably Windows, the GABBI records should be written in binary mode.

    ◆ tqsl_getGABBItCONTACT()

    DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCONTACT ( tQSL_Cert  cert,
    tQSL_Location  loc,
    TQSL_QSO_RECORD qso,
    int  stationuid 
    )

    Get a GABBI record that contains the QSO data.

    • stationuid is the value of the associated STATION_UID field.

    N.B.: If cert is not initialized for signing (see tqsl_beginSigning()) the function will return with a TQSL_SIGNINIT_ERROR error.

    Returns the NULL pointer on error.

    N.B. On systems that distinguish text-mode files from binary-mode files, notably Windows, the GABBI records should be written in binary mode.

    ◆ tqsl_getGABBItCONTACTData()

    DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItCONTACTData ( tQSL_Cert  cert,
    tQSL_Location  loc,
    TQSL_QSO_RECORD qso,
    int  stationuid,
    char *  signdata,
    int  sdlen 
    )

    Get a GABBI record that contains the QSO data along with the associated signdata (QSO data signed to validate the QSO).

    • stationuid is the value of the associated STATION_UID field.

    N.B.: If cert is not initialized for signing (see tqsl_beginSigning()) the function will return with a TQSL_SIGNINIT_ERROR error.

    Returns the NULL pointer on error.

    N.B. On systems that distinguish text-mode files from binary-mode files, notably Windows, the GABBI records should be written in binary mode.

    ◆ tqsl_getGABBItSTATION()

    DLLEXPORT const char* CALLCONVENTION tqsl_getGABBItSTATION ( tQSL_Location  loc,
    int  uid,
    int  certuid 
    )

    Get a GABBI record that contains the Staion Location data.

    • uid is the value for the STATION_UID field.
    • certuid is the value of the asociated CERT_UID field.

    Returns the NULL pointer on error.

    N.B. On systems that distinguish text-mode files from binary-mode files, notably Windows, the GABBI records should be written in binary mode.

    ◆ tqsl_getLocationCallSign()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationCallSign ( tQSL_Location  loc,
    char *  buf,
    int  bufsiz 
    )

    Get the call sign from the station location.

    ◆ tqsl_getLocationDXCCEntity()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationDXCCEntity ( tQSL_Location  loc,
    int *  dxcc 
    )

    Get the DXCC entity from the station location.

    ◆ tqsl_getLocationField()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationField ( tQSL_Location  locp,
    const char *  field,
    char *  buf,
    int  bufsiz 
    )

    Get a field from the station location.

    ◆ tqsl_getLocationFieldChanged()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldChanged ( tQSL_Location  loc,
    int  field_num,
    int *  changed 
    )

    Get the changed status of a field. The changed flag is set to 1 if the field's pick list was changed during the last call to tqsl_updateStationLocationCapture or zero if the list was not changed.

    ◆ tqsl_getLocationFieldCharData()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldCharData ( tQSL_Location  loc,
    int  field_num,
    char *  buf,
    int  bufsiz 
    )

    Get the character data from the specified field.

    If the field input type (see tqsl_getLocationFieldInputType()) is TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST, this will return the text of the selected item.

    ◆ tqsl_getLocationFieldDataGABBI()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBI ( tQSL_Location  loc,
    int  field_num,
    char *  buf,
    int  bufsiz 
    )

    Get the GABBI name of the specified field

    ◆ tqsl_getLocationFieldDataGABBISize()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataGABBISize ( tQSL_Location  loc,
    int  field_num,
    int *  rval 
    )

    Get the size of the GABBI name of the specified field

    ◆ tqsl_getLocationFieldDataLabel()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabel ( tQSL_Location  loc,
    int  field_num,
    char *  buf,
    int  bufsiz 
    )

    Get the label for the specified field

    ◆ tqsl_getLocationFieldDataLabelSize()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLabelSize ( tQSL_Location  loc,
    int  field_num,
    int *  rval 
    )

    Get the number of characters in the label for the specified field

    ◆ tqsl_getLocationFieldDataLength()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataLength ( tQSL_Location  loc,
    int  field_num,
    int *  rval 
    )

    Get the length of the input field data.

    ◆ tqsl_getLocationFieldDataType()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldDataType ( tQSL_Location  loc,
    int  field_num,
    int *  type 
    )

    Get the data type of the input field.

    type will be either TQSL_LOCATION_FIELD_CHAR or TQSL_LOCATION_FIELD_INT

    ◆ tqsl_getLocationFieldFlags()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldFlags ( tQSL_Location  loc,
    int  field_num,
    int *  flags 
    )

    Get the flags for the input field.

    flags will be either TQSL_LOCATION_FIELD_UPPER Field is to be uppercased on input TQSL_LOCATION_FIELD_MUSTSEL Value must be selected TQSL_LOCATION_FIELD_SELNXT Value must be selected to allow Next/Finish

    ◆ tqsl_getLocationFieldIndex()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIndex ( tQSL_Location  loc,
    int  field_num,
    int *  dat 
    )

    If the field input type (see tqsl_getLocationFieldInputType()) is TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST, gets the index of the selected list item.

    ◆ tqsl_getLocationFieldInputType()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldInputType ( tQSL_Location  loc,
    int  field_num,
    int *  type 
    )

    Get the input type of the input field.

    type will be one of TQSL_LOCATION_FIELD_TEXT, TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST

    ◆ tqsl_getLocationFieldIntData()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldIntData ( tQSL_Location  loc,
    int  field_num,
    int *  dat 
    )

    Get the integer data from the specified field.

    This is only meaningful if the field data type (see tqsl_getLocationFieldDataType()) is TQSL_LOCATION_FIELD_INT.

    ◆ tqsl_getLocationFieldLabel()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldLabel ( tQSL_Location  locp,
    const char *  field,
    char *  buf,
    int  bufsiz 
    )

    Get a field label from the station location.

    ◆ tqsl_getLocationFieldListItem()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationFieldListItem ( tQSL_Location  loc,
    int  field_num,
    int  item_idx,
    char *  buf,
    int  bufsiz 
    )

    Get the text of a specified item of a specified field

    ◆ tqsl_getLocationQSODetails()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationQSODetails ( tQSL_Location  locp,
    char *  buf,
    int  buflen 
    )

    Get the QSO details in canonical form.

    ◆ tqsl_getLocationStationDetails()

    DLLEXPORT int CALLCONVENTION tqsl_getLocationStationDetails ( tQSL_Location  locp,
    char *  buf,
    int  buflen 
    )

    Get the station location details in canonical form.

    ◆ tqsl_getMode()

    DLLEXPORT int CALLCONVENTION tqsl_getMode ( int  index,
    const char **  mode,
    const char **  group 
    )

    Get a mode by its index.

    mode - The GAABI mode name group - CW | PHONE | IMAGE | DATA

    Note: group may be NULL.

    ◆ tqsl_getNextStationLocationCapturePage()

    DLLEXPORT int CALLCONVENTION tqsl_getNextStationLocationCapturePage ( tQSL_Location  loc,
    int *  page 
    )

    Return the next page to in the page sequence

    ◆ tqsl_getNumADIFMode()

    DLLEXPORT int CALLCONVENTION tqsl_getNumADIFMode ( int *  number)

    Get the number of ADIF Mode entries in the Mode list

    ◆ tqsl_getNumBand()

    DLLEXPORT int CALLCONVENTION tqsl_getNumBand ( int *  number)

    Get the number of Band entries in the Band list

    ◆ tqsl_getNumDXCCEntity()

    DLLEXPORT int CALLCONVENTION tqsl_getNumDXCCEntity ( int *  number)

    Get the number of DXCC entities in the primary DXCC list.

    ◆ tqsl_getNumLocationField()

    DLLEXPORT int CALLCONVENTION tqsl_getNumLocationField ( tQSL_Location  loc,
    int *  numf 
    )

    Get the number of fields on the current station location page

    Get the input type of the input field.

    type will be one of TQSL_LOCATION_FIELD_TEXT, TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST Get the number of fields on the current station location page

    ◆ tqsl_getNumLocationFieldListItems()

    DLLEXPORT int CALLCONVENTION tqsl_getNumLocationFieldListItems ( tQSL_Location  loc,
    int  field_num,
    int *  rval 
    )

    Get the number of items in the specified field's pick list.

    ◆ tqsl_getNumMode()

    DLLEXPORT int CALLCONVENTION tqsl_getNumMode ( int *  number)

    Get the number of Mode entries in the Mode list

    ◆ tqsl_getNumPropagationMode()

    DLLEXPORT int CALLCONVENTION tqsl_getNumPropagationMode ( int *  number)

    Get the number of Propagation Mode entries in the Propagation Mode list

    ◆ tqsl_getNumSatellite()

    DLLEXPORT int CALLCONVENTION tqsl_getNumSatellite ( int *  number)

    Get the number of Satellite entries in the Satellite list

    ◆ tqsl_getNumStationLocationCapturePages()

    DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocationCapturePages ( tQSL_Location  loc,
    int *  npages 
    )

    Return the number of station location capture pages.

    ◆ tqsl_getNumStationLocations()

    DLLEXPORT int CALLCONVENTION tqsl_getNumStationLocations ( tQSL_Location  loc,
    int *  nloc 
    )

    Get the number of saved station locations

    ◆ tqsl_getPrevStationLocationCapturePage()

    DLLEXPORT int CALLCONVENTION tqsl_getPrevStationLocationCapturePage ( tQSL_Location  loc,
    int *  page 
    )

    Return the previous page in the page sequence.

    ◆ tqsl_getPropagationMode()

    DLLEXPORT int CALLCONVENTION tqsl_getPropagationMode ( int  index,
    const char **  name,
    const char **  descrip 
    )

    Get a propagation mode by its index.

    name - The GAABI propagation mode name descrip - Text description of the propagation mode

    Note: descrip may be NULL.

    ◆ tqsl_getSatellite()

    DLLEXPORT int CALLCONVENTION tqsl_getSatellite ( int  index,
    const char **  name,
    const char **  descrip,
    tQSL_Date start,
    tQSL_Date end 
    )

    Get a satellite by its index.

    name - The GAABI satellite name descrip - Text description of the satellite start - The date the satellite entered service end - The last date the satellite was in service

    Note: descrip, start and/or end may be NULL.

    ◆ tqsl_getStationDataEnc()

    DLLEXPORT int CALLCONVENTION tqsl_getStationDataEnc ( tQSL_StationDataEnc sdata)

    Return the contents of the station data file as a byte stream. The caller is required to tqsl_freeStationDataEnc() this pointer when done with it.

    ◆ tqsl_getStationLocation()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocation ( tQSL_Location loc,
    const char *  name 
    )

    Retrieve a saved station location. Once finished wih the station location, tqsl_endStationLocationCapture() should be called to release resources.

    ◆ tqsl_getStationLocationCallSign()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCallSign ( tQSL_Location  loc,
    int  idx,
    char *  buf,
    int  bufsiz 
    )

    Get the call sign from the station location

    ◆ tqsl_getStationLocationCaptureName()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCaptureName ( tQSL_Location  loc,
    char *  namebuf,
    int  bufsiz 
    )

    Get the name of the station location

    ◆ tqsl_getStationLocationCapturePage()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationCapturePage ( tQSL_Location  loc,
    int *  page 
    )

    Get the current page number

    ◆ tqsl_getStationLocationErrors()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationErrors ( tQSL_Location  loc,
    char *  buf,
    int  bufsiz 
    )

    Get any errors returned from parsing the selected station location. This should be called after tqsl_getStationLocation to determine if any of the existing fields failed validation. Currently only zone data is validated here, but future validations for things like properly formatted grid squares is likely.

    ◆ tqsl_getStationLocationField()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationField ( tQSL_Location  locp,
    const char *  name,
    char *  namebuf,
    int  bufsize 
    )

    Get a named field from the station location

    ◆ tqsl_getStationLocationName()

    DLLEXPORT int CALLCONVENTION tqsl_getStationLocationName ( tQSL_Location  loc,
    int  idx,
    char *  buf,
    int  bufsiz 
    )

    Get the name of the specified (by idx) saved station location

    ◆ tqsl_hasNextStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_hasNextStationLocationCapture ( tQSL_Location  loc,
    int *  rval 
    )

    Returns 1 (in rval) if there is a next page

    ◆ tqsl_hasPrevStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_hasPrevStationLocationCapture ( tQSL_Location  loc,
    int *  rval 
    )

    Returns 1 (in rval) if there is a previous page

    ◆ tqsl_initStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_initStationLocationCapture ( tQSL_Location locp)

    Begin the process of generating a station record

    ◆ tqsl_mergeStationLocations()

    DLLEXPORT int CALLCONVENTION tqsl_mergeStationLocations ( const char *  locdata)

    Merge saved location data with existing

    ◆ tqsl_nextStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_nextStationLocationCapture ( tQSL_Location  loc)

    Advance the page to the next one in the page sequence

    ◆ tqsl_prevStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_prevStationLocationCapture ( tQSL_Location  loc)

    Return the page to the previous one in the page sequence.

    ◆ tqsl_restoreStationLocation()

    DLLEXPORT int CALLCONVENTION tqsl_restoreStationLocation ( const char *  name)

    Restore the deleted station location by name.

    ◆ tqsl_saveCallsignLocationInfo()

    DLLEXPORT int CALLCONVENTION tqsl_saveCallsignLocationInfo ( const char *  callsign,
    const char *  json 
    )

    Save the json results for a given callsign location Detail.

    ◆ tqsl_saveStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_saveStationLocationCapture ( tQSL_Location  loc,
    int  overwrite 
    )

    Save the station location data. Note that the name must have been set via tqsl_setStationLocationCaptureName if this is a new station location. If the overwrite parameter is zero and a station location of that name is already in existance, an error occurs with tQSL_Error set to TQSL_NAME_EXISTS.

    ◆ tqsl_setADIFMode()

    DLLEXPORT int CALLCONVENTION tqsl_setADIFMode ( const char *  adif_item,
    const char *  mode 
    )

    Set the mapping of an ADIF mode to a TQSL mode.

    ◆ tqsl_setCabrilloMapEntry()

    DLLEXPORT int CALLCONVENTION tqsl_setCabrilloMapEntry ( const char *  contest,
    int  field,
    int  contest_type 
    )

    Set the mapping of a Cabrillo contest name (as found in the CONTEST line of a Cabrillo file) to the QSO line call-worked field number and the contest type.

    field can have a value of TQSL_MIN_CABRILLO_MAP_FIELD (cabrillo.h) or greater. Field number starts at 1.

    contest_type must be TQSL_CABRILLO_HF or TQSL_CABRILLO_VHF, defined in cabrillo.h

    ◆ tqsl_setLocationCallSign()

    DLLEXPORT int CALLCONVENTION tqsl_setLocationCallSign ( tQSL_Location  loc,
    const char *  buf,
    int  dxcc 
    )

    Set the call sign for the station location.

    ◆ tqsl_setLocationField()

    DLLEXPORT int CALLCONVENTION tqsl_setLocationField ( tQSL_Location  locp,
    const char *  field,
    const char *  buf 
    )

    Set a field in a station location.

    ◆ tqsl_setLocationFieldCharData()

    DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldCharData ( tQSL_Location  loc,
    int  field_num,
    const char *  buf 
    )

    Set the text data of a specified field.

    ◆ tqsl_setLocationFieldIndex()

    DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIndex ( tQSL_Location  loc,
    int  field_num,
    int  dat 
    )

    If the field input type (see tqsl_getLocationFieldInputType()) is TQSL_LOCATION_FIELD_DDLIST or TQSL_LOCATION_FIELD_LIST, sets the index of the selected list item.

    ◆ tqsl_setLocationFieldIntData()

    DLLEXPORT int CALLCONVENTION tqsl_setLocationFieldIntData ( tQSL_Location  loc,
    int  field_num,
    int  dat 
    )

    Set the integer data of a specified field.

    ◆ tqsl_setStationLocationCaptureName()

    DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCaptureName ( tQSL_Location  loc,
    const char *  name 
    )

    Set the name of the station location

    ◆ tqsl_setStationLocationCapturePage()

    DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCapturePage ( tQSL_Location  loc,
    int  page 
    )

    Set the current page number. Typically, the page number will be 1 (the starting page) or a value obtained from tqsl_getStationLocationCapturePage().

    ◆ tqsl_setStationLocationCertFlags()

    DLLEXPORT int CALLCONVENTION tqsl_setStationLocationCertFlags ( tQSL_Location  loc,
    int  flags 
    )

    Set the certificate flags used in a location page. This is used to enable expired certs (or disable).

    ◆ tqsl_updateStationLocationCapture()

    DLLEXPORT int CALLCONVENTION tqsl_updateStationLocationCapture ( tQSL_Location  loc)

    Update the pages based on the currently selected settings.

    tqsl-2.7.2/src/doxygen/html/group__Convert.html0000644000175000017500000013352614534122221021602 0ustar rmurphyrmurphy TrustedQSL Library API: Converter API
    TrustedQSL Library API
    Converter API

    Macros

    #define TQSL_LOC_IGNORE   0
     Ignore MY_ ADIF fields.
     
    #define TQSL_LOC_REPORT   1
     Report on MY_ ADIF fields not matching cert/location.
     
    #define TQSL_LOC_UPDATE   2
     Update Cert/Loc to track MY_ ADIF fields.
     

    Typedefs

    typedef void * tQSL_Converter
     

    Functions

    DLLEXPORT int CALLCONVENTION tqsl_beginConverter (tQSL_Converter *convp)
     
    DLLEXPORT int CALLCONVENTION tqsl_beginADIFConverter (tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc)
     
    DLLEXPORT int CALLCONVENTION tqsl_beginCabrilloConverter (tQSL_Converter *conv, const char *filename, tQSL_Cert *certs, int ncerts, tQSL_Location loc)
     
    DLLEXPORT int CALLCONVENTION tqsl_endConverter (tQSL_Converter *conv)
     
    DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowBadCall (tQSL_Converter conv, int allow)
     
    DLLEXPORT int CALLCONVENTION tqsl_setConverterQTHDetails (tQSL_Converter conv, int logverify)
     
    DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowDuplicates (tQSL_Converter convp, int ignore)
     
    DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreSeconds (tQSL_Converter convp, int ignore)
     
    DLLEXPORT int CALLCONVENTION tqsl_setConverterAppName (tQSL_Converter convp, const char *app)
     
    DLLEXPORT int CALLCONVENTION tqsl_converterRollBack (tQSL_Converter convp)
     
    DLLEXPORT int CALLCONVENTION tqsl_converterCommit (tQSL_Converter convp)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecords (tQSL_Converter convp, char *key, char *data, int keylen)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecordsV2 (tQSL_Converter convp, char *key, char *data, int keylen)
     
    DLLEXPORT int CALLCONVENTION tqsl_putDuplicateRecord (tQSL_Converter convp, const char *key, const char *data, int keylen)
     
    DLLEXPORT int CALLCONVENTION tqsl_setADIFConverterDateFilter (tQSL_Converter conv, tQSL_Date *start, tQSL_Date *end)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getConverterGABBI (tQSL_Converter conv)
     
    DLLEXPORT int CALLCONVENTION tqsl_getConverterCert (tQSL_Converter conv, tQSL_Cert *certp)
     
    DLLEXPORT int CALLCONVENTION tqsl_getConverterLine (tQSL_Converter conv, int *lineno)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getConverterRecordText (tQSL_Converter conv)
     

    Detailed Description

    The Converter API provides the capability of converting Cabrillo and ADIF files to GABBI output.

    Typedef Documentation

    ◆ tQSL_Converter

    typedef void* tQSL_Converter

    Opaque converter type used by applications to access conversion functions

    Function Documentation

    ◆ tqsl_beginADIFConverter()

    DLLEXPORT int CALLCONVENTION tqsl_beginADIFConverter ( tQSL_Converter conv,
    const char *  filename,
    tQSL_Cert certs,
    int  ncerts,
    tQSL_Location  loc 
    )

    Initiates the conversion process for an ADIF file.

    certs and ncerts define a set of certificates that are available to the converter for signing records. Typically, this list will be obtained by calling tqsl_selectCertificates().

    tqsl_endConverter() should be called to free the resources when the conversion is finished.

    ◆ tqsl_beginCabrilloConverter()

    DLLEXPORT int CALLCONVENTION tqsl_beginCabrilloConverter ( tQSL_Converter conv,
    const char *  filename,
    tQSL_Cert certs,
    int  ncerts,
    tQSL_Location  loc 
    )

    Initiates the conversion process for a Cabrillo file.

    certs and ncerts define a set of certificates that are available to the converter for signing records. Typically, this list will be obtained by calling tqsl_selectCertificates().

    tqsl_endConverter() should be called to free the resources when the conversion is finished.

    ◆ tqsl_beginConverter()

    DLLEXPORT int CALLCONVENTION tqsl_beginConverter ( tQSL_Converter convp)

    Create a simple converter object

    Allocates resources for converting logs and processing duplicate records.

    ◆ tqsl_converterCommit()

    DLLEXPORT int CALLCONVENTION tqsl_converterCommit ( tQSL_Converter  convp)

    Commits insertions into the duplicates database.

    This is called when a log is created normally and without issue, and so the presumption is that we are "done" with these QSOs.

    ◆ tqsl_converterRollBack()

    DLLEXPORT int CALLCONVENTION tqsl_converterRollBack ( tQSL_Converter  convp)

    Roll back insertions into the duplicates database.

    This is called when cancelling creating a log, and causes any records added to the duplicates database to be removed so re-processing that log does not cause the records to be mis-marked as duplicates.

    ◆ tqsl_endConverter()

    DLLEXPORT int CALLCONVENTION tqsl_endConverter ( tQSL_Converter conv)

    End the conversion process by freeing the used resources.

    ◆ tqsl_getConverterCert()

    DLLEXPORT int CALLCONVENTION tqsl_getConverterCert ( tQSL_Converter  conv,
    tQSL_Cert certp 
    )

    Get the certificate used to sign the most recent QSO record.

    ◆ tqsl_getConverterGABBI()

    DLLEXPORT const char* CALLCONVENTION tqsl_getConverterGABBI ( tQSL_Converter  conv)

    This is the main converter function. It returns a single GABBI record.

    Returns the NULL pointer on error or EOF. (Test tQSL_Error to determine which.)

    tQSL_Error is set to TQSL_DATE_OUT_OF_RANGE if QSO date range checking is active and the QSO date is outside the specified range. This is a non-fatal error.

    tQSL_Error is set to TQSL_DUPLICATE_QSO if the QSO has already been processed on the current computer.

    N.B. On systems that distinguish text-mode files from binary-mode files, notably Windows, the GABBI records should be written in binary mode.

    N.B. If the selected certificate has not been initialized for signing via tqsl_beginSigning(), this function will return a TQSL_SIGNINIT_ERROR. The cert that caused the error can be obtained via tqsl_getConverterCert(), initialized for signing, and then this function can be called again. No data records will be lost in this process.

    ◆ tqsl_getConverterLine()

    DLLEXPORT int CALLCONVENTION tqsl_getConverterLine ( tQSL_Converter  conv,
    int *  lineno 
    )

    Get the input-file line number last read by the converter, starting at line 1.

    ◆ tqsl_getConverterRecordText()

    DLLEXPORT const char* CALLCONVENTION tqsl_getConverterRecordText ( tQSL_Converter  conv)

    Get the text of the last record read by the converter.

    Returns NULL on error.

    ◆ tqsl_getDuplicateRecords()

    DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecords ( tQSL_Converter  convp,
    char *  key,
    char *  data,
    int  keylen 
    )

    Bulk read the duplicate DB records

    This is called to retrieve the QSO records from the dupe database. It returns the key/value pair upon each call. Return -1 for end of file, 0 for success, 1 for errors.

    ◆ tqsl_getDuplicateRecordsV2()

    DLLEXPORT int CALLCONVENTION tqsl_getDuplicateRecordsV2 ( tQSL_Converter  convp,
    char *  key,
    char *  data,
    int  keylen 
    )

    Bulk read the duplicate DB records

    This is called to retrieve the QSO records from the dupe database. It returns the key/value pair upon each call. Return -1 for end of file, 0 for success, 1 for errors. V2 expects a 256 byte buffer for the "data" string.

    ◆ tqsl_putDuplicateRecord()

    DLLEXPORT int CALLCONVENTION tqsl_putDuplicateRecord ( tQSL_Converter  convp,
    const char *  key,
    const char *  data,
    int  keylen 
    )

    Bulk write duplicate DB records

    This is called to store a QSO record into the dupe database.

    Return -1 for duplicate insertion, 0 for success, 1 for errors.

    ◆ tqsl_setADIFConverterDateFilter()

    DLLEXPORT int CALLCONVENTION tqsl_setADIFConverterDateFilter ( tQSL_Converter  conv,
    tQSL_Date start,
    tQSL_Date end 
    )

    Set QSO date filtering in the converter.

    If start points to a valid date, QSOs prior to that date will be ignored by the converter. Similarly, if end points to a valid date, QSOs after that date will be ignored. Either or both may be NULL (or point to an invalid date) to disable date filtering for the respective range.

    ◆ tqsl_setConverterAllowBadCall()

    DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowBadCall ( tQSL_Converter  conv,
    int  allow 
    )

    Configure the converter to allow (allow != 0) or disallow (allow == 0) nonamateur call signs in the CALL field. (Note: the test for validity is fairly trivial and will allow some nonamateur calls to get through, but it does catch most common errors.)

    allow defaults to 0 when tqsl_beginADIFConverter or tqsl_beginCabrilloConverter is called.

    ◆ tqsl_setConverterAllowDuplicates()

    DLLEXPORT int CALLCONVENTION tqsl_setConverterAllowDuplicates ( tQSL_Converter  convp,
    int  ignore 
    )

    Configure the converter to allow (allow != 0) or disallow (allow == 0) duplicate QSOs in a signed log. Duplicate detection is done using QSO details, location details, and certificate serial number.

    allow defaults to 1 for backwards compatibility when tqsl_beginADIFConverter or tqsl_beginCabrilloConverter is called.

    ◆ tqsl_setConverterAppName()

    DLLEXPORT int CALLCONVENTION tqsl_setConverterAppName ( tQSL_Converter  convp,
    const char *  app 
    )

    Specify the name of the application using the conversion library. This is output in a header record in the exported log file. Call this before calling tqsl_getConverterGABBI.

    app is a c string containing the application name.

    ◆ tqsl_setConverterIgnoreSeconds()

    DLLEXPORT int CALLCONVENTION tqsl_setConverterIgnoreSeconds ( tQSL_Converter  convp,
    int  ignore 
    )

    Configure the converter to ignore (ignore != 0) or include (ignore == 0) seconds in times when detecting duplicate QSOs in a signed log. Duplicate detection is done using QSO details, location details, and certificate serial number.

    ignore defaults to 0.

    ◆ tqsl_setConverterQTHDetails()

    DLLEXPORT int CALLCONVENTION tqsl_setConverterQTHDetails ( tQSL_Converter  conv,
    int  logverify 
    )

    Configure the converter's handing of QTH fields in an adif input file

    allow defaults to 0 when tqsl_beginADIFConverter or tqsl_beginCabrilloConverter is called.

    tqsl-2.7.2/src/doxygen/html/group__CertStuff.html0000644000175000017500000034270614534122221022071 0ustar rmurphyrmurphy TrustedQSL Library API: Certificate Handling API
    TrustedQSL Library API
    Certificate Handling API

    Macros

    #define TQSL_SELECT_CERT_WITHKEYS   1
     Private keys only (no cert)
     
    #define TQSL_SELECT_CERT_EXPIRED   2
     Include expired certs.
     
    #define TQSL_SELECT_CERT_SUPERCEDED   4
     Include superseded certs.
     
    #define TQSL_PK_TYPE_ERR   0
     Error retrieving private key.
     
    #define TQSL_PK_TYPE_NONE   1
     No private key.
     
    #define TQSL_PK_TYPE_UNENC   2
     Private key is not encrypted.
     
    #define TQSL_PK_TYPE_ENC   3
     Private key is encrypted.
     
    #define TQSL_CERT_STATUS_UNK   0
     Status is unknown.
     
    #define TQSL_CERT_STATUS_SUP   1
     Certificate is superceded.
     
    #define TQSL_CERT_STATUS_EXP   2
     Certificate is expired.
     
    #define TQSL_CERT_STATUS_OK   3
     Certificate is valid.
     
    #define TQSL_CERT_STATUS_INV   4
     Invalid serial number.
     

    Functions

    DLLEXPORT int CALLCONVENTION tqsl_selectCertificates (tQSL_Cert **certlist, int *ncerts, const char *callsign, int dxcc, const tQSL_Date *date, const TQSL_PROVIDER *issuer, int flag)
     
    DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates (tQSL_Cert **certlist, int *ncerts, const char *type)
     
    DLLEXPORT int CALLCONVENTION tqsl_getSelectedCertificate (tQSL_Cert *cert, const tQSL_Cert **certlist, int idx)
     
    DLLEXPORT int CALLCONVENTION tqsl_isCertificateExpired (tQSL_Cert cert, int *status)
     
    DLLEXPORT int CALLCONVENTION tqsl_isCertificateSuperceded (tQSL_Cert cert, int *status)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateKeyOnly (tQSL_Cert cert, int *keyonly)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateEncoded (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded (const char *callsign, const char *type, const char *keybuf, const char *certbuf)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerial (tQSL_Cert cert, long *serial)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt (tQSL_Cert cert, char *serial, int serialsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialLength (tQSL_Cert cert)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuer (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganization (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganizationalUnit (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateCallSign (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateAROName (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateEmailAddress (tQSL_Cert cert, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotBeforeDate (tQSL_Cert cert, tQSL_Date *date)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotAfterDate (tQSL_Cert cert, tQSL_Date *date)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotBeforeDate (tQSL_Cert cert, tQSL_Date *date)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotAfterDate (tQSL_Cert cert, tQSL_Date *date)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateDXCCEntity (tQSL_Cert cert, int *dxcc)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress1 (tQSL_Cert cert, char *str, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress2 (tQSL_Cert cert, char *str, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCity (tQSL_Cert cert, char *str, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestState (tQSL_Cert cert, char *str, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestPostalCode (tQSL_Cert cert, char *str, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCountry (tQSL_Cert cert, char *str, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificatePrivateKeyType (tQSL_Cert cert)
     
    DLLEXPORT void CALLCONVENTION tqsl_freeCertificate (tQSL_Cert cert)
     
    DLLEXPORT void CALLCONVENTION tqsl_freeCertificateList (tQSL_Cert *list, int ncerts)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCertificateStatus (long serial)
     
    DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus (long serial, const char *status)
     
    DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile (const char *file, int(*cb)(int type, const char *message, void *userdata), void *user)
     
    DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile (const char *file, long *serial)
     
    DLLEXPORT int CALLCONVENTION tqsl_getNumProviders (int *n)
     
    DLLEXPORT int CALLCONVENTION tqsl_getProvider (int idx, TQSL_PROVIDER *provider)
     
    DLLEXPORT int CALLCONVENTION tqsl_createCertRequest (const char *filename, TQSL_CERT_REQ *req, int(*pwcb)(char *pwbuf, int pwsize, void *userdata), void *user)
     
    DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File (tQSL_Cert cert, const char *filename, const char *p12password)
     
    DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64 (tQSL_Cert cert, char *base64, int b64len, const char *p12password)
     
    DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File (const char *filename, const char *p12password, const char *password, int(*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type, const char *message, void *userdata), void *user)
     
    DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64 (const char *base64, const char *p12password, const char *password, int(*pwcb)(char *buf, int bufsiz, void *userdata), int(*cb)(int type, const char *message, void *userdata), void *user)
     
    DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates (char ***calls, int *ncall, const char *filter)
     
    DLLEXPORT void CALLCONVENTION tqsl_freeDeletedCertificateList (char **list, int nloc)
     
    DLLEXPORT int CALLCONVENTION tqsl_restoreCallsignCertificate (const char *callsign)
     
    DLLEXPORT int CALLCONVENTION tqsl_deleteCertificate (tQSL_Cert cert)
     

    Detailed Description

    Certificates are managed by manipulating tQSL_Cert objects. A tQSL_Cert contains:

    • The identity of the organization that issued the certificate (the "issuer").
    • The name and call sign of the amateur radio operator (ARO).
    • The DXCC entity number for which this certificate is valid.
    • The range of QSO dates for which this certificate can be used.
    • The resources needed to digitally sign and verify QSO records.

    The certificate management process consists of:

    • Applying for a certificate. Certificate requests are produced via the tqsl_createCertRequest() function, which produces a certificate-request file to send to the issuer.
    • Importing the certificate file received from the issuer into the local "certificate store," a directory managed by the tQSL library, via tqsl_importTQSLFile().
    • Selecting an appropriate certificate to use to sign a QSO record via tqsl_selectCertificates().

    Function Documentation

    ◆ tqsl_createCertRequest()

    DLLEXPORT int CALLCONVENTION tqsl_createCertRequest ( const char *  filename,
    TQSL_CERT_REQ req,
    int(*)(char *pwbuf, int pwsize, void *userdata)  pwcb,
    void *  user 
    )

    Create a certificate-request Gabbi file.

    The req parameter must be properly populated with the required fields.

    If req->password is NULL and cb is not NULL, the callback will be called to acquire the password. Otherwise req->password will be used as the password. If the password is NULL or an empty string the generated private key will be stored unencrypted.

    If req->signer is not zero and the signing certificate requires a password, the password may be in req->signer_password, else signer_pwcb is called.

    ◆ tqsl_deleteCertificate()

    DLLEXPORT int CALLCONVENTION tqsl_deleteCertificate ( tQSL_Cert  cert)

    Delete a certificate and private key

    ◆ tqsl_exportPKCS12Base64()

    DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12Base64 ( tQSL_Cert  cert,
    char *  base64,
    int  b64len,
    const char *  p12password 
    )

    Save a key pair and certificates to a Base64 string in PKCS12 format.

    The tQSL_Cert must be initialized for signing (see tqsl_beginSigning()) if the user certificate is being exported.

    The supplied p12password is used to encrypt the PKCS12 data.

    ◆ tqsl_exportPKCS12File()

    DLLEXPORT int CALLCONVENTION tqsl_exportPKCS12File ( tQSL_Cert  cert,
    const char *  filename,
    const char *  p12password 
    )

    Save a key pair and certificates to a file in PKCS12 format.

    The tQSL_Cert must be initialized for signing (see tqsl_beginSigning()) if the user certificate is being exported.

    The supplied p12password is used to encrypt the PKCS12 data.

    ◆ tqsl_freeCertificate()

    DLLEXPORT void CALLCONVENTION tqsl_freeCertificate ( tQSL_Cert  cert)

    Free the memory used by the tQSL_Cert. Once this function is called, cert should not be used again in any way.

    ◆ tqsl_freeCertificateList()

    DLLEXPORT void CALLCONVENTION tqsl_freeCertificateList ( tQSL_Cert list,
    int  ncerts 
    )

    Free the memory used by a certificate list. The allocated list of tQSL_Certs are freed and the pointer array is freed. Once this function is called, the list or the cert should not be used again in any way.

    ◆ tqsl_freeDeletedCertificateList()

    DLLEXPORT void CALLCONVENTION tqsl_freeDeletedCertificateList ( char **  list,
    int  nloc 
    )

    Free the list of restorable Callsign Certificates.

    ◆ tqsl_getCertificateAROName()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateAROName ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the ARO name string from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateCallSign()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateCallSign ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the ARO call sign string from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateDXCCEntity()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateDXCCEntity ( tQSL_Cert  cert,
    int *  dxcc 
    )

    Get the DXCC entity number from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • dxcc - Pointer to an int to hold the returned date.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateEmailAddress()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateEmailAddress ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the email address from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateEncoded()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateEncoded ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the encoded certificate for inclusion in a GABBI file.

    ◆ tqsl_getCertificateIssuer()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuer ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the issuer (DN) string from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateIssuerOrganization()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganization ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the issuer's organization name from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateIssuerOrganizationalUnit()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateIssuerOrganizationalUnit ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the issuer's organizational unit name from a tQSL_Cert.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateKeyOnly()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateKeyOnly ( tQSL_Cert  cert,
    int *  keyonly 
    )

    Find out if the "certificate" is just a key pair.

    ◆ tqsl_getCertificateNotAfterDate()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotAfterDate ( tQSL_Cert  cert,
    tQSL_Date date 
    )

    Get the certificate's not-after date from a tQSL_Cert.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateNotBeforeDate()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateNotBeforeDate ( tQSL_Cert  cert,
    tQSL_Date date 
    )

    Get the certificate's not-before date from a tQSL_Cert.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificatePrivateKeyType()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificatePrivateKeyType ( tQSL_Cert  cert)

    Determine the nature of the private key associated with a certificate.

    Returns one of the following values:

    • TQSL_PK_TYPE_ERR - An error occurred. Use tqsl_getErrorString() to examine.
    • TQSL_PK_TYPE_NONE - No matching private key was found.
    • TQSL_PK_TYPE_UNENC - The matching private key is unencrypted.
    • TQSL_PK_TYPE_ENC - The matching private key is encrypted (password protected).

    ◆ tqsl_getCertificateQSONotAfterDate()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotAfterDate ( tQSL_Cert  cert,
    tQSL_Date date 
    )

    Get the QSO not-after date from a tQSL_Cert.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateQSONotBeforeDate()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateQSONotBeforeDate ( tQSL_Cert  cert,
    tQSL_Date date 
    )

    Get the QSO not-before date from a tQSL_Cert.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateRequestAddress1()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress1 ( tQSL_Cert  cert,
    char *  str,
    int  bufsiz 
    )

    Get the first address line from the certificate request used in applying for a tQSL_Cert certificate.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateRequestAddress2()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestAddress2 ( tQSL_Cert  cert,
    char *  str,
    int  bufsiz 
    )

    Get the second address line from the certificate request used in applying for a tQSL_Cert certificate.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateRequestCity()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCity ( tQSL_Cert  cert,
    char *  str,
    int  bufsiz 
    )

    Get the city from the certificate request used in applying for a tQSL_Cert certificate.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateRequestCountry()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestCountry ( tQSL_Cert  cert,
    char *  str,
    int  bufsiz 
    )

    Get the country from the certificate request used in applying for a tQSL_Cert certificate.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateRequestPostalCode()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestPostalCode ( tQSL_Cert  cert,
    char *  str,
    int  bufsiz 
    )

    Get the postal (ZIP) code from the certificate request used in applying for a tQSL_Cert certificate.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateRequestState()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateRequestState ( tQSL_Cert  cert,
    char *  str,
    int  bufsiz 
    )

    Get the state from the certificate request used in applying for a tQSL_Cert certificate.

    • cert - a tQSL_Cert object, normally one returned from tqsl_selectCertificates()
    • buf - Buffer to hold the returned string.
    • bufsiz - Size of buf.

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_getCertificateSerial()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerial ( tQSL_Cert  cert,
    long *  serial 
    )

    Get the issuer's serial number of the certificate.

    ◆ tqsl_getCertificateSerialExt()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialExt ( tQSL_Cert  cert,
    char *  serial,
    int  serialsiz 
    )

    Get the issuer's serial number of the certificate as a hexadecimal string. Needed for certs with long serial numbers (typically root certs).

    ◆ tqsl_getCertificateSerialLength()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateSerialLength ( tQSL_Cert  cert)

    Get the length of the issuer's serial number of the certificate as it will be returned by tqsl_getCertificateSerialExt.

    ◆ tqsl_getCertificateStatus()

    DLLEXPORT int CALLCONVENTION tqsl_getCertificateStatus ( long  serial)

    Determine the status of a callsign certificate

    • serial - the serial number of the certificate tqsl_selectCertificates()
    • status - an integer to receive the certificate status

    Returns one of the following values:

    • TQSL_CERT_STATUS_UNK - An error occurred and the status is unknown
    • TQSL_CERT_STATUS_SUP - The certificate has been superceded
    • TQSL_CERT_STATUS_EXP - The certificate has expired
    • TQSL_CERT_STATUS_OK - The certificate is valid
    • TQSL_CERT_STATUS_INV - The serial number supplied is invalid

    ◆ tqsl_getDeletedCallsignCertificates()

    DLLEXPORT int CALLCONVENTION tqsl_getDeletedCallsignCertificates ( char ***  calls,
    int *  ncall,
    const char *  filter 
    )

    Get the list of restorable station locations.

    ◆ tqsl_getKeyEncoded()

    DLLEXPORT int CALLCONVENTION tqsl_getKeyEncoded ( tQSL_Cert  cert,
    char *  buf,
    int  bufsiz 
    )

    Get the encoded private key for inclusion in a backup file.

    ◆ tqsl_getNumProviders()

    DLLEXPORT int CALLCONVENTION tqsl_getNumProviders ( int *  n)

    Get the number of certificate providers known to tqsllib.

    ◆ tqsl_getProvider()

    DLLEXPORT int CALLCONVENTION tqsl_getProvider ( int  idx,
    TQSL_PROVIDER provider 
    )

    Get the information for a certificate provider.

    ◆ tqsl_getSelectedCertificate()

    DLLEXPORT int CALLCONVENTION tqsl_getSelectedCertificate ( tQSL_Cert cert,
    const tQSL_Cert **  certlist,
    int  idx 
    )

    Get a particulat certificate from the list returnded by tqsl_selectCertificates. This function exists principally to make it easier for VB programs to access the list of certificates.

    It is the caller's responsibility to ensure that 0 <= idx < ncerts (where ncerts is the value returned by tqsl_selectCertificates)

    ◆ tqsl_getSerialFromTQSLFile()

    DLLEXPORT int CALLCONVENTION tqsl_getSerialFromTQSLFile ( const char *  file,
    long *  serial 
    )

    Get the serial for the first user cert from a .tq6 file used to support asking the user to save their cert after import

    • file is the path to the file
    • serial is where the serial number is returned

    Returns 0 on success, nonzero on failure.

    ◆ tqsl_importKeyPairEncoded()

    DLLEXPORT int CALLCONVENTION tqsl_importKeyPairEncoded ( const char *  callsign,
    const char *  type,
    const char *  keybuf,
    const char *  certbuf 
    )

    Import a base64 encoded certificate and private key from a backup file.

    ◆ tqsl_importPKCS12Base64()

    DLLEXPORT int CALLCONVENTION tqsl_importPKCS12Base64 ( const char *  base64,
    const char *  p12password,
    const char *  password,
    int(*)(char *buf, int bufsiz, void *userdata)  pwcb,
    int(*)(int type, const char *message, void *userdata)  cb,
    void *  user 
    )

    Load certificates and a private key from a Base64 encoded PKCS12 string.

    ◆ tqsl_importPKCS12File()

    DLLEXPORT int CALLCONVENTION tqsl_importPKCS12File ( const char *  filename,
    const char *  p12password,
    const char *  password,
    int(*)(char *buf, int bufsiz, void *userdata)  pwcb,
    int(*)(int type, const char *message, void *userdata)  cb,
    void *  user 
    )

    Load certificates and a private key from a PKCS12 file.

    ◆ tqsl_importTQSLFile()

    DLLEXPORT int CALLCONVENTION tqsl_importTQSLFile ( const char *  file,
    int(*)(int type, const char *message, void *userdata)  cb,
    void *  user 
    )

    Import a Gabbi cert file received from a CA

    The callback, cb, will be called whenever a certificate is ready to be imported:

    cb(type, message);

    type has several fields that can be accessed via macros:

    TQSL_CERT_CB_CALL_TYPE(type) := TQSL_CERT_CB_MILESTONE | TQSL_CERT_CB_RESULT

    TQSL_CERT_CB_CERT_TYPE(type) := TQSL_CERT_CB_ROOT | TQSL_CERT_CB_CA | TQSL_CERT_CB_USER

    TQSL_CERT_CB_RESULT_TYPE(type) := TQSL_CERT_CB_PROMPT | TQSL_CERT_CB_WARNING | TQSL_CERT_CB_ERROR

    TQSL_CERT_CB_RESULT_TYPE() is meaningful only if TQSL_CERT_CB_CALL_TYPE() == TQSL_CERT_CB_RESULT

    ◆ tqsl_isCertificateExpired()

    DLLEXPORT int CALLCONVENTION tqsl_isCertificateExpired ( tQSL_Cert  cert,
    int *  status 
    )

    Find out if the "certificate" is expired

    ◆ tqsl_isCertificateSuperceded()

    DLLEXPORT int CALLCONVENTION tqsl_isCertificateSuperceded ( tQSL_Cert  cert,
    int *  status 
    )

    Find out if the "certificate" is superceded

    ◆ tqsl_restoreCallsignCertificate()

    DLLEXPORT int CALLCONVENTION tqsl_restoreCallsignCertificate ( const char *  callsign)

    Restore a deleted callsign certificate by callsign.

    ◆ tqsl_selectCACertificates()

    DLLEXPORT int CALLCONVENTION tqsl_selectCACertificates ( tQSL_Cert **  certlist,
    int *  ncerts,
    const char *  type 
    )

    Get a list of authority certificates

    Selects a set of certificates from the root or authorities certificate stores The function produces a list of tQSL_Cert objects.

    Each of the tQSL_Cert objects in the list should be freed by calling tqsl_freeCertificate(). tqsl_freeCertificateList() is a better function to use for that as it also frees the allocated array that holds the certificate pointers.

    ◆ tqsl_selectCertificates()

    DLLEXPORT int CALLCONVENTION tqsl_selectCertificates ( tQSL_Cert **  certlist,
    int *  ncerts,
    const char *  callsign,
    int  dxcc,
    const tQSL_Date date,
    const TQSL_PROVIDER issuer,
    int  flag 
    )

    Get a list of certificates

    Selects a set of certificates from the user's certificate store based on optional selection criteria. The function produces a list of tQSL_Cert objects.

    • certlist - Pointer to a variable that is set by the function to point to the list of tQSL_Cert objects.
    • ncerts - Pointer to an int that is set to the number of objects in the certlist list.
    • callsign - Optional call sign to match.
    • date - Optional QSO date string in ISO format. Only certs that have a QSO date range that encompasses this date will be returned.
    • issuer - Optional issuer (DN) string to match.
    • flag - OR of TQSL_SELECT_CERT_EXPIRED (include expired certs), TQSL_SELECT_CERT_SUPERCEDED and TQSL_SELECT_CERT_WITHKEYS (keys that don't have associated certs will be returned).

    Returns 0 on success, nonzero on failure.

    Each of the tQSL_Cert objects in the list should be freed by calling tqsl_freeCertificate(). tqsl_freeCertificateList() is a better function to use for that as it also frees the allocated array that holds the certificate pointers.

    ◆ tqsl_setCertificateStatus()

    DLLEXPORT int CALLCONVENTION tqsl_setCertificateStatus ( long  serial,
    const char *  status 
    )

    Store the status of a callsign certificate

    • serial - serial number of the certificate
    • status - the status value to store.
    tqsl-2.7.2/src/doxygen/html/group__Cabrillo.html0000644000175000017500000005754614534122221021720 0ustar rmurphyrmurphy TrustedQSL Library API: Cabrillo API
    TrustedQSL Library API

    Classes

    struct  tqsl_cabrilloField
     

    Macros

    #define TQSL_CABRILLO_MAX_FIELDS   12
     Max field count.
     
    #define TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX   64
     Max field name length.
     
    #define TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX   40
     Max field value length.
     
    #define TQSL_MIN_CABRILLO_MAP_FIELD   5
     First possible call-worked field.
     
    #define TQSL_DEF_CABRILLO_MAP_FIELD   8
     Default call-worked field.
     

    Typedefs

    typedef void * tQSL_Cabrillo
     Opaque cabrillo log type.
     

    Enumerations

    enum  TQSL_CABRILLO_ERROR_TYPE {
      TQSL_CABRILLO_NO_ERROR , TQSL_CABRILLO_EOF , TQSL_CABRILLO_NO_START_RECORD , TQSL_CABRILLO_NO_CONTEST_RECORD ,
      TQSL_CABRILLO_UNKNOWN_CONTEST , TQSL_CABRILLO_BAD_FIELD_DATA , TQSL_CABRILLO_EOR
    }
     Cabrillo status values.
     
    enum  TQSL_CABRILLO_FREQ_TYPE { TQSL_CABRILLO_HF , TQSL_CABRILLO_VHF , TQSL_CABRILLO_UNKNOWN }
     

    Functions

    DLLEXPORT const char *CALLCONVENTION tqsl_cabrilloGetError (TQSL_CABRILLO_ERROR_TYPE err)
     
    DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo (tQSL_Cabrillo *cabp, const char *filename)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloContest (tQSL_Cabrillo cab, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloFreqType (tQSL_Cabrillo cab, TQSL_CABRILLO_FREQ_TYPE *type)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloLine (tQSL_Cabrillo cab, int *lineno)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getCabrilloRecordText (tQSL_Cabrillo cab)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloField (tQSL_Cabrillo cab, tqsl_cabrilloField *field, TQSL_CABRILLO_ERROR_TYPE *err)
     
    DLLEXPORT int CALLCONVENTION tqsl_endCabrillo (tQSL_Cabrillo *cabp)
     

    Detailed Description

    These functions and data structures provide a means of parsing a Cabrillo file into its component fields.

    For convenience, the returned fields are identified using field names from the ADIF specification.

    Enumeration Type Documentation

    ◆ TQSL_CABRILLO_FREQ_TYPE

    Frequency type: HF, VHF, or UNKNOWN

    Function Documentation

    ◆ tqsl_beginCabrillo()

    DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo ( tQSL_Cabrillo cabp,
    const char *  filename 
    )

    Initialize a Cabrillo file for reading

    ◆ tqsl_cabrilloGetError()

    DLLEXPORT const char* CALLCONVENTION tqsl_cabrilloGetError ( TQSL_CABRILLO_ERROR_TYPE  err)

    Get the Cabrillo error message that corresponds to a particular error value

    ◆ tqsl_endCabrillo()

    DLLEXPORT int CALLCONVENTION tqsl_endCabrillo ( tQSL_Cabrillo cabp)

    Finish reading a Cabrillo file and release its resources

    ◆ tqsl_getCabrilloContest()

    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloContest ( tQSL_Cabrillo  cab,
    char *  buf,
    int  bufsiz 
    )

    Get the Contest name as specified in the Cabrillo CONTEST line

    ◆ tqsl_getCabrilloField()

    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloField ( tQSL_Cabrillo  cab,
    tqsl_cabrilloField field,
    TQSL_CABRILLO_ERROR_TYPE err 
    )

    Get the next field of the Cabrillo record

    err is set to TQSL_CABRILLO_NO_ERROR or TQSL_CABRILLO_EOR (end-of-record) if field was populated with data. If err == TQSL_CABRILLO_EOR, this is the last field of the record.

    err == TQSL_CABRILLO_EOF when there is no more data available.

    ◆ tqsl_getCabrilloFreqType()

    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloFreqType ( tQSL_Cabrillo  cab,
    TQSL_CABRILLO_FREQ_TYPE type 
    )

    Get the Frequency type (HF or VHF) as determined by the contest

    ◆ tqsl_getCabrilloLine()

    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloLine ( tQSL_Cabrillo  cab,
    int *  lineno 
    )

    Get the current line number (starting from 1) of the input file

    ◆ tqsl_getCabrilloRecordText()

    DLLEXPORT const char* CALLCONVENTION tqsl_getCabrilloRecordText ( tQSL_Cabrillo  cab)

    Get the text of the current Cabrillo record

    tqsl-2.7.2/src/doxygen/html/group__ADIF.html0000644000175000017500000005437414534122221020670 0ustar rmurphyrmurphy TrustedQSL Library API: ADIF API
    TrustedQSL Library API

    Classes

    struct  tqsl_adifFieldDefinitions
     
    struct  tqsl_adifFieldResults
     

    Macros

    #define TQSL_ADIF_FIELD_NAME_LENGTH_MAX   64
     Max length of ADIF field.
     
    #define TQSL_ADIF_FIELD_SIZE_LENGTH_MAX   10
     Max length of field name.
     
    #define TQSL_ADIF_FIELD_TYPE_LENGTH_MAX   1
     Max length of field type.
     

    Typedefs

    typedef void * tQSL_ADIF
     Opaque ADIF type.
     

    Enumerations

    enum  TQSL_ADIF_BOOLEAN { TQSL_FALSE , TQSL_TRUE }
     
    enum  TQSL_ADIF_RANGE_TYPE { TQSL_ADIF_RANGE_TYPE_NONE , TQSL_ADIF_RANGE_TYPE_MINMAX , TQSL_ADIF_RANGE_TYPE_ENUMERATION }
     Specifies the type of range limits to apply to a field.
     
    enum  TQSL_ADIF_GET_FIELD_ERROR {
      TQSL_ADIF_GET_FIELD_SUCCESS , TQSL_ADIF_GET_FIELD_NO_NAME_MATCH , TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH , TQSL_ADIF_GET_FIELD_NO_RANGE_MATCH ,
      TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH , TQSL_ADIF_GET_FIELD_NO_RESULT_ALLOCATION , TQSL_ADIF_GET_FIELD_NAME_LENGTH_OVERFLOW , TQSL_ADIF_GET_FIELD_DATA_LENGTH_OVERFLOW ,
      TQSL_ADIF_GET_FIELD_SIZE_OVERFLOW , TQSL_ADIF_GET_FIELD_TYPE_OVERFLOW , TQSL_ADIF_GET_FIELD_ERRONEOUS_STATE , TQSL_ADIF_GET_FIELD_EOF
    }
     Response values returned from tqsl_getADIFField()
     

    Functions

    DLLEXPORT const char *CALLCONVENTION tqsl_adifGetError (TQSL_ADIF_GET_FIELD_ERROR status)
     
    DLLEXPORT int CALLCONVENTION tqsl_beginADIF (tQSL_ADIF *adifp, const char *filename)
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFField (tQSL_ADIF adif, tqsl_adifFieldResults *field, TQSL_ADIF_GET_FIELD_ERROR *status, const tqsl_adifFieldDefinitions *adifFields, const char *const *typesDefined, unsigned char *(*allocator)(size_t))
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFLine (tQSL_ADIF adif, int *lineno)
     
    DLLEXPORT int CALLCONVENTION tqsl_endADIF (tQSL_ADIF *adifp)
     
    DLLEXPORT int CALLCONVENTION tqsl_adifMakeField (const char *fieldname, char type, const unsigned char *value, int len, unsigned char *buf, int buflen)
     

    Detailed Description

    These functions and data structures provide a means of parsing an ADIF file into its component fields, along with range-checking the field contents.

    Enumeration Type Documentation

    ◆ TQSL_ADIF_BOOLEAN

    Boolean type - TRUE/FALSE

    Function Documentation

    ◆ tqsl_adifGetError()

    DLLEXPORT const char* CALLCONVENTION tqsl_adifGetError ( TQSL_ADIF_GET_FIELD_ERROR  status)

    Get the ADIF error message that corresponds to a particular error value

    ◆ tqsl_adifMakeField()

    DLLEXPORT int CALLCONVENTION tqsl_adifMakeField ( const char *  fieldname,
    char  type,
    const unsigned char *  value,
    int  len,
    unsigned char *  buf,
    int  buflen 
    )

    Form an ADIF field string.

    N.B. On systems that distinguish text-mode files from binary-mode files, notably Windows, the text should be written in binary mode.

    ◆ tqsl_beginADIF()

    DLLEXPORT int CALLCONVENTION tqsl_beginADIF ( tQSL_ADIF adifp,
    const char *  filename 
    )

    Initialize an ADIF file for reading

    ◆ tqsl_endADIF()

    DLLEXPORT int CALLCONVENTION tqsl_endADIF ( tQSL_ADIF adifp)

    End and release an ADIF file

    ◆ tqsl_getADIFField()

    DLLEXPORT int CALLCONVENTION tqsl_getADIFField ( tQSL_ADIF  adif,
    tqsl_adifFieldResults field,
    TQSL_ADIF_GET_FIELD_ERROR status,
    const tqsl_adifFieldDefinitions adifFields,
    const char *const *  typesDefined,
    unsigned char *(*)(size_t)  allocator 
    )

    Get the next field from an ADIF file

    • adif - ADIF handle returned from tqsl_beginADIF()
    • field - pointer to struct that contains the field data and description
    • status - pointer to returned status variable
    • adifFields - pointer to an array of field-definition structures. The last item in the array should have an empty string as its name member.
    • typesDefined - pointer to an array of char pointers that define the allowed field-type strings. The last item in the array should point to an empty string.
    • allocator - pointer to a function that returns a pointer to a memory block of the specified size. This function will be called at most one time during a call to tqsl_getADIFField. The returned pointer will then be used to populate the data member of field. The caller is responsible for freeing this memory, if needed.

    ◆ tqsl_getADIFLine()

    DLLEXPORT int CALLCONVENTION tqsl_getADIFLine ( tQSL_ADIF  adif,
    int *  lineno 
    )

    Get the current line number (starting from 1) of the input file

    tqsl-2.7.2/src/doxygen/html/globals_vars.html0000644000175000017500000000577614534122221021272 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
     
    tqsl-2.7.2/src/doxygen/html/globals_type.html0000644000175000017500000000524314534122221021265 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
     
    tqsl-2.7.2/src/doxygen/html/globals_t.html0000644000175000017500000012246214534122221020552 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
    Here is a list of all documented file members with links to the documentation:

    - t -

    tqsl-2.7.2/src/doxygen/html/globals_func.html0000644000175000017500000006423314534122221021243 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
     

    - t -

    tqsl-2.7.2/src/doxygen/html/globals_eval.html0000644000175000017500000000563714534122221021242 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
     
    tqsl-2.7.2/src/doxygen/html/globals_enum.html0000644000175000017500000000457714534122221021261 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
     
    tqsl-2.7.2/src/doxygen/html/globals_defs.html0000644000175000017500000003530314534122221021225 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
     

    - c -

    - d -

    - t -

    tqsl-2.7.2/src/doxygen/html/globals_d.html0000644000175000017500000000420014534122221020517 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
    Here is a list of all documented file members with links to the documentation:

    - d -

    tqsl-2.7.2/src/doxygen/html/globals_0x74.html0000644000175000017500000011175414534122221021013 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    Here is a list of all documented file members with links to the documentation:

    - t -

    tqsl-2.7.2/src/doxygen/html/globals_0x64.html0000644000175000017500000000603714534122221021007 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    Here is a list of all documented file members with links to the documentation:

    - d -

    tqsl-2.7.2/src/doxygen/html/globals.html0000644000175000017500000000420714534122221020223 0ustar rmurphyrmurphy TrustedQSL Library API: File Members
    TrustedQSL Library API
    Here is a list of all documented file members with links to the documentation:

    - c -

    tqsl-2.7.2/src/doxygen/html/functions_vars.html0000644000175000017500000002706214534122221021647 0ustar rmurphyrmurphy TrustedQSL Library API: Class Members - Variables
    TrustedQSL Library API
     

    - a -

    - b -

    - c -

    - d -

    - e -

    - f -

    - h -

    - l -

    - m -

    - n -

    - o -

    - p -

    - q -

    - r -

    - s -

    - t -

    - u -

    - v -

    - y -

    tqsl-2.7.2/src/doxygen/html/functions.html0000644000175000017500000002724214534122221020614 0ustar rmurphyrmurphy TrustedQSL Library API: Class Members
    TrustedQSL Library API
    Here is a list of all documented class members with links to the class documentation for each member:

    - a -

    - b -

    - c -

    - d -

    - e -

    - f -

    - h -

    - l -

    - m -

    - n -

    - o -

    - p -

    - q -

    - r -

    - s -

    - t -

    - u -

    - v -

    - y -

    tqsl-2.7.2/src/doxygen/html/ftv2vertline.png0000644000175000017500000000012614534122221021046 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATxݱðScOx@ y}IENDB`tqsl-2.7.2/src/doxygen/html/ftv2splitbar.png0000644000175000017500000000047214534122221021042 0ustar rmurphyrmurphyPNG  IHDRMIDATxݡJCa( %4 bȘͶ3v^EL ,b;{Ï/aYկq:\IIIIIIIIIIIIIIIIII-l揊_t/ϻYQVYivk_ۣI@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$C[V=[fIENDB`tqsl-2.7.2/src/doxygen/html/ftv2pnode.png0000644000175000017500000000034514534122221020326 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATx=QFDk:FPK؃=V@ճ 8SHx0bnrr{򽿾$ TP XOd6"SOB(Q)+YĈ ҪR>Vtsm9(k-@ȧ-$ b [he Kp-l|CApRG'rͭaIENDB`tqsl-2.7.2/src/doxygen/html/ftv2plastnode.png0000644000175000017500000000034514534122221021212 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATx=QFDk:FPK؃=V@ճ 8SHx0bnrr{򽿾$ TP XOd6"SOB(Q)+YĈ ҪR>Vtsm9(k-@ȧ-$ b [he Kp-l|CApRG'rͭaIENDB`tqsl-2.7.2/src/doxygen/html/ftv2ns.png0000644000175000017500000000060414534122221017637 0ustar rmurphyrmurphyPNG  IHDR}\KIDATx1K1 G⁂n lE(nࢋMA@ tK%ܕ ]BI%uͅa,e v祫i\tun0oV\$G.&@Y=%$um6'߫9Q\b)0-ZTH`pcsm 5:>ަI F] jgo[ on Ԭvq?\ 6Tee lQ c3*dWTM\rh61F fIENDB`tqsl-2.7.2/src/doxygen/html/ftv2node.png0000644000175000017500000000012614534122221020143 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATxݱðScOx@ y}IENDB`tqsl-2.7.2/src/doxygen/html/ftv2mo.png0000644000175000017500000000062314534122221017633 0ustar rmurphyrmurphyPNG  IHDR}\ZIDATx1K@iBҡ(h"EI'oک 8R- BTP]zB3 _㒻}]V}dIiJb+|K…,[P\ʘMƢ#F`JݤkA?Y4ck6"Z)0SHM@㋺Wmo4HJ+Qobt *~8_+3Y- PwA+^}+xhϕMAE]TD~EÞߴ^R)`A9pq-۾ۍ3tƛTH) ICxd#1 m@V?Zgo_3-\IENDB`tqsl-2.7.2/src/doxygen/html/ftv2mnode.png0000644000175000017500000000036614534122221020326 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATx!NA\ Um@`5i`h W7] b&ofdY4 c 3v=]\B I=BB;k WN@vy4]Y|M}]x6a }dׇY>||5?>|B"'IENDB`tqsl-2.7.2/src/doxygen/html/ftv2mlastnode.png0000644000175000017500000000036614534122221021212 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATx!NA\ Um@`5i`h W7] b&ofdY4 c 3v=]\B I=BB;k WN@vy4]Y|M}]x6a }dׇY>||5?>|B"'IENDB`tqsl-2.7.2/src/doxygen/html/ftv2link.png0000644000175000017500000000135214534122221020155 0ustar rmurphyrmurphyPNG  IHDR}\IDATxMOS[sa?-XZ(PD4 AWbu`b 77wHFCԁ/`voAPqP@ 980 +y^Z9SW\83g3'Nçl_bpV"ֆXd]3xM[1W *PGz/Eg{ aoV:这1$RW,@56-,m/蹖 r5T*S(Vf89u գwa=<{ҡUr+dDF$`zNܮ0Q3~_^N=vpTLT}kqm<?ZhX_ݥ[) `ga_*2`'=F2EP l=8Wv%THqɿ<"GxH{#֫aJmKsVءM^ T ݛr߽m_?Wİ#uIENDB`tqsl-2.7.2/src/doxygen/html/ftv2lastnode.png0000644000175000017500000000012614534122221021027 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATxݱðScOx@ y}IENDB`tqsl-2.7.2/src/doxygen/html/ftv2folderopen.png0000644000175000017500000000112514534122221021353 0ustar rmurphyrmurphyPNG  IHDR}\IDATx]?oP9i4i;iiZ7`b٬,HU'$*T]TDP6w};C; aӝߟjAInS}9Hӎ|? =_Ɗue*;YEsYBėsٌ ɫYq !Gǿv̇خ F}qb]70)d-}PfY{4@}2ԗNIǃc%UImcƝ>xt9$ OVE*Û#׈r@l$PrHaa dZrqIoT\,tj2FAxv-Lp׌p TI/ \sf; jViTo^cpb]€<a՜y9:+,E f6NEKU}^;nZuUS4 ѬbN.kjT% iV )GJ@TxIENDB`tqsl-2.7.2/src/doxygen/html/ftv2folderclosed.png0000644000175000017500000000115014534122221021661 0ustar rmurphyrmurphyPNG  IHDR}\/IDATx]MO@~uؐlp]#]PYEC\9y`xC &=qvZv3m؃vLN}}ޝZA@n ONp xKxj8s _[D'yye+ 7#rNlk* 0Ь_d_(Öz=xvhzP-䍒̪u$\DJcB4.:Ϗ-}LE #gN;B6䬜@p&h>p9EEάʑ"un$R"?{<%PNt$߶+^<"2Dqq\ҙaA"ԵP}#Ez{.8i p(ADwDE߂z;Kק8t q:uvvݛvEn{MFXgfZ֝*ߩ:jYq#3SWr'  IENDB`tqsl-2.7.2/src/doxygen/html/ftv2doc.png0000644000175000017500000000135214534122221017765 0ustar rmurphyrmurphyPNG  IHDR}\IDATxMOS[sa?-XZ(PD4 AWbu`b 77wHFCԁ/`voAPqP@ 980 +y^Z9SW\83g3'Nçl_bpV"ֆXd]3xM[1W *PGz/Eg{ aoV:这1$RW,@56-,m/蹖 r5T*S(Vf89u գwa=<{ҡUr+dDF$`zNܮ0Q3~_^N=vpTLT}kqm<?ZhX_ݥ[) `ga_*2`'=F2EP l=8Wv%THqɿ<"GxH{#֫aJmKsVءM^ T ݛr߽m_?Wİ#uIENDB`tqsl-2.7.2/src/doxygen/html/ftv2cl.png0000644000175000017500000000070514534122221017617 0ustar rmurphyrmurphyPNG  IHDR}\IDATx;H#Ao4ႇK ,m vڞJ XY B|drcvoİ 0Ò3ͤe״1X8nQ88֧3*rb-$P1@Z-#011HkK wO@!fuc;sB[EA\>]Pzf| +g5b i5mM_q,cod!,{Y,zT8H]𤕘7/8Q!F~6?Y A@Ũ.@TYr8*>?e[6xIENDB`tqsl-2.7.2/src/doxygen/html/ftv2blank.png0000644000175000017500000000012614534122221020305 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATxݱðScOx@ y}IENDB`tqsl-2.7.2/src/doxygen/html/folderopen.png0000644000175000017500000000112514534122221020551 0ustar rmurphyrmurphyPNG  IHDR}\IDATx]?oP9i4i;iiZ7`b٬,HU'$*T]TDP6w};C; aӝߟjAInS}9Hӎ|? =_Ɗue*;YEsYBėsٌ ɫYq !Gǿv̇خ F}qb]70)d-}PfY{4@}2ԗNIǃc%UImcƝ>xt9$ OVE*Û#׈r@l$PrHaa dZrqIoT\,tj2FAxv-Lp׌p TI/ \sf; jViTo^cpb]€<a՜y9:+,E f6NEKU}^;nZuUS4 ѬbN.kjT% iV )GJ@TxIENDB`tqsl-2.7.2/src/doxygen/html/folderclosed.png0000644000175000017500000000115014534122221021057 0ustar rmurphyrmurphyPNG  IHDR}\/IDATx]MO@~uؐlp]#]PYEC\9y`xC &=qvZv3m؃vLN}}ޝZA@n ONp xKxj8s _[D'yye+ 7#rNlk* 0Ь_d_(Öz=xvhzP-䍒̪u$\DJcB4.:Ϗ-}LE #gN;B6䬜@p&h>p9EEάʑ"un$R"?{<%PNt$߶+^<"2Dqq\ҙaA"ԵP}#Ez{.8i p(ADwDE߂z;Kק8t q:uvvݛvEn{MFXgfZ֝*ߩ:jYq#3SWr'  IENDB`tqsl-2.7.2/src/doxygen/html/files.html0000644000175000017500000000707714534122221017712 0ustar rmurphyrmurphy TrustedQSL Library API: File List
    TrustedQSL Library API
    File List
    Here is a list of all documented files with brief descriptions:
    tqsl-2.7.2/src/doxygen/html/dynsections.js0000644000175000017500000001054414534122221020613 0ustar rmurphyrmurphy/* @licstart The following is the entire license notice for the JavaScript code in this file. The MIT License (MIT) Copyright (C) 1997-2020 by Dimitri van Heesch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @licend The above is the entire license notice for the JavaScript code in this file */ function toggleVisibility(linkObj) { var base = $(linkObj).attr('id'); var summary = $('#'+base+'-summary'); var content = $('#'+base+'-content'); var trigger = $('#'+base+'-trigger'); var src=$(trigger).attr('src'); if (content.is(':visible')===true) { content.hide(); summary.show(); $(linkObj).addClass('closed').removeClass('opened'); $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); } else { content.show(); summary.hide(); $(linkObj).removeClass('closed').addClass('opened'); $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); } return false; } function updateStripes() { $('table.directory tr'). removeClass('even').filter(':visible:even').addClass('even'); } function toggleLevel(level) { $('table.directory tr').each(function() { var l = this.id.split('_').length-1; var i = $('#img'+this.id.substring(3)); var a = $('#arr'+this.id.substring(3)); if (l tqsl-2.7.2/src/doxygen/html/doxygen.png0000644000175000017500000000730314534122221020075 0ustar rmurphyrmurphyPNG  IHDRh ;IDATx]y\պ~45%TL QPE"q11]8aw*(*" z`8 m,p$%B(8k6lk[߷;?kPx'tz3_Q4g@m ci{~4:Hc'PP7^h zbcP 3}OqNkT(?d ~z<4ǡ؞vz٦Zd,6k]Fz< Zs?sU2Sw1c`[}%ѽ.Լ6BLZ!F8[ T #g]:vu?vbR?wgb$kF~;عƕX?lNʪ,HCgAzlӺg ]jM3oҳ'=$f}GS_co.ȹ:ds:1={9?zqviDp moaEqҵw}~{j{ºFNë[OqOSXO]>muľe5{Jկ(bl}`UyacCAklysA7oJ .Be. Z'-PyF.lp&.j7rez19HG%qz׈c_k_")HJn~֘5 q5#+9T Rܸrzϴ̝ =υ{áOfwg|/$;֙ƭ]W"/< DఽB}yIEc^=[VhM$l];Kr¦* t$]M;I1!M (f<5~z mՠ>کIz;u[ie^ӳNF6B\}7+,'a -yHY,^f~?Hc{Z+4\sٷnߣFơsغD?<vkx0MlذIxdEEAMg*YE7ۙ^[uv[wG=Edn׶l'pGk+C82 dz3H BS[wŘ ~xptmţiQ歉AB1fى4uI]6% 1t.NJphz̠R1"3-"&1[:N mW0_œ 6&)ꦬ}~{m]zMP~^:eQT_*798ˍ 347E¿uSɻU_ NWeNӏ|;;d"ȉ޵ᆴ"ĴMM+bY_E]PXKНIޥoE<_(EP|m,өZߺk,kM`jzeU t36˷r}w:Χ |TܵQK_pໃYd0!a –W$$/\$ 2mLH dHV,:RZJaz*>_NT(‚^SVFU8E܈nd;8\C]=m:bDd=ߞUU5O|]Pv\]2"y[yzg{Y{Ù5;w{N3nĨwKݭ29Id y)P8ũ@mPwjl,6 hWd ump.DžtwR xBδYcxg*vo y򑕓[?V0NO난~󒯷h#Hk8kӍ^q@]ӓ,56-κUn[>]@nϜp[6# 4tn:}8T9_Y$/GK(ђM`dѺ;OB &P{qhJ+閧l2M_1ӫtlya L^y.۽[ u/]iS}N>e1qjf&iT\=kϛX-.84V5u!TE .OH4zwTr. xքHHg hT$yqzp< qrwI]I鲘s":ՖbզL69VW<;3?M3AV#ޯKUr9!qtH+6V/TS^pqgLP'5E ޺ n"2|;W"֬TwtO' +W+Z̖<&nO,I06.Z.h*INڒOegBXZ9hDSʍ A/c`A"z|ş;H#|%OOD mcƤqmu&~n πZj =_n[nN$_bE)8?6l}#bW( d-p&a"9ņ$ڛA!;{~8ޣ10`#kuN Qbh 8Mawhq(bK Z%m֍(J)@> 7% {y ohf>{p.­_%glZ\B2B #Һphݚ[<#SpA7Ht4:|gtL*($Ʃ$;b`=MM5ǾHH.HeA5}rd)T};Q5i2O00;,냔}g]79_{C>h{.II?[Kswz6u;OJa˶zvd l舊yc'rTWӰL |ʽhB T'ò]K(=Kx  L,Pʵu׈ž1ݫ;pGDxZY kf676oھH~޸ 8Up6(? K+?%ݷ/19U?B)l @=ޞkIENDB`tqsl-2.7.2/src/doxygen/html/doc.png0000644000175000017500000000135214534122221017163 0ustar rmurphyrmurphyPNG  IHDR}\IDATxMOS[sa?-XZ(PD4 AWbu`b 77wHFCԁ/`voAPqP@ 980 +y^Z9SW\83g3'Nçl_bpV"ֆXd]3xM[1W *PGz/Eg{ aoV:这1$RW,@56-,m/蹖 r5T*S(Vf89u գwa=<{ҡUr+dDF$`zNܮ0Q3~_^N=vpTLT}kqm<?ZhX_ݥ[) `ga_*2`'=F2EP l=8Wv%THqɿ<"GxH{#֫aJmKsVءM^ T ݛr߽m_?Wİ#uIENDB`tqsl-2.7.2/src/doxygen/html/closed.png0000644000175000017500000000020414534122221017662 0ustar rmurphyrmurphyPNG  IHDR KIDATxm @!Gk7-`&sts@k}2 P%_N .:0Dk›x" ֛)x5IENDB`tqsl-2.7.2/src/doxygen/html/classes.html0000644000175000017500000000526514534122221020242 0ustar rmurphyrmurphy TrustedQSL Library API: Class Index
    TrustedQSL Library API
    Class Index
    tqsl-2.7.2/src/doxygen/html/cabrillo_8h_source.html0000644000175000017500000005541714534122221022357 0ustar rmurphyrmurphy TrustedQSL Library API: cabrillo.h Source File
    TrustedQSL Library API
    cabrillo.h
    Go to the documentation of this file.
    1 /***************************************************************************
    2  cabrillo.h - description
    3  -------------------
    4  begin : Thu Dec 5 2002
    5  copyright : (C) 2002 by ARRL
    6  author : Jon Bloom
    7  email : jbloom@arrl.org
    8  revision : $Id$
    9  ***************************************************************************/
    10 
    11 #ifndef __CABRILLO_H
    12 #define __CABRILLO_H
    13 
    14 #include "tqsllib.h"
    15 
    16 #undef CLIENT_STATIC
    17 #ifndef LOTW_SERVER
    18 #define CLIENT_STATIC static
    19 #else
    20 #define CLIENT_STATIC
    21 #endif
    22 
    35 #define TQSL_CABRILLO_MAX_FIELDS 12
    36 #define TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX 64
    37 #define TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX 40
    38 
    40 typedef enum {
    41  TQSL_CABRILLO_NO_ERROR,
    42  TQSL_CABRILLO_EOF,
    43  TQSL_CABRILLO_NO_START_RECORD,
    44  TQSL_CABRILLO_NO_CONTEST_RECORD,
    45  TQSL_CABRILLO_UNKNOWN_CONTEST,
    46  TQSL_CABRILLO_BAD_FIELD_DATA,
    47  TQSL_CABRILLO_EOR,
    49 
    53 typedef enum {
    54  TQSL_CABRILLO_HF,
    55  TQSL_CABRILLO_VHF,
    56  TQSL_CABRILLO_UNKNOWN,
    58 
    59 // Minimum field number for callsign and default field number
    60 // For VHF, default should be 7.
    61 #define TQSL_MIN_CABRILLO_MAP_FIELD 5
    62 #define TQSL_DEF_CABRILLO_MAP_FIELD 8
    63 
    69 typedef struct {
    73 
    74 typedef void * tQSL_Cabrillo;
    75 
    76 #ifdef __cplusplus
    77 extern "C" {
    78 #endif
    79 
    82 
    84 DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo(tQSL_Cabrillo *cabp, const char *filename);
    85 
    88 
    91 
    94 
    97 
    107 
    110 
    111 #ifdef __cplusplus
    112 }
    113 #endif
    114 
    117 #endif // __CABRILLO_H
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloLine(tQSL_Cabrillo cab, int *lineno)
    DLLEXPORT const char *CALLCONVENTION tqsl_getCabrilloRecordText(tQSL_Cabrillo cab)
    TQSL_CABRILLO_ERROR_TYPE
    Cabrillo status values.
    Definition: cabrillo.h:40
    #define TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX
    Max field value length.
    Definition: cabrillo.h:37
    DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo(tQSL_Cabrillo *cabp, const char *filename)
    TQSL_CABRILLO_FREQ_TYPE
    Definition: cabrillo.h:53
    DLLEXPORT int CALLCONVENTION tqsl_endCabrillo(tQSL_Cabrillo *cabp)
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloFreqType(tQSL_Cabrillo cab, TQSL_CABRILLO_FREQ_TYPE *type)
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloContest(tQSL_Cabrillo cab, char *buf, int bufsiz)
    #define TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX
    Max field name length.
    Definition: cabrillo.h:36
    void * tQSL_Cabrillo
    Opaque cabrillo log type.
    Definition: cabrillo.h:74
    DLLEXPORT const char *CALLCONVENTION tqsl_cabrilloGetError(TQSL_CABRILLO_ERROR_TYPE err)
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloField(tQSL_Cabrillo cab, tqsl_cabrilloField *field, TQSL_CABRILLO_ERROR_TYPE *err)
    Definition: cabrillo.h:69
    #define CALLCONVENTION
    Symbol exports - Windows only.
    Definition: tqsllib.h:27
    #define DLLEXPORT
    Symbol exports - Windows only.
    Definition: tqsllib.h:25
    tqsl-2.7.2/src/doxygen/html/cabrillo_8h.html0000644000175000017500000003422014534122221020764 0ustar rmurphyrmurphy TrustedQSL Library API: cabrillo.h File Reference
    TrustedQSL Library API
    cabrillo.h File Reference
    #include "tqsllib.h"

    Go to the source code of this file.

    Classes

    struct  tqsl_cabrilloField
     

    Macros

    #define CLIENT_STATIC   static
     Static linkage.
     
    #define TQSL_CABRILLO_MAX_FIELDS   12
     Max field count.
     
    #define TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX   64
     Max field name length.
     
    #define TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX   40
     Max field value length.
     
    #define TQSL_MIN_CABRILLO_MAP_FIELD   5
     First possible call-worked field.
     
    #define TQSL_DEF_CABRILLO_MAP_FIELD   8
     Default call-worked field.
     

    Typedefs

    typedef void * tQSL_Cabrillo
     Opaque cabrillo log type.
     

    Enumerations

    enum  TQSL_CABRILLO_ERROR_TYPE {
      TQSL_CABRILLO_NO_ERROR , TQSL_CABRILLO_EOF , TQSL_CABRILLO_NO_START_RECORD , TQSL_CABRILLO_NO_CONTEST_RECORD ,
      TQSL_CABRILLO_UNKNOWN_CONTEST , TQSL_CABRILLO_BAD_FIELD_DATA , TQSL_CABRILLO_EOR
    }
     Cabrillo status values.
     
    enum  TQSL_CABRILLO_FREQ_TYPE { TQSL_CABRILLO_HF , TQSL_CABRILLO_VHF , TQSL_CABRILLO_UNKNOWN }
     

    Functions

    DLLEXPORT const char *CALLCONVENTION tqsl_cabrilloGetError (TQSL_CABRILLO_ERROR_TYPE err)
     
    DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo (tQSL_Cabrillo *cabp, const char *filename)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloContest (tQSL_Cabrillo cab, char *buf, int bufsiz)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloFreqType (tQSL_Cabrillo cab, TQSL_CABRILLO_FREQ_TYPE *type)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloLine (tQSL_Cabrillo cab, int *lineno)
     
    DLLEXPORT const char *CALLCONVENTION tqsl_getCabrilloRecordText (tQSL_Cabrillo cab)
     
    DLLEXPORT int CALLCONVENTION tqsl_getCabrilloField (tQSL_Cabrillo cab, tqsl_cabrilloField *field, TQSL_CABRILLO_ERROR_TYPE *err)
     
    DLLEXPORT int CALLCONVENTION tqsl_endCabrillo (tQSL_Cabrillo *cabp)
     
    tqsl-2.7.2/src/doxygen/html/bdwn.png0000644000175000017500000000022314534122221017344 0ustar rmurphyrmurphyPNG  IHDR5ZIDATx DP1lm rj.e D[ɾ|6V3?Ls'(}>+ Kch` ^ލnIENDB`tqsl-2.7.2/src/doxygen/html/bc_s.png0000644000175000017500000000124414534122221017324 0ustar rmurphyrmurphyPNG  IHDR_ kIDATxkQϝ̤I&m&156*nąܸR,4 +H(Ub1J.(EmߏhJmKS'C(х & r3g(z&_9}՟@mu ` h`ԯ &~M4%3?h)\Yi>Jb @giވkg\轭EUv+?E"pB\Y&$vM+Dn)}:Xo 3گ'.f0u9Ljf6%3Gf#sm(,k*ʒJJˢou_~ r]%%mnu]zr5[ưXeIVtsm9(k-@ȧ-$ b [he Kp-l|CApRG'rͭaIENDB`tqsl-2.7.2/src/doxygen/html/arrowdown.png0000644000175000017500000000036614534122221020444 0ustar rmurphyrmurphyPNG  IHDRɪ|IDATx!NA\ Um@`5i`h W7] b&ofdY4 c 3v=]\B I=BB;k WN@vy4]Y|M}]x6a }dׇY>||5?>|B"'IENDB`tqsl-2.7.2/src/doxygen/html/annotated.html0000644000175000017500000001030314534122221020547 0ustar rmurphyrmurphy TrustedQSL Library API: Class List
    TrustedQSL Library API
    Class List
    Here are the classes, structs, unions and interfaces with brief descriptions:
    tqsl-2.7.2/src/doxygen/html/adif_8h_source.html0000644000175000017500000007752214534122221021474 0ustar rmurphyrmurphy TrustedQSL Library API: adif.h Source File
    TrustedQSL Library API
    adif.h
    Go to the documentation of this file.
    1 /***************************************************************************
    2  adif.h - description
    3  -------------------
    4  begin : Wed May 15 2002
    5  copyright : (C) 2002 by ARRL
    6  email : MSimcik@localhost.localdomain
    7  revision : $Id$
    8  ***************************************************************************/
    9 
    10 #ifndef __ADIF_H
    11 #define __ADIF_H
    12 
    13 #include "tqsllib.h"
    14 
    15 #include <stdio.h>
    16 #include <stdlib.h>
    17 
    28 #define TQSL_ADIF_FIELD_NAME_LENGTH_MAX 64
    29 #define TQSL_ADIF_FIELD_SIZE_LENGTH_MAX 10
    30 #define TQSL_ADIF_FIELD_TYPE_LENGTH_MAX 1
    31 
    35 #ifndef TQSL_ADIF_BOOLEAN
    36 typedef enum {
    37  TQSL_FALSE,
    38  TQSL_TRUE
    40 #endif
    41 
    42 typedef void * tQSL_ADIF;
    43 
    45 typedef enum {
    46  TQSL_ADIF_RANGE_TYPE_NONE,
    47  TQSL_ADIF_RANGE_TYPE_MINMAX,
    48  TQSL_ADIF_RANGE_TYPE_ENUMERATION
    50 
    52 typedef enum {
    53  TQSL_ADIF_GET_FIELD_SUCCESS,
    54  TQSL_ADIF_GET_FIELD_NO_NAME_MATCH,
    55  TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH,
    56  TQSL_ADIF_GET_FIELD_NO_RANGE_MATCH,
    57  TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH,
    58  TQSL_ADIF_GET_FIELD_NO_RESULT_ALLOCATION,
    59  TQSL_ADIF_GET_FIELD_NAME_LENGTH_OVERFLOW,
    60  TQSL_ADIF_GET_FIELD_DATA_LENGTH_OVERFLOW,
    61  TQSL_ADIF_GET_FIELD_SIZE_OVERFLOW,
    62  TQSL_ADIF_GET_FIELD_TYPE_OVERFLOW,
    63  TQSL_ADIF_GET_FIELD_ERRONEOUS_STATE,
    64  TQSL_ADIF_GET_FIELD_EOF
    66 
    68 typedef struct {
    72  unsigned int max_length;
    73  long signed min_value;
    74  long signed max_value;
    75  const char **enumStrings;
    76  void *userPointer;
    78 
    80 typedef struct {
    84  unsigned char *data;
    85  unsigned int adifNameIndex;
    86  void *userPointer;
    87  int line_no;
    89 
    90 
    91 /* function prototypes */
    92 
    93 #ifdef __cplusplus
    94 extern "C" {
    95 #endif
    96 
    99 
    101 DLLEXPORT int CALLCONVENTION tqsl_beginADIF(tQSL_ADIF *adifp, const char *filename);
    102 
    120  const tqsl_adifFieldDefinitions *adifFields, const char * const *typesDefined,
    121  unsigned char *(*allocator)(size_t) );
    122 
    125 
    128 
    134 DLLEXPORT int CALLCONVENTION tqsl_adifMakeField(const char *fieldname, char type, const unsigned char *value, int len,
    135  unsigned char *buf, int buflen);
    136 
    137 #ifdef __cplusplus
    138 }
    139 #endif
    140 
    143 #endif /* __ADIF_H */
    void * tQSL_ADIF
    Opaque ADIF type.
    Definition: adif.h:42
    TQSL_ADIF_BOOLEAN
    Definition: adif.h:36
    DLLEXPORT int CALLCONVENTION tqsl_getADIFLine(tQSL_ADIF adif, int *lineno)
    DLLEXPORT int CALLCONVENTION tqsl_getADIFField(tQSL_ADIF adif, tqsl_adifFieldResults *field, TQSL_ADIF_GET_FIELD_ERROR *status, const tqsl_adifFieldDefinitions *adifFields, const char *const *typesDefined, unsigned char *(*allocator)(size_t))
    TQSL_ADIF_GET_FIELD_ERROR
    Response values returned from tqsl_getADIFField()
    Definition: adif.h:52
    #define TQSL_ADIF_FIELD_TYPE_LENGTH_MAX
    Max length of field type.
    Definition: adif.h:30
    DLLEXPORT int CALLCONVENTION tqsl_beginADIF(tQSL_ADIF *adifp, const char *filename)
    DLLEXPORT int CALLCONVENTION tqsl_endADIF(tQSL_ADIF *adifp)
    #define TQSL_ADIF_FIELD_SIZE_LENGTH_MAX
    Max length of field name.
    Definition: adif.h:29
    DLLEXPORT const char *CALLCONVENTION tqsl_adifGetError(TQSL_ADIF_GET_FIELD_ERROR status)
    TQSL_ADIF_RANGE_TYPE
    Specifies the type of range limits to apply to a field.
    Definition: adif.h:45
    #define TQSL_ADIF_FIELD_NAME_LENGTH_MAX
    Max length of ADIF field.
    Definition: adif.h:28
    DLLEXPORT int CALLCONVENTION tqsl_adifMakeField(const char *fieldname, char type, const unsigned char *value, int len, unsigned char *buf, int buflen)
    Definition: adif.h:68
    unsigned int max_length
    Max length.
    Definition: adif.h:72
    const char ** enumStrings
    Enumerated values.
    Definition: adif.h:75
    void * userPointer
    user poitner
    Definition: adif.h:76
    TQSL_ADIF_RANGE_TYPE rangeType
    Range type.
    Definition: adif.h:71
    long signed max_value
    Max value.
    Definition: adif.h:74
    long signed min_value
    Min value.
    Definition: adif.h:73
    Definition: adif.h:80
    int line_no
    Input line where the tag was found.
    Definition: adif.h:87
    void * userPointer
    User pointer.
    Definition: adif.h:86
    unsigned char * data
    data
    Definition: adif.h:84
    unsigned int adifNameIndex
    Name index.
    Definition: adif.h:85
    #define CALLCONVENTION
    Symbol exports - Windows only.
    Definition: tqsllib.h:27
    #define DLLEXPORT
    Symbol exports - Windows only.
    Definition: tqsllib.h:25
    tqsl-2.7.2/src/doxygen/html/adif_8h.html0000644000175000017500000003104514534122221020102 0ustar rmurphyrmurphy TrustedQSL Library API: adif.h File Reference
    TrustedQSL Library API
    adif.h File Reference
    #include "tqsllib.h"
    #include <stdio.h>
    #include <stdlib.h>

    Go to the source code of this file.

    Classes

    struct  tqsl_adifFieldDefinitions
     
    struct  tqsl_adifFieldResults
     

    Macros

    #define TQSL_ADIF_FIELD_NAME_LENGTH_MAX   64
     Max length of ADIF field.
     
    #define TQSL_ADIF_FIELD_SIZE_LENGTH_MAX   10
     Max length of field name.
     
    #define TQSL_ADIF_FIELD_TYPE_LENGTH_MAX   1
     Max length of field type.
     

    Typedefs

    typedef void * tQSL_ADIF
     Opaque ADIF type.
     

    Enumerations

    enum  TQSL_ADIF_BOOLEAN { TQSL_FALSE , TQSL_TRUE }
     
    enum  TQSL_ADIF_RANGE_TYPE { TQSL_ADIF_RANGE_TYPE_NONE , TQSL_ADIF_RANGE_TYPE_MINMAX , TQSL_ADIF_RANGE_TYPE_ENUMERATION }
     Specifies the type of range limits to apply to a field.
     
    enum  TQSL_ADIF_GET_FIELD_ERROR {
      TQSL_ADIF_GET_FIELD_SUCCESS , TQSL_ADIF_GET_FIELD_NO_NAME_MATCH , TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH , TQSL_ADIF_GET_FIELD_NO_RANGE_MATCH ,
      TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH , TQSL_ADIF_GET_FIELD_NO_RESULT_ALLOCATION , TQSL_ADIF_GET_FIELD_NAME_LENGTH_OVERFLOW , TQSL_ADIF_GET_FIELD_DATA_LENGTH_OVERFLOW ,
      TQSL_ADIF_GET_FIELD_SIZE_OVERFLOW , TQSL_ADIF_GET_FIELD_TYPE_OVERFLOW , TQSL_ADIF_GET_FIELD_ERRONEOUS_STATE , TQSL_ADIF_GET_FIELD_EOF
    }
     Response values returned from tqsl_getADIFField()
     

    Functions

    DLLEXPORT const char *CALLCONVENTION tqsl_adifGetError (TQSL_ADIF_GET_FIELD_ERROR status)
     
    DLLEXPORT int CALLCONVENTION tqsl_beginADIF (tQSL_ADIF *adifp, const char *filename)
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFField (tQSL_ADIF adif, tqsl_adifFieldResults *field, TQSL_ADIF_GET_FIELD_ERROR *status, const tqsl_adifFieldDefinitions *adifFields, const char *const *typesDefined, unsigned char *(*allocator)(size_t))
     
    DLLEXPORT int CALLCONVENTION tqsl_getADIFLine (tQSL_ADIF adif, int *lineno)
     
    DLLEXPORT int CALLCONVENTION tqsl_endADIF (tQSL_ADIF *adifp)
     
    DLLEXPORT int CALLCONVENTION tqsl_adifMakeField (const char *fieldname, char type, const unsigned char *value, int len, unsigned char *buf, int buflen)
     
    tqsl-2.7.2/src/doxygen/html/.gitignore0000644000175000017500000000001714534122221017675 0ustar rmurphyrmurphy._* #osx cruft tqsl-2.7.2/src/converter.cpp0000644000175000017500000000665314534122221016013 0ustar rmurphyrmurphy/*************************************************************************** converter.cpp - c++ example program for signing a log ------------------- begin : Sun Dec 15 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "sysconfig.h" #endif #include #include #include #include #ifdef HAVE_GETOPT_H #include #endif #include "tqsllib.h" #include "tqslerrno.h" #include "tqslconvert.h" #include "tqslexc.h" using std::cerr; using std::endl; using std::ofstream; int usage() { cerr << "Usage: converter [-ac] station-location infile [outfile]\n"; exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { enum { UNKNOWN, CABRILLO, ADIF } type = UNKNOWN; int opt; while ((opt = getopt(argc, argv, "ca")) != -1) { switch (opt) { case 'c': type = CABRILLO; break; case 'a': type = ADIF; break; default: usage(); } } if (argc - optind < 2) usage(); tQSL_Converter conv = 0; try { if (tqsl_init()) throw tqslexc(); // Get the specified station location data tQSL_Location loc; if (tqsl_getStationLocation(&loc, argv[optind++])) throw tqslexc(); // Get the callsign and DXCC entity to use char call[256]; int dxcc; if (tqsl_getLocationCallSign(loc, call, sizeof call)) throw tqslexc(); if (tqsl_getLocationDXCCEntity(loc, &dxcc)) throw tqslexc(); // Get a list of available signing certificates tQSL_Cert *certs; int ncerts; if (tqsl_selectCertificates(&certs, &ncerts, call, dxcc, 0, 0, 1)) throw tqslexc(); if (ncerts < 1) throw myexc(string("No certificates available for ") + call); int stat = 1; if (type == UNKNOWN || type == CABRILLO) { if ((stat = tqsl_beginCabrilloConverter(&conv, argv[optind], certs, ncerts, loc)) != 0 && type == CABRILLO) throw tqslexc(); } if (stat) { if (tqsl_beginADIFConverter(&conv, argv[optind], certs, ncerts, loc)) throw tqslexc(); } tqsl_setConverterAllowDuplicates(conv, false); optind++; const char *ofile = (optind < argc) ? argv[optind] : "converted.tq7"; ofstream out; out.open(ofile, std::ios::out|std::ios::trunc|std::ios::binary); if (!out.is_open()) throw myexc(string("Unable to open ") + ofile); bool haveout = false; do { const char *gabbi = tqsl_getConverterGABBI(conv); if (gabbi) { haveout = true; out << gabbi; continue; } if (tQSL_Error == TQSL_SIGNINIT_ERROR) { tQSL_Cert cert; if (tqsl_getConverterCert(conv, &cert)) throw tqslexc(); if (tqsl_beginSigning(cert, 0, 0, 0)) throw tqslexc(); continue; } if (tQSL_Error == TQSL_DUPLICATE_QSO) continue; break; } while (1); out.close(); if (tQSL_Error != TQSL_NO_ERROR) throw tqslexc(); else if (!haveout) cerr << "Empty log file" << endl; } catch(exception& x) { char buf[40] = ""; int lineno; if (conv && !tqsl_getConverterLine(conv, &lineno)) // && lineno > 0) snprintf(buf, sizeof buf, " on line %d", lineno); cerr << "Aborted: " << x.what() << buf << endl; tqsl_converterRollBack(conv); return EXIT_FAILURE; } tqsl_converterCommit(conv); return EXIT_SUCCESS; } tqsl-2.7.2/src/converter.c0000644000175000017500000000640614534122221015447 0ustar rmurphyrmurphy/*************************************************************************** converter.c - "C" example program for signing a log ------------------- begin : Sun Dec 15 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #include #include #include #include #include #include #include "tqsllib.h" #include "tqslerrno.h" #include "tqslconvert.h" int usage() { fprintf(stderr, "Usage: converter [-ac] station-location infile [outfile]\n"); exit(EXIT_FAILURE); } void fail(tQSL_Converter conv) { char buf[40]; const char *err = tqsl_getErrorString(); int lineno; buf[0] = '\0'; if (conv && !tqsl_getConverterLine(conv, &lineno)) // && lineno > 0) sprintf(buf, " on line %d", lineno); fprintf(stderr, "Aborted: %s%s\n", err, buf); if (conv) tqsl_converterRollBack(conv); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { enum { UNKNOWN, CABRILLO, ADIF } type = UNKNOWN; int opt; tQSL_Location loc; tQSL_Converter conv = 0; int stat = 1; char call[256]; int dxcc; tQSL_Cert *certs; int ncerts; int haveout = 0; const char *ofile; int out; while ((opt = getopt(argc, argv, "ca")) != -1) { switch (opt) { case 'c': type = CABRILLO; break; case 'a': type = ADIF; break; default: usage(); } } if (argc - optind < 2) usage(); if (tqsl_init()) fail(conv); // Get the specified station location data if (tqsl_getStationLocation(&loc, argv[optind++])) fail(conv); // Get the callsign and DXCC entity to use if (tqsl_getLocationCallSign(loc, call, sizeof call)) fail(conv); if (tqsl_getLocationDXCCEntity(loc, &dxcc)) fail(conv); // Get a list of available signing certificates if (tqsl_selectCertificates(&certs, &ncerts, call, dxcc, 0, 0, 1)) fail(conv); if (ncerts < 1) { fprintf(stderr, "No certificates available for %s\n", call); exit (EXIT_FAILURE); } if (type == UNKNOWN || type == CABRILLO) { if ((stat = tqsl_beginCabrilloConverter(&conv, argv[optind], certs, ncerts, loc)) != 0 && type == CABRILLO) fail(conv); } if (stat) { if (tqsl_beginADIFConverter(&conv, argv[optind], certs, ncerts, loc)) fail(conv); } tqsl_setConverterAllowDuplicates(conv, 0); optind++; ofile = (optind < argc) ? argv[optind] : "converted.tq8"; out = creat(ofile, 0660); if (out < 0) { fprintf(stderr, "Unable to open %s\n", ofile); exit (EXIT_FAILURE); } tqsl_setConverterAppName(conv, "converter-sample"); do { const char *gabbi = tqsl_getConverterGABBI(conv); if (gabbi) { haveout = 1; write(out, gabbi, strlen(gabbi)); continue; } if (tQSL_Error == TQSL_SIGNINIT_ERROR) { tQSL_Cert cert; if (tqsl_getConverterCert(conv, &cert)) fail(conv); if (tqsl_beginSigning(cert, 0, 0, 0)) fail(conv); continue; } if (tQSL_Error == TQSL_DUPLICATE_QSO) continue; break; } while (1); close(out); if (tQSL_Error != TQSL_NO_ERROR) fail(conv); else if (!haveout) fprintf(stderr, "Empty log file\n"); tqsl_converterCommit(conv); return EXIT_SUCCESS; } tqsl-2.7.2/src/config.xml0000644000175000017500000164730514534122221015275 0ustar rmurphyrmurphy AM ARDOP ATV C4FM CHIP128 CHIP64 CHIP CLO CONTESTI PCW CW DIGITALVOICE DOMINOEX DOMINOF DOMINO DSTAR FAX FM FSK441 FT8 FMHELL FSKHELL HELL80 HFSK PSKHELL HELL ISCAT-A ISCAT-B ISCAT JT4A JT4B JT4C JT4D JT4E JT4F JT4G JT4 JT65A JT65B JT65B2 JT65C JT65C2 JT65 JT6M JT9-1 JT9-10 JT9-2 JT9-30 JT9-5 JT9A JT9B JT9C JT9D JT9E JT9E FAST JT9F JT9F FAST JT9G JT9G FAST JT9H JT9H FAST JT9 FSQCALL FST4 FT4 JS8 MFSK11 MFSK128 MFSK16 MFSK22 MFSK31 MFSK32 MFSK4 MFSK64 MFSK8 Q65 MFSK MSK144 MT63 OLIVIA 16/1000 OLIVIA 16/500 OLIVIA 32/1000 OLIVIA 4/125 OLIVIA 4/250 OLIVIA 8/250 OLIVIA 8/500 OLIVIA OPERA-BEACON OPERA-QSO OPERA PAC2 PAC3 PAC4 PAC PAX2 PAX PKT BPSK125 BPSK31 BPSK63 FSK31 PSK10 PSK1000 PSK125 PSK250 PSK31 PSK500 PSK63 PSK63F PSKAM10 PSKAM31 PSKAM50 PSKFEC31 QPSK125 QPSK250 QPSK31 QPSK500 QPSK63 SIM31 PSK PSK2K Q15 QRA64A QRA64B QRA64C QRA64D QRA64E QRA64 ROS-EME ROS-HF ROS-MF ROS ASCI RTTY RTTYM LSB USB SSB SSTV T10 THOR THRBX THRB AMTORFEC GTOR TOR V4 VOI WINMOR WSPR 1.25CM 1.25M 10M 12M 13CM 15M 160M 17M 1MM 2.5MM 20M 2190M 23CM 2M 2MM 30M 33CM 3CM 40M 4M 4MM 60M 630M 6CM 6M 6MM 70CM 80M 9CM SUBMM 7QP AADX-CW AADX-SSB AP-SPRINT ARI-DX ARRL-10 ARRL-160 ARRL-DX-CW ARRL-DX-SSB ARRL-RTTY ARRL-SCR ARRL-SS-CW ARRL-SS-SSB ARRL-UHF-AUG ARRL-VHF-JAN ARRL-VHF-JUN ARRL-VHF-SEP AZQP BARTG-RTTY BARTG-SPRINT CQ-160-CW CQ-160-SSB CQ-M CQ-VHF CQ-WPX-CW CQ-WPX-RTTY CQ-WPX-SSB CQ-WW-CW CQ-WW-RTTY CQ-WW-SSB CW-Ops CWOPS-Open DARC-WAEDC-CW DARC-WAEDC-RTTY DARC-WAEDC-SSB DE_QSO-PARTY EU Sprint EU-HF EUHFC FCG-FQP FL-QSO-PARTY HELVETIA IARU-HF IL QSO Party IN QSO Party IN-QSO-PARTY JARTS-WW_RTTY JIDX-CW JIDX-SSB MI-QSO-PARTY MRRC-OhQP NA-SPRINT-CW NA-SPRINT-SSB NAQP-CW NAQP-RTTY NAQP-SSB NCCC-CQP NEQP NRAU-BALTIC-CW NRAU-BALTIC-SSB NY-QSO-PARTY OCEANIA-DX-CW OCEANIA-DX-SSB OK-OM-DX PACC RAC CANADA DAY RAC CANADA WINTER RADIO-WW-RTTY RAEM RDAC RDXC REF-160M REF-CW REF-SSB RSGB-160 RSGB-21/28 RSGB-80M-CC RSGB-80M-SPRINT RSGB-AFS-CW RSGB-AFS-SSB RSGB-CLUB-CALLS RSGB-COMMONWEALTH RSGB-IOTA RSGB-LOW-POWER RSGB-NFD RSGB-ROPOCO RSGB-SSB-FD SAC-CW SAC-SSB SARTG-RTTY SC-QSO-PARTY SCC RTTY SP-DX-RTTY SPDXContest STEW-PERRY State QSO Party - GA TARA-RTTY TMC-RTTY UBA-DX-CW UBA-DX-SSB VA-QSO-PARTY VOLTA-RTTY Virginia QSO Party Wisconsin QSO Party XE-RTTY -NONE- CANADA ABU AIL ISLANDS (DELETED) AFGHANISTAN AGALEGA & SAINT BRANDON ISLANDS ALAND ISLANDS ALASKA ALBANIA ALDABRA (DELETED) AMERICAN SAMOA AMSTERDAM & SAINT PAUL ISLANDS ANDAMAN & NICOBAR ISLANDS ANGUILLA ANTARCTICA ARMENIA ASIATIC RUSSIA NEW ZEALAND SUBANTARCTIC ISLANDS AVES ISLAND AZERBAIJAN BAJO NUEVO (DELETED) BAKER & HOWLAND ISLANDS BALEARIC ISLANDS PALAU BLENHEIM REEF (DELETED) BOUVET ISLAND BRITISH NORTH BORNEO (DELETED) BRITISH SOMALILAND (DELETED) BELARUS CANAL ZONE (DELETED) CANARY ISLANDS CELEBES & MOLUCCA ISLANDS (DELETED) CENTRAL KIRIBATI CEUTA & MELILLA CHAGOS ISLANDS CHATHAM ISLAND CHRISTMAS ISLAND CLIPPERTON ISLAND COCOS ISLAND COCOS (KEELING) ISLANDS COMORO ISLANDS (DELETED) CRETE CROZET ISLAND DAMAO, DIU (DELETED) DESECHEO ISLAND DESROCHES (DELETED) DODECANESE EAST MALAYSIA EASTER ISLAND EASTERN KIRIBATI EQUATORIAL GUINEA MEXICO ERITREA ESTONIA ETHIOPIA EUROPEAN RUSSIA FARQUHAR (DELETED) FERNANDO DE NORONHA FRENCH EQUATORIAL AFRICA (DELETED) FRENCH INDO-CHINA (DELETED) FRENCH WEST AFRICA (DELETED) BAHAMAS FRANZ JOSEF LAND BARBADOS FRENCH GUIANA BERMUDA BRITISH VIRGIN ISLANDS BELIZE FRENCH INDIA (DELETED) KUWAIT/SAUDI ARABIA NEUTRAL ZONE (DELETED) CAYMAN ISLANDS CUBA GALAPAGOS ISLANDS DOMINICAN REPUBLIC EL SALVADOR GEORGIA GUATEMALA GRENADA HAITI GUADELOUPE HONDURAS GERMANY (DELETED) JAMAICA MARTINIQUE BONAIRE,CURACAO (NETH ANTILLES) (DELETED) NICARAGUA PANAMA TURKS & CAICOS ISLANDS TRINIDAD & TOBAGO ARUBA GEYSER REEF (DELETED) ANTIGUA & BARBUDA DOMINICA MONTSERRAT SAINT LUCIA SAINT VINCENT GLORIOSO ISLAND ARGENTINA GOA (DELETED) GOLD COAST TOGOLAND (DELETED) GUAM BOLIVIA GUANTANAMO BAY GUERNSEY GUINEA BRAZIL GUINEA-BISSAU HAWAII HEARD ISLAND CHILE IFNI (DELETED) ISLE OF MAN ITALIAN SOMALILAND (DELETED) COLOMBIA ITU HQ JAN MAYEN JAVA (DELETED) ECUADOR JERSEY JOHNSTON ISLAND JUAN DE NOVA, EUROPA JUAN FERNANDEZ ISLAND KALININGRAD KAMARAN ISLANDS (DELETED) KARELO-FINNISH REP (DELETED) GUYANA KAZAKHSTAN KERGUELEN ISLAND PARAGUAY KERMADEC ISLAND KINGMAN REEF (DELETED) KYRGYZSTAN PERU REPUBLIC OF KOREA KURE ISLAND KURIA MURIA ISLAND (DELETED) SURINAME FALKLAND ISLANDS LAKSHADWEEP ISLANDS LAOS URUGUAY LATVIA LITHUANIA LORD HOWE ISLAND VENEZUELA AZORES AUSTRALIA MALYJ VYSOTSKIJ ISLAND (DELETED) MACAO MACQUARIE ISLAND YEMEN ARAB REPUBLIC (DELETED) MALAYA (DELETED) NAURU VANUATU MALDIVES TONGA MALPELO ISLAND NEW CALEDONIA PAPUA NEW GUINEA MANCHURIA (DELETED) MAURITIUS ISLAND MARIANA ISLANDS MARKET REEF MARSHALL ISLANDS MAYOTTE ISLAND NEW ZEALAND MELLISH REEF PITCAIRN ISLAND MICRONESIA MIDWAY ISLAND FRENCH POLYNESIA FIJI ISLANDS MINAMI TORISHIMA MINERVA REEF (DELETED) MOLDOVA MOUNT ATHOS MOZAMBIQUE NAVASSA ISLAND NETHERLANDS BORNEO (DELETED) NETHERLANDS N GUINEA (DELETED) SOLOMON ISLANDS NEWFOUNDLAND LABRADOR (DELETED) NIGER NIUE NORFOLK ISLAND SAMOA NORTH COOK ISLANDS OGASAWARA OKINAWA (DELETED) OKINO TORI-SHIMA (DELETED) ANNOBON PALESTINE (DELETED) PALMYRA & JARVIS ISLANDS PAPUA TERRITORY (DELETED) PETER 1 ISLAND PORTUGUESE TIMOR (DELETED) PRINCE EDWARD & MARION ISLANDS PUERTO RICO ANDORRA REVILLAGIGEDO ASCENSION ISLAND AUSTRIA RODRIGUEZ ISLAND RUANDA-URUNDI (DELETED) BELGIUM SAAR (DELETED) SABLE ISLAND BULGARIA SAINT MARTIN CORSICA CYPRUS SAN ANDRES ISLAND SAN FELIX ISLAND CZECHOSLOVAKIA (DELETED) SAO TOME & PRINCIPE SARAWAK (DELETED) DENMARK FAROE ISLANDS ENGLAND FINLAND SARDINIA SAUDI ARABIA/IRAQ NEUTRAL ZONE (DELETED) FRANCE SERRANA BANK & RONCADOR CAY (DELETED) GERMAN DEMOCRATIC REPUBLIC (DELETED) FEDERAL REPUBLIC OF GERMANY SIKKIM (DELETED) SOMALIA GIBRALTAR SOUTH COOK ISLANDS SOUTH GEORGIA ISLAND GREECE GREENLAND SOUTH ORKNEY ISLANDS HUNGARY SOUTH SANDWICH ISLANDS SOUTH SHETLAND ISLANDS ICELAND PEOPLE'S DEM REP OF YEMEN (DELETED) SOUTHERN SUDAN (DELETED) IRELAND SOVEREIGN MILITARY ORDER OF MALTA SPRATLY ISLANDS ITALY SAINT KITTS & NEVIS SAINT HELENA LIECHTENSTEIN SAINT PAUL ISLAND SAINT PETER AND PAUL ROCKS LUXEMBOURG SINT MAARTEN, SABA, SAINT EUSTATIUS (DELETED) MADEIRA ISLANDS MALTA SUMATRA (DELETED) SVALBARD MONACO SWAN ISLAND (DELETED) TAJIKISTAN NETHERLANDS TANGIER (DELETED) NORTHERN IRELAND NORWAY TERRITORY OF NEW GUINEA (DELETED) TIBET (DELETED) POLAND TOKELAU ISLANDS TRIESTE (DELETED) PORTUGAL TRINDADE & MARTIM VAZ ISLANDS TRISTAN DA CUNHA & GOUGH ISLANDS ROMANIA TROMELIN ISLAND SAINT PIERRE & MIQUELON SAN MARINO SCOTLAND TURKMENISTAN SPAIN TUVALU U K BASES ON CYPRUS SWEDEN US VIRGIN ISLANDS UGANDA SWITZERLAND UKRAINE UNITED NATIONS HQ UNITED STATES OF AMERICA UZBEKISTAN VIET NAM WALES VATICAN CITY SERBIA WAKE ISLAND WALLIS & FUTUNA ISLANDS WEST MALAYSIA WESTERN KIRIBATI WESTERN SAHARA WILLIS ISLAND BAHRAIN BANGLADESH BHUTAN ZANZIBAR (DELETED) COSTA RICA MYANMAR CAMBODIA SRI LANKA CHINA HONG KONG INDIA INDONESIA IRAN IRAQ ISRAEL JAPAN JORDAN DPRK (NORTH KOREA) BRUNEI KUWAIT LEBANON MONGOLIA NEPAL OMAN PAKISTAN PHILIPPINES QATAR SAUDI ARABIA SEYCHELLES ISLANDS SINGAPORE DJIBOUTI SYRIA TAIWAN THAILAND TURKEY UNITED ARAB EMIRATES ALGERIA ANGOLA BOTSWANA BURUNDI CAMEROON CENTRAL AFRICAN REPUBLIC CAPE VERDE CHAD COMOROS REPUBLIC OF THE CONGO DEMOCRATIC REPUBLIC OF THE CONGO BENIN GABON THE GAMBIA GHANA COTE D'IVOIRE KENYA LESOTHO LIBERIA LIBYA MADAGASCAR MALAWI MALI MAURITANIA MOROCCO NIGERIA ZIMBABWE REUNION ISLAND RWANDA SENEGAL SIERRA LEONE ROTUMA REPUBLIC OF SOUTH AFRICA NAMIBIA SUDAN KINGDOM OF ESWATINI TANZANIA TUNISIA EGYPT BURKINA FASO ZAMBIA TOGO WALVIS BAY (DELETED) CONWAY REEF BANABA ISLAND YEMEN PENGUIN ISLANDS (DELETED) CROATIA SLOVENIA BOSNIA-HERZEGOVINA NORTH MACEDONIA CZECH REPUBLIC SLOVAK REPUBLIC PRATAS ISLAND SCARBOROUGH REEF TEMOTU PROVINCE AUSTRAL ISLANDS MARQUESAS ISLANDS PALESTINE TIMOR - LESTE CHESTERFIELD ISLANDS DUCIE ISLAND MONTENEGRO SWAINS ISLAND SAINT BARTHELEMY CURACAO SINT MAARTEN SABA & SAINT EUSTATIUS BONAIRE REPUBLIC OF SOUTH SUDAN REPUBLIC OF KOSOVO Australian Capital Territory New South Wales Victoria Queensland South Australia Western Australia Tasmania Northern Territory Alberta British Columbia Manitoba New Brunswick Newfoundland and Labrador Northwest Territories Nova Scotia Nunavut Ontario Prince Edward Island Quebec Saskatchewan Yukon Territory International Peace Garden Roosevelt Campobello International Park Anhui Beijing Chongqing Fujian Guangdong Gansu Guangxi Guizhou Henan Hubei Hebei Hainan Heilongjiang Hunan Jilin Jiangsu Jiangxi Liaoning Nei Mongol Ningxia Qinghai Sichuan Shandong Shanghai Shaanxi Shanxi Tianjin Xinjiang Xizang Yunnan Zhejiang Africa Asia Antarctica Europe North America Oceania South America War in the Pacific National Historical Park American Memorial Park San Juan National Historic Site Buck Island Reef National Monument Christiansted National Historic Site Christiansted NHS + Buck Island Reef NM Salt River Bay NHP and Ecological Preserve National Historical Park Virgin Islands National Park Virgin Islands Coral Reef National Monument Virgin Islands NP + Virgin Islands Coral Reef National Park of American Samoa Hammarland Somero Ahlainen Alastaro Askainen (Villnäs) Aura Dragsfjärd Eura Eurajoki Halikko Harjavalta Honkajoki Houtskari (Houtskär) Huittinen Hämeenkyrö Ikaalinen Iniö Jämijärvi Kaarina (St. Karins) Kalanti Kankaanpää Karinainen Karjala Karvia Äetsä (Keikyä) Kemiönsaari (Kemiö) Kihniö Kiikala Kiikka Kiikoinen Kisko Kiukainen Kodisjoki Kokemäki (Kumo) Korppoo (Korpo) Koski tl Kullaa Kustavi (Gustavs) Kuusjoki Köyliö (Kjulo) Laitila Lappi Lavia Lemu Lieto Loimaa Loimaan kunta (Loimaan mlk) Lokalahti Luvia Marttila Masku Mellilä Merikarvia Merimasku Metsämaa Mietoinen Mouhijärvi Muurla Mynämäki Naantali (Nådendal) Nakkila Nauvo (Nagu) Noormarkku (Norrmark) Nousiainen Oripää Paimio (Permar) Parainen (Pargas) Parkano Perniö (Bjärnå) Pertteli Piikkiö (Pikis) Pomarkku (Påmark) Pori (Björneborg) Punkalaidun Pyhäranta Pöytyä Raisio (Reso) Rauma (Raumo) Rauman mlk (Raumo lk) Rusko Rymättylä (Rimito) Salo Sauvo Siikainen Suodenniemi Suomusjärvi Säkylä Särkisalo Taivassalo Tarvasjoki Turku (Åbo) Ulvila Uusikaupunki (Nystad) Vahto Sastamala (Vammala) Vampula Vehmaa Velkua Viljakkala Västanfjärd Yläne Artjärvi (Artsjö) Askola Bromarv Espoo (Esbo) Hanko (Hangö) Helsinki (Helsingfors) Hyvinkää (Hyvinge) Inkoo (Ingå) Järvenpää Karjaa (Karis) Karjalohja (Karislojo) Karkkila Kauniainen (Grankulla) Kerava (Kervo) Kirkkonummi (Kyrkslätt) Lapinjärvi (Lappträsk) Liljendal Lohja (Lojo) Lohjan kunta (Lohjan mlk) Loviisa (Lovisa) Myrskylä (Mörskom) Mäntsälä Nummi-Pusula (Nummi) Nurmijärvi Orimattila Pernaja (Perna) Pohja (Pojo) Pornainen (Borgnäs) Porvoo (Borgå) Porvoon mlk (Borgå lk) Pukkila Pusula Ruotsinpyhtää (Strömfors) Sammatti Sipoo (Sibbo) Siuntio (Sjundeå) Snappertuna Tammisaari (Ekenäs) Tammisaaren mlk (Ekenäs lk) Tenhola (Tenala) Tuusula (Tusby) Vantaa (Vanda) Vihti Raasepori Asikkala Eräjärvi Forssa Hattula Hauho Hausjärvi Hollola Humppila Hämeenlinna (Tavastehus) Janakkala Jokioinen Juupajoki Kalvola Kangasala Hämeenkoski (Koski hl) Kuhmalahti Kuorevesi Kuru Kylmäkoski Kärkölä Lahti Lammi Lempäälä Loppi Luopioinen Längelmäki Mänttä Nastola Nokia Orivesi Padasjoki Pirkkala Pälkäne Renko Riihimäki Ruovesi Sahalahti Somerniemi Somero Tammela Tampere (Tammerfors) Toijala Tottijärvi Tuulos Urjala Valkeakoski Vesilahti Viiala Vilppula Virrat Ylöjärvi Ypäjä Hämeenkyrö (Tavastkyro) Ikaalinen Kihniö Mouhijärvi Parkano Viljakkala Akaa Mänttä-Vilppula Anttola Enonkoski Hartola Haukivuori Heinola Heinolan mlk (Heinola lk) Heinävesi Hirvensalmi Joroinen Juva Jäppilä Kangaslampi Kangasniemi Kerimäki Mikkeli (St. Michel) Mikkelin mlk (St. Michel's lk) Mäntyharju Pertunmaa Pieksämäki Pieksänmaa (Pieksämäen mlk) Punkaharju Puumala Rantasalmi Ristiina Savonlinna (Nyslott) Savonranta Sulkava Sysmä Virtasalmi Anjala Elimäki Hamina (Fredrikshamn) Iitti Imatra Jaala Joutseno Karhula Kotka Kouvola Kuusankoski Kymi (Kymmene) Lappeenranta (Villmanstrand) Lemi Luumäki Miehikkälä Nuijamaa Parikkala Pyhtää (Pyttis) Rautjärvi Ruokolahti Saari Savitaipale Sippola Suomenniemi Taipalsaari Uudenkaarlepyyn mlk (Nykarleby lk) Valkeala Vehkalahti Virolahti Ylämaa Anjalankoski Alahärmä Alajärvi Alavus (Alavo) Evijärvi Halsua Hankasalmi Himanka Ilmajoki Isojoki (Stora) Isokyrö (Storkyro) Jalasjärvi Joutsa Jurva Jyväskylä Jyväskylän mlk (Jyväskylä lk) Jämsä Jämsänkoski Kaarlela (Karleby) Kannonkoski Kannus Karijoki (Bötom) Karstula Kaskinen (Kasköo) Kauhajoki Kauhava Kaustinen (Kaustby) Keuruu Kinnula Kivijärvi Kokkola (Gamlakarleby) Konginkangas Konnevesi Korpilahti Korsnäs Kortesjärvi Kristiinankaupunki (Kristinestad) Kruunupyy (Kronoby) Kuhmoinen Kuortane Kurikka Kyyjärvi Kälviä Laihia Lappajärvi Lapua (Lappo) Laukaa Lehtimäki Leivonmäki Lestijärvi Lohtaja Luhanka Luoto (Larsmo) Maalahti (Malax) Maksamaa (Maxmo) Multia Mustasaari (Korsholm) Muurame Nurmo Närpiö (Närpes) Oravainen (Gravais) Perho Peräseinäjoki Petäjävesi Pietarsaari (Jakobstad) Pedersöre (Pietarsaaren mlk) Pihtipudas Purmo Pylkönmäki Saarijärvi Seinäjoki Soini Sumiainen Suolahti Säynätsalo Teuva (Östermark) Toholampi Toivakka Töysä Ullava Uurainen Uusikaarlepyy (Nykarleby) Vaasa (Vasa) Veteli (Vetil) Viitasaari Vimpeli (Vindala) Vähäkyrö (Lillkyro) Vöyri (Vörå) Ylihärmä Ylistaro Ähtäri Ähtävä (Esse) Äänekoski Jepua (Jeppo) Munsala Uudenkaarlepyyn mlk Vöyri-Maksamaa (Vörå-Maxmo) Eno Iisalmi Ilomantsi Joensuu Juankoski Juuka Kaavi Karttula Keitele Kesälahti Kiihtelysvaara Kitee Kiuruvesi Kontiolahti Kuopio Lapinlahti Leppävirta Lieksa Liperi Maaninka Nilsiä Nurmes Outokumpu Pielavesi Polvijärvi Pyhäselkä Rautalampi Rautavaara Rääkkylä Siilinjärvi Sonkajärvi Suonenjoki Tervo Tohmajärvi Tuupovaara Tuusniemi Valtimo Varkaus Varpaisjärvi Vehmersalmi Vesanto Vieremä Värtsilä Alavieska Haapajärvi Haapavesi Hailuoto (Karlö) Haukipudas Hyrynsalmi Ii Kajaani Kajaanin mlk (Kajaani lk) Kalajoki Kempele Kestilä Kiiminki Kuhmo Kuivaniemi Kuusamo Kärsämäki Liminka Lumijoki Merijärvi Muhos Nivala Oulainen Oulu (Uleåborg) Oulunsalo Paltamo Pattijoki Piippola Pudasjärvi Pulkkila Puolanka Pyhäjoki Pyhäjärvi Pyhäntä Raahe (Brahestad) Rantsila Reisjärvi Ristijärvi Ruukki Sievi Siikajoki Sotkamo Suomussalmi Taivalkoski Temmes Tyrnävä Utajärvi Vaala Vihanti Vuolijoki Yli-Ii Ylikiiminki Ylivieska Siikalatva Enontekiö Inari (Enare) Kemi Keminmaa (Kemin mlk) Kemijärvi Kemijärven mlk Kittilä Kolari Muonio Pelkosenniemi Pello Posio Ranua Rovaniemi Rovaniemen mlk (Rovaniemi lk) Salla Savukoski Simo Sodankylä Tervola Tornio (Torneå) Utsjoki Ylitornio (Övertorneå) Brändö Eckerö Finström Föglö Geta Hammarland Jomala Kumlinge Kökar Lemland Lumparland Maarianhamina (Mariehamn) Saltvik Sottunga Sund Vårdö Märket Reef Sapporo-shi Asahikawa-shi Otaru-shi Hakodate-shi Muroran-shi Kushiro-shi Obihiro-shi Kitami-shi Yubari-shi Iwamizawa-shi Abashiri-shi Rumoi-shi Tomakomai-shi Wakkanai-shi Bibai-shi Ashibetsu-shi Ebetsu-shi Akabira-shi Mombetsu-shi Shibetsu-shi Nayoro-shi Mikasa-shi Nemuro-shi Chitose-shi Takikawa-shi Sunagawa-shi Utashinai-shi Fukagawa-shi Furano-shi Noboribetsu-shi Eniwa-shi Kameda-shi Date-shi Kitahiroshima-shi Ishikari-shi Hokuto-shi Akan-gun Ashoro-gun Atsukeshi-gun Atsuta-gun Abashiri-gun Abuta-gun (Shiribeshi) Abuta-gun (Iburi) Ishikari-gun Isoya-gun Iwanai-gun Usu-gun Utasutsu-gun Urakawa-gun Uryu-gun (Sorachi) Esashi-gun Okushiri-gun Oshoro-gun Kasai-gun Kato-gun Kabato-gun Kamiiso-gun Kamikawa-gun (Tokachi) Kamikawa-gun (Kamikawa) Kameda-gun Kayabe-gun Kawakami-gun Kushiro-gun Kudo-gun Sapporo-gun Samani-gun Saru-gun Shizunai-gun Shibetsu-gun Shimamaki-gun Shakotan-gun Shari-gun Shiraoi-gun Shiranuka-gun Suttsu-gun Setana-gun Soya-gun Sorachi-gun (Sorachi) Sorachi-gun (Kamikawa) Chitose-gun Teshio-gun (Rumoi) Teshio-gun (Soya) Tokachi-gun Tokoro-gun Tomamae-gun Nakagawa-gun (Kamikawa) Nakagawa-gun (Tokachi) Niikappu-gun Nishi-gun Nemuro-gun Notsuke-gun Hanasaki-gun Hamamasu-gun Bikuni-gun Hiyama-gun Hiroo-gun Futoro-gun Furuu-gun Furubira-gun Horoizumi-gun Horobetsu-gun Mashike-gun Matsumae-gun Mitsuishi-gun Menashi-gun Mombetsu-gun Yamakoshi-gun Yubari-gun Yufutsu-gun (Iburi) Yufutsu-gun (Kamikawa) Yoichi-gun Rishiri-gun Rumoi-gun Rebun-gun Futami-gun Hidaka-gun Uryu-gun (Kamikawa) Chuo-ku Kita-ku Higashi-ku Shiroishi-ku Toyohira-ku Minami-ku Nishi-ku Atsubetsu-ku Teine-ku Kiyota-ku Aomori-shi Hirosaki-shi Hachinohe-shi Kuroishi-shi Goshogawara-shi Towada-shi Misawa-shi Mutsu-shi Tsugaru-shi Hirakawa-shi Kamikita-gun Kitatsugaru-gun Sannohe-gun Shimokita-gun Nakatsugaru-gun Nishitsugaru-gun Higashitsugaru-gun Minamitsugaru-gun Morioka-shi Kamaishi-shi Miyako-shi Ichinoseki-shi Ofunato-shi Mizusawa-shi Hanamaki-shi Kitakami-shi Kuji-shi Tono-shi Rikuzentakata-shi Esashi-shi Ninohe-shi Hachimantai-shi Oshu-shi Takizawa-shi Isawa-gun Iwate-gun Esashi-gun Kamihei-gun Kunohe-gun Kesen-gun Shimohei-gun Shiwa-gun Nishiiwai-gun Ninohe-gun Hienuki-gun Higashiiwai-gun Waga-gun Akita-shi Noshiro-shi Odate-shi Yokote-shi Honjo-shi Oga-shi Yuzawa-shi Omagari-shi Kazuno-shi Yurihonjo-shi Katagami-shi Daisen-shi Kitaakita-shi Nikaho-shi Senboku-shi Ogachi-gun Kaduno-gun Kawabe-gun Kitaakita-gun Semboku-gun Hiraka-gun Minamiakita-gun Yamamoto-gun Yuri-gun Yamagata-shi Yonezawa-shi Tsuruoka-shi Sakata-shi Shinjo-shi Sagae-shi Kaminoyama-shi Murayama-shi Nagai-shi Tendo-shi Higashine-shi Obanazawa-shi Nan01yo-shi Akumi-gun Kitamurayama-gun Nishiokitama-gun Nishitagawa-gun Nishimurayama-gun Higashiokitama-gun Higashitagawa-gun Higashimurayama-gun Minamiokitama-gun Minamimurayama-gun Mogami-gun Sendai-shi Ishinomaki-shi Shiogama-shi Furukawa-shi Kesennuma-shi Shiroishi-shi Natori-shi Kakuda-shi Tagajo-shi Izumi-shi Iwanuma-shi Tome-shi Kuruhara-shi Higashimatsushima-shi Osaki-shi Igu-gun Oshika-gun Katta-gun Kami-gun Kurihara-gun Kurokawa-gun Shida-gun Shibata-gun Tamadukuri-gun Toda-gun Tome-gun Natori-gun Miyagi-gun Motoyoshi-gun Monou-gun Watari-gun Aoba-ku Miyagino-ku Wakabayashi-ku Taihaku-ku Izumi-ku Fukushima-shi Aizuwakamatsu-shi Koriyama-shi Taira-shi Shirakawa-shi Haramachi-shi Sukagawa-shi Kitakata-shi Joban-shi Iwaki-shi Soma-shi Uchigo-shi Nakoso-shi Nihonmatsu-shi Iwaki-shi Wakamatsu-shi Tamura-shi Minamisoma-shi Date-shi Motomiya-shi Asaka-gun Adachi-gun Ishikawa-gun Ishiki-gun Iwase-gun Onuma-gun Kawanuma-gun Kitaaidu-gun Shinobu-gun Soma-gun Date-gun Tamura-gun Nishishirakawa-gun Higashishirakawa-gun Futaba-gun Minamiaidu-gun Yama-gun Niigata-shi Nagaoka-shi Takada-shi Sanjo-shi Kashiwazaki-shi Shibata-shi Niitsu-shi Ojiya-shi Kamo-shi Tokamachi-shi Mitsuke-shi Murakami-shi Tsubame-shi Naoetsu-shi Tochio-shi Itoigawa-shi Arai-shi Gosen-shi Ryotsu-shi Shirone-shi Toyosaka-shi Joetsu-shi Agano-shi Sado-shi Uonuma-shi Minamiuonuma-shi Myoko-shi Tainai-shi Iwafune-gun Kariwa-gun Kitauonuma-gun Kitakambara-gun Koshi-gun Sado-gun Santo-gun Nakauonuma-gun Nakakambara-gun Nakakubiki-gun Nishikambara-gun Nishikubiki-gun Higashikambara-gun Higashikubiki-gun Minamiuonuma-gun Minamikambara-gun Kita-ku Higashi-ku Chuo-ku Konan-ku Akiha-ku Minami-ku Nishi-ku Nishikan-ku Nagano-shi Matsumoto-shi Ueda-shi Okaya-shi Iida-shi Suwa-shi Suzaka-shi Komoro-shi Ina-shi Komagane-shi Nakano-shi Omachi-shi Iiyama-shi Chino-shi Shiojiri-shi Shinonoi-shi Koshoku-shi Saku-shi Chikuma-shi Tomi-shi Azumino-shi Kamiina-gun Kamitakai-gun Kamiminochi-gun Kiso-gun Kitaazumi-gun Kitasaku-gun Sarashina-gun Shimoina-gun Shimotakai-gun Shimominochi-gun Suwa-gun Chiisagata-gun Hanishina-gun Higashichikuma-gun Minamiazumi-gun Minamisaku-gun Chiyoda-ku Chuo-ku Minato-ku Shinjuku-ku Bunkyo-ku Taito-ku Sumida-ku Koto-ku Shinagawa-ku Meguro-ku Ota-ku Setagaya-ku Shibuya-ku Nakano-ku Suginami-ku Toshima-ku Kita-ku Arakawa-ku Itabashi-ku Nerima-ku Adachi-ku Katsushika-ku Edogawa-ku Tokyo 23-wards Hachioji-shi Tachikawa-shi Musashino-shi Mitaka-shi Ome-shi Fuchu-shi Akishima-shi Chofu-shi Machida-shi Koganei-shi Kodaira-shi Hino-shi Higashimurayama-shi Kokubunji-shi Kunitachi-shi Hoya-shi Tanashi-shi Fussa-shi Komae-shi Higashiyamato-shi Kiyose-shi Higashikurume-shi Musashimurayama-shi Tama-shi Inagi-shi Akigawa-shi Hamura-shi Akiruno-shi Nishitokyo-shi Kitatama-gun Nishitama-gun Minamitama-gun Oshima-gun Miyake-gun Hachijo-gun Ogawasara-gun Yokohama-shi Yokosuka-shi Kawasaki-shi Hiratsuka-shi Kamakura-shi Fujisawa-shi Odawara-shi Chigasaki-shi Zushi-shi Sagamihara-shi Miura-shi Hadano-shi Atsugi-shi Yamato-shi Isehara-shi Ebina-shi Zama-shi Minamiashigara-shi Ayase-shi Aiko-gun Ahigarakami-gun Ashigarashimo-gun Koza-gun Tsukui-gun Naka-gun Miura-gun Tsurumi-ku Kanagawa-ku Nishi-ku Naka-ku Minami-ku Hodogaya-ku Isogo-ku Kanazawa-ku Kohoku-ku Totsuka-ku Konan-ku Asahi-ku Midori-ku Seya-ku Sakae-ku Izumi-ku Aoba-ku Tsuzuki-ku Kawasaki-ku Saiwai-ku Nakahara-ku Takatsu-ku Tama-ku Miyamae-ku Asao-ku Midori-ku Chuou-ku Minami-ku Chiba-shi Choshi-shi Ichikawa-shi Funabashi-shi Tateyama-shi Kisarazu-shi Matsudo-shi Noda-shi Sawara-shi Mobara-shi Narita-shi Sakura-shi Togane-shi Yokaichiba-shi Asahi-shi Narashino-shi Kashiwa-shi Katsuura-shi Ichihara-shi Nagareyama-shi Yachiyo-shi Abiko-shi Kamogawa-shi Kimitsu-shi Kamagaya-shi Futtu-shi Urayasu-shi Yotsukaido-shi Sodegaura-shi Yachimata-shi Inzai-shi Shiroi-shi Tomisato-shi Minamiboso-shi Sosa-shi Katori-shi Sanmu-shi Isumi-shi Oamishirasato-shi Awa-gun Isumi-gun Ichihara-gun Inba-gun Kaijo-gun Katori-gun Kimitsu-gun Sambu-gun Sosa-gun Chiba-gun Chosei-gun Higashikatsushika-gun Chuo-ku Hanamigawa-ku Inage-ku Wakaba-ku Midori-ku Mihama-ku Urawa-shi Kawagoe-shi Kumagaya-shi Kawaguchi-shi Omiya-shi Gyoda-shi Chichibu-shi Tokorozawa-shi Hanno-shi Kazo-shi Honjo-shi Higashimatsuyama-shi Iwatsuki-shi Kasukabe-shi Sayama-shi Hanyu-shi Konosu-shi Fukaya-shi Ageo-shi Yono-shi Soka-shi Koshigaya-shi Warabi-shi Toda-shi Iruma-shi Hatogaya-shi Asaka-shi Shiki-shi Wako-shi Niiza-shi Okegawa-shi Kuki-shi Kitamoto-shi Yashio-shi Kamifukuoka-shi Fujimi-shi Misato-shi Hasuda-shi Sakado-shi Satte-shi Tsurugashima-shi Hidaka-shi Yoshikawa-shi Saitama-shi Fujimino-shi Shiraoka-shi Iruma-gun Osato-gun Kitaadachi-gun Kitakatsushika-gun Kitasaitama-gun Kodama-gun Chichibu-gun Hiki-gun Minamisaitama-gun Nishi-ku Kita-ku Omiya-ku Minuma-ku Chuo-ku Sakura-ku Urawa-ku Minami-ku Midori-ku Iwatsuki-ku Mito-shi Hitachi-shi Tsuchiura-shi Koga-shi Ishioka-shi Shimodate-shi Yuki-shi Ryugasaki-shi Nakaminato-shi Shimotsuma-shi Mitsukaido-shi Hitachiota-shi Katsuta-shi Takahagi-shi Kitaibaraki-shi Kasama-shi Toride-shi Iwai-shi Ushiku-shi Tsukuba-shi Hitachinaka-shi Kashima-shi Itako-shi Moriya-shi Hitachiomiya-shi Naka-shi Chikusei-shi Bandou-shi Inashiki-shi Kasumigaura-shi Sakuragawa-shi Kamisu-shi Namegata-shi Hokota-shi Joso-shi Tsukubamirai-shi Omitama-shi Inashiki-gun Kashima-gun Kitasoma-gun Kuji-gun Sashima-gun Taga-gun Tsukuba-gun Naka-gun Namegata-gun Niihari-gun Nishiibaraki-gun Higashiibaraki-gun Makabe-gun Yuki-gun Utsunomiya-shi Ashikaga-shi Tochigi-shi Sano-shi Kanuma-shi Nikko-shi Imaichi-shi Oyama-shi Mooka-shi Otawara-shi Yaita-shi Kuroiso-shi Nasushiobara-shi Sakura-shi Nasukarasuyama-shi Shimotsuke-shi Ashikaga-gun Aso-gun Kamitsuga-gun Kawachi-gun Shioya-gun Shimotsuga-gun Nasu-gun Haga-gun Maebashi-shi Takasaki-shi Kiryu-shi Isesaki-shi Ota-shi Numata-shi Tatebayashi-shi Shibukawa-shi Fujioka-shi Tomioka-shi Annaka-shi Midori-shi Agatsuma-gun Usui-gun Ora-gun Kanra-gun Kitagumma-gun Gumma-gun Sawa-gun Seta-gun Tano-gun Tone-gun Nitta-gun Yamada-gun Kofu-shi Fujiyoshida-shi Enzan-shi Tsuru-shi Yamanashi-shi Otsuki-shi Nirasaki-shi Minami-Alps Hokuto-shi Kai-shi Fuehuki-shi Uenohara-shi Koshu-shi Chuo-shi Kitakoma-gun Kitatsuru-gun Nakakoma-gun Nishiyatsushiro-gun Higashiyatsushiro-gun Higashiyamanashi-gun Minamikoma-gun Minamitsuru-gun Shizuoka-shi Hamamatsu-shi Numadu-shi Shimizu-shi Atami-shi Mishima-shi Fujinomiya-shi Ito-shi Shimada-shi Yoshiwara-shi Iwata-shi Yaidu-shi Fuji-shi Kakegawa-shi Fujieda-shi Gotemba-shi Fukuroi-shi Tenryu-shi Hamakita-shi Shimoda-shi Susono-shi Kosai-shi Izu-shi Omaezaki-shi Kikugawa-shi Izunokuni-shi Makinohara-shi Abe-gun Inasa-gun Ihara-gun Iwata-gun Ogasa-gun Kamo-gun Shida-gun Shuchi-gun Sunto-gun Tagata-gun Haibara-gun Hamana-gun Fuji-gun Aoi-ku Suruga-ku Shimizu-ku Naka-ku Higashi-ku Nishi-ku Minami-ku Kita-ku Hamakita-ku Tenryu-ku Gifu-shi Ogaki-shi Takayama-shi Tajimi-shi Seki-shi Nakatsugawa-shi Mino-shi Mizunami-shi Hashima-shi Ena-shi Minokamo-shi Toki-shi Kakamigahara-shi Kani-shi Yamagata-shi Mizuho-shi Hida-shi Motosu-shi Gujo-shi Gero-shi Kaizu-shi Ampachi-gun Inaba-gun Ibi-gun Ena-gun Ono-gun Kaizu-gun Kani-gun Kamo-gun Gujo-gun Toki-gun Hashima-gun Fuwa-gun Mashita-gun Mugi-gun Motosu-gun Yamagata-gun Yoro-gun Yoshiki-gun Nagoya-shi Toyohashi-shi Okazaki-shi Ichinomiya-shi Seto-shi Handa-shi Kasugai-shi Toyokawa-shi Tsushima-shi Hekinan-shi Kariya-shi Toyota-shi Anjo-shi Nishio-shi Gamagori-shi Inuyama-shi Tokoname-shi Moriyama-shi Konan-shi Bisai-shi Komaki-shi Inazawa-shi Shinshiro-shi Tokai-shi Obu-shi Chita-shi Takahama-shi Chiryu-shi Owariasahi-shi Iwakura-shi Toyoake-shi Nissin-shi Tahara-shi Aisai-shi Kiyosu-shi Kitanagoya-shi Yatomi-shi Miyoshi-shi Ama-shi Nagakute-shi Aichi-gun Atsumi-gun Ama-gun Kitashitara-gun Chita-gun Nakashima-gun Nishikasugai-gun Nishikamo-gun Niwa-gun Nukata-gun Haguri-gun Hazu-gun Higashikasugai-gun Higashikamo-gun Hekikai-gun Hoi-gun Minamishitara-gun Yana-gun Chikusa-ku Higashi-ku Kita-ku Nishi-ku Nakamura-ku Naka-ku Showa-ku Mizuho-ku Atsuta-ku Nakagawa-ku Minato-ku Minami-ku Moriyama-ku Midori-ku Meito-ku Tenpaku-ku Tsu-shi Yokkaichi-shi Ise-shi Matsusaka-shi Kuwana-shi Ueno-shi Suzuka-shi Nabari-shi Owase-shi Kameyama-shi Toba-shi Kumano-shi Hisai-shi Ujiyamada-shi Inabe-shi Shima-shi Iga-shi Age-gun Ano-gun Ayama-gun Iinan-gun Ichishi-gun Inabe-gun Kawage-gun Kitamuro-gun Kuwana-gun Shima-gun Suzuka-gun Taki-gun Naga-gun Mie-gun Minamimuro-gun Watarai-gun Kyoto-shi Fukuchiyama-shi Maiduru-shi Ayabe-shi Uji-shi Miyazu-shi Kameoka-shi Joyo-shi Nagaokakyo-shi Muko-shi Yawata-shi Kyotanabe-shi Kyotango-shi Nantan-shi Kizugawa-shi Amada-gun Ikaruga-gun Otokuni-gun Kasa-gun Kitakuwada-gun Kuze-gun Kumano-gun Soraku-gun Takeno-gun Tsuduki-gun Naka-gun Funai-gun Minamikuwada-gun Yoza-gun Kita-ku Kamigyo-ku Sakyo-ku Nakagyo-ku Higashiyama-ku Shimogyo-ku Minami-ku Ukyo-ku Fushimi-ku Yamashina-ku Nishikyo-ku Otsu-shi Hikone-shi Nagahama-shi Omihachiman-shi Yokaichi-shi Kusatsu-shi Moriyama-shi Ritto-shi Koka-shi Yasu-shi Konan-shi Takashima-shi Higashioumi-shi Maibara-shi Ika-gun Inukami-gun Echi-gun Gamou-gun Kanzaki-gun Kurita-gun Koka-gun Sakata-gun Shiga-gun Takashima-gun Higashiazai-gun Yasu-gun Nara-shi Yamatotakada-shi Yamatokoriyama-shi Tenri-shi Kashihara-shi Sakurai-shi Gojo-shi Gose-shi Ikoma-shi Kashiba-shi Katsuragi-shi Uda-shi Ikoma-gun Uda-gun Uchi-gun Kitakatsuragi-gun Shiki-gun Soekami-gun Takaichi-gun Minamikatsuragi-gun Yamabe-gun Yoshino-gun Osaka-shi Sakai-shi Kishiwada-shi Toyonaka-shi Fuse-shi Ikeda-shi Suita-shi Izumiotsu-shi Takatsuki-shi Kaiduka-shi Moriguchi-shi Hirakata-shi Ibaraki-shi Yao-shi Izumisano-shi Tondabayashi-shi Neyagawa-shi Kawachinagano-shi Hiraoka-shi Kawachi-shi Matsubara-shi Daito-shi Izumi-shi Mino-shi Kashiwara-shi Habikino-shi Kadoma-shi Settsu-shi Fujiidera-shi Takaishi-shi Higashiosaka-shi Sennan-shi Shijonawate-shi Katano-shi Osakasayama-shi Hannan-shi Kitakawachi-gun Sennan-gun Senboku-gun Toyono-gun Nakakawachi-gun Mishima-gun Minamikawachi-gun Kita-ku Miyakojima-ku Fukushima-ku Konohana-ku Higashi-ku Nishi-ku Minato-ku Taisho-ku Tennoji-ku Minami-ku Naniwa-ku Oyodo-ku Nishiyodogawa-ku Higashiyodogawa-ku Higashinari-ku Ikuno-ku Asahi-ku Joto-ku Abeno-ku Sumiyoshi-ku Higashisumiyoshi-ku Nishinari-ku Yodogawa-ku Tsurumi-ku Suminoe-ku Hirano-ku Chuo-ku Sakai-ku Naka-ku Higashi-ku Nishi-ku Minami-ku Kita-ku Mihara-ku Wakayama-shi Shingu-shi Kainan-shi Tanabe-shi Gobo-shi Hashimoto-shi Arida-shi Kinokawa-shi Iwade-shi Arida-gun Ito-gun Kaiso-gun Naga-gun Nishimuro-gun Higashimuro-gun Hidaka-gun Kobe-shi Himeji-shi Amagasaki-shi Akashi-shi Nishinomiya-shi Sumoto-shi Ashiya-shi Itami-shi Aioi-shi Toyooka-shi Kakogawa-shi Tatsuno-shi Ako-shi Nishiwaki-shi Takaraduka-shi Miki-shi Takasago-shi Kawanishi-shi Ono-shi Sanda-shi Kasai-shi Sasayama-shi Yabu-shi Tanba-shi Minamiawaji-shi Asago-shi Awaji-shi Shiso-shi Kato-shi Tatsuno-shi Akou-gun Asago-gun Arima-gun Izushi-gun Ibo-gun Innami-gun Kako-gun Kasai-gun Kato-gun Kawabe-gun Kanzaki-gun Kinosaki-gun Sayo-gun Shikama-gun Shiso-gun Taka-gun Taki-gun Tsuna-gun Hikami-gun Mikata-gun Mino-gun Mihara-gun Muko-gun Yabu-gun Higashinada-ku Nada-ku Hyogo-ku Nagata-ku Suma-ku Tarumi-ku Kita-ku Chuo-ku Nishi-ku Fukiai-ku Ikuta-ku Toyama-shi Takaoka-shi Shinminato-shi Uodu-shi Himi-shi Namerikawa-shi Kurobe-shi Tonami-shi Oyabe-shi Nanto-shi Imizu-shi Imizu-gun Kaminiikawa-gun Shimoniikawa-gun Nakaniikawa-gun Nishitonami-gun Nei-gun Himi-gun Higashitonami-gun Fukui-shi Tsuruga-shi Takefu-shi Obama-shi Ono-shi Katsuyama-shi Sabae-shi Awara-shi Echizen-shi Sakai-shi Asuwa-gun Imadate-gun Oi-gun Ono-gun Onyu-gun Sakai-gun Tsuruga-gun Nanjo-gun Nyuu-gun Mikata-gun Yoshida-gun Mikatakaminaka-gun Kanazawa-shi Nanao-shi Komatsu-shi Wajima-shi Suzu-shi Kaga-shi Hakui-shi Matsuto-shi Kahoku-shi Hakusan-shi Nomi-shi Nonoichi-shi Ishikawa-gun Enuma-gun Kashima-gun Kahoku-gun Suzu-gun Nomi-gun Hakui-gun Fugeshi-gun Housu-gun Okayama-shi Kurashiki-shi Tsuyama-shi Tamano-shi Kojima-shi Tamashima-shi Kasaoka-shi saidaiji-shi Ibara-shi Soja-shi Takahashi-shi Niimi-shi Bizen-shi Setouchi-shi Akaiwa-shi Maniwa-shi Mimasaka-shi Asakuchi-shi Aida-gun Akaiwa-gun Asakuchi-gun Atetsu-gun Oku-gun Oda-gun Katsuta-gun Kawakami-gun Kibi-gun Kume-gun Kojima-gun Shitsuki-gun Jodo-gun Jobo-gun Tsukubo-gun Tomada-gun Maniwa-gun Mitsu-gun Wake-gun Kaga-gun Kita-ku Naka-ku Higashi-ku Minami-ku Matsue-shi Hamada-shi Izumo-shi Masuda-shi Oda-shi Yasugi-shi Gotsu-shi Hirata-shi Unnan-shi Ano-gun Ama-gun Iishi-gun Ochi-gun Ohara-gun Oki-gun Ochi-gun Kanoashi-gun Suki-gun Chibu-gun Naka-gun Nita-gun Nima-gun Nogi-gun Hikawa-gun Mino-gun Yatsuka-gun Asa-gun Yamaguchi-shi Shimonoseki-shi Ube-shi Hagi-shi Tokuyama-shi Hofu-shi Kudamatsu-shi Iwakuni-shi Onoda-shi Hikari-shi Nagato-shi Yanai-shi Mine-shi Shinnan01yo-shi Shunan-shi San01yoonoda-shi Abu-gun Oshima-gun Otsu-gun Kuga-gun Kumage-gun Saba-gun Tsuno-gun Toyoura-gun Mine-gun Yoshiki-gun Tottori-shi Kurayoshi-shi Yonago-shi Sakaiminato-shi Iwami-gun Ketaka-gun Saihaku-gun Tohaku-gun Hino-gun Yazu-gun Hiroshima-shi Kure-shi Takehara-shi Mihara-shi Onomichi-shi Innoshima-shi Matsunaga-shi Fukuyama-shi Fuchu-shi Miyoshi-shi Syoubara-shi Otake-shi Higashihiroshima-shi Hatsukaichi-shi Akitakata-shi Etajima-shi Aki-gun Asa-gun Ashina-gun Kamo-gun Konu-gun Saeki-gun Jinseki-gun Sera-gun Takata-gun Toyota-gun Numakuma-gun Hiba-gun Fukayasu-gun Futami-gun Mitsugi-gun Yamagata-gun Naka-ku Higashi-ku Minami-ku Nishi-ku Asaminami-ku Asakita-ku Aki-ku Saeki-ku Takamatsu-shi Marugame-shi Sakaide-shi Zentsuji-shi Kan01onji-shi Sanuki-shi Higashikagawa-shi Mitoyo-shi Ayauta-gun Okawa-gun Kagawa-gun Kita-gun Syozu-gun Nakatado-gun Mitoyo-gun Tokushima-shi Naruto-shi Komatsushima-shi Anan-shi Yoshinogawa-shi Awa-shi Mima-shi Miyoshi-shi Awa-gun Itano-gun Oe-gun Kaifu-gun Katsuura-gun Naka-gun Myozai-gun Myodo-gun Mima-gun Miyoshi-gun Matsuyama-shi Imabari-shi Uwajima-shi Yawatahama-shi Niihama-shi Saijo-shi Ozu-shi Iyomishima-shi Kawanoe-shi Iyo-shi Hojo-shi Toyo-shi Shikokuchuo-shi Seiyo-shi Toon-shi Iyo-gun Uma-gun Ochi-gun Onsen-gun Kamiukena-gun Kita-gun Kitauwa-gun Shuso-gun Nii-gun Nishiuwa-gun Higashiuwa-gun Minamiuwa-gun Kochi-shi Muroto-shi Aki-shi Tosa-shi Susaki-shi Nakamura-shi Sukumo-shi Tosashimizu-shi Nankoku-shi Shimanto-shi Konan-shi Kami-shi Agawa-gun Aki-gun Kami-gun Takaoka-gun Tosa-gun Nagaoka-gun Hata-gun Fukuoka-shi Kokura-shi Moji-shi Yahata-shi Tobata-shi Wakamatsu-shi Kurume-shi Omuta-shi Noogata-shi Iizuka-shi Tagawa-shi Yanagawa-shi Amagi-shi Yamada-shi Yame-shi Chikugo-shi Okawa-shi Yukuhashi-shi Buzen-shi Nakama-shi Kitakyushu-shi Ogoori-shi Kasuga-shi Chikushino-shi Onojo-shi Munakata-shi Dazaifu-shi Maebaru-shi Koga-shi Fukutsu-shi Ukiha-shi Miyawaka-shi Kama-shi Asakura-shi Miyama-shi Itoshima-shi Asakura-gun Itoshima-gun Ukiha-gun Onga-gun Kasuya-gun Kaho-gun Kurate-gun Sawara-gun Tagawa-gun Chikushi-gun Chikujo-gun Mii-gun Miike-gun Mizuma-gun Miyako-gun Munakata-gun Yamato-gun Yame-gun Higashi-ku Hakata-ku Chuo-ku Minami-ku Nishi-ku Jonan-ku Sawara-ku Moji-ku Wakamatsu-ku Tobata-ku Kokurakita-ku Kokuraminami-ku Yahatahigashi-ku Yahatanishi-ku Yahata-ku Kokura-ku Saga-shi Karatsu-shi Tosu-shi Taku-shi Imari-shi Takeo-shi Kashima-shi Ogi-shi Ureshino-shi Kanzaki-shi Ogi-gun Kanzaki-gun Kishima-gun Saga-gun Nishimatsuura-gun Higashimatsuura-gun Fujitsu-gun Miyaki-gun Nagasaki-shi Sasebo-shi Shimabara-shi Isahaya-shi Omura-shi Fukue-shi Hirado-shi Matsuura-shi Tsushima-shi Iki-shi Goto-shi Saikai-shi Unzen-shi Minamishimabara-shi Iki-gun Kamiagata-gun Kitatakaki-gun Kitamatsuura-gun Shimoagata-gun Nishisonogi-gun Higashisonogi-gun Minamitakaki-gun Minamimatsuura-gun Kumamoto-shi Yatsushiro-shi Hitoyoshi-shi Arao-shi Minamata-shi Tamana-shi Hondo-shi Yamaga-shi Ushibuka-shi Kikuchi-shi Uto-shi Kamiamakusa-shi Uki-shi Aso-shi Amakusa-shi Koshi-shi Ashikita-gun Aso-gun Amakusa-gun Uto-gun Kamimashiki-gun Kamoto-gun Kikuchi-gun Kuma-gun Shimomashiki-gun Tamana-gun Hotaku-gun Yatsushiro-gun Chuo-ku Higashi-ku Nishi-ku Minami-ku Kita-ku Oita-shi Beppu-shi Nakatsu-shi Hita-shi Saiki-shi Usuki-shi Tsukumi-shi Taketa-shi Tsurusaki-shi Bungotakada-shi Kitsuki-shi Usa-shi Bungoono-shi Yufu-shi Kunisaki-shi Usa-gun Oita-gun Ono-gun Kitaamabe-gun Kusu-gun Shimoge-gun Naoiri-gun Nishikunisaki-gun Hayami-gun Higashikunisaki-gun Hita-gun Minamiamabe-gun Miyazaki-shi Miyakonojo-shi Nobeoka-shi Nichinan-shi Kobayashi-shi Hyuga-shi Kushima-shi Saito-shi Ebino-shi Kitamorokata-gun Koyu-gun Nishiusuki-gun Nishimorokata-gun Higashiusuki-gun Higashimorokata-gun Minaminaka-gun Miyazaki-gun Kagoshima-shi Sendai-shi Kanoya-shi Makurazaki-shi Kushikino-shi Akune-shi Izumi-shi Naze-shi Okuchi-shi Ibusuki-shi Kaseda-shi Kokubu-shi Taniyama-shi Nishinoomote-shi Tarumizu-shi Satsumasendai-shi Hioki-shi Soo-shi Kirishima-shi Ichikikushikino-shi Minamisatsuma-shi Shibushi-shi Amami-shi Minamikyushu-shi Isa-shi Aira-shi Aira-gun Isa-gun Izumi-gun Ibusuki-gun Oshima-gun Kagoshima-gun Kawanabe-gun Kimotsuki-gun Kumage-gun Satsuma-gun Soo-gun Hioki-gun Naha-shi Ishikawa-shi Hirara-shi Ishigaki-shi Koza-shi Ginowan-shi Gushikawa-shi Nago-shi Urasoe-shi Itoman-shi Okinawa-shi Tomigusuku-shi Uruma-shi Miyakojima-shi Nanjo-shi Kunigami-gun Shimajiri-gun Nakagami-gun Miyako-gun Yaeyama-gun Hokkaido-do Aomori-ken Iwate-ken Akita-ken Yamagata-ken Miyagi-ken Fukushima-ken Niigata-ken Nagano-ken Tokyo-to Kanagawa-ken Chiba-ken Saitama-ken Ibaraki-ken Tochigi-ken Gunma-ken Yamanashi-ken Shizuoka-ken Gifu-ken Aichi-ken Mie-ken Kyoto-ken Shiga-ken Nara-ken Osaka-fu Wakayama-ken Hyogo-ken Toyama-ken Fukui-ken Ishikawa-ken Okayama-ken Shimane-ken Yamaguchi-ken Tottori-ken Hiroshima-ken Kagawa-ken Tokushima-ken Ehime-ken Kochi-ken Fukuoka-ken Saga-ken Nagasaki-ken Kumamoto-ken Oita-ken Miyazaki-ken Kagoshima-ken Okinawa-ken Kaliningradskaya oblast' (Kaliningrad Oblast) Aginsky Buryatsky avtonomny okrug (Agin-Buryat Autonomous Okrug) [DELETED] Altayskiy kray (Altai Krai) Amurskaya oblast' (Amur Oblast) Respublika Bashkortostan (Republic of Bashkortostan) (Bashkortostan Republic) Respublika Buryatiya (Republic of Buryatia) Chelyabinskaya oblast' (Chelyabinsk Oblast) Chukotsky avtonomny okrug (Chukotka Autonomous Okrug) Zabaykalsky kray (Zabaykalsky Krai) Yevreyskaya avtonomnaya oblast' (Jewish Autonomous Oblast) Evenkiysky avtonomny okrug (Evenk Autonomous Okrug) [DELETED] Respublika Altay (Altai Republic) (Altay Republits) Respublika Khakasiya (Khakasiya Republits) (Republic of Khakassia) Khabarovskiy kray (Khabarovsk Krai) Khanty-Mansiyskiy avtonomnyy okrug (Khanty-Mansi Autonomous Okrug) Irkutskaya oblast' (Irkutsk Oblast) Yamalo-Nenetsky avtonomny okrug (Yamalo-Nenets Autonomous Okrug) Kemerovskaya oblast' (Kemerovo Oblast) Koryaksky avtonomny okrug (Koryak Autonomous Okrug) [DELETED] Krasnoyarskiy kray (Krasnoyarsk Krai) Kurganskaya oblast' (Kurgan Oblast) Kamchatskiy kray (Kamchatka Krai) Magadanskaya oblast' (Magadan Oblast) Novosibirskaya oblast' (Novosibirsk Oblast) Orenburgskaya oblast' (Orenburg Oblast) Omskaya oblast' (Omsk Oblast) Primorskiy kray (Primorsky Krai) Sakhalinskaya oblast' (Sakhalin Oblast) Sverdlovskaya oblast' (Sverdlovsk Oblast) Taymyrsky Dolgano-Nenetsky avtonomny okru (Taymyr Autonomous Okrug) (Taymyria) [DELETED] Tyumenskaya oblast' (Tyumen Oblast) Tomskaya oblast' (Tomsk Oblast) Respublika Tyva (Tyva Republic) (Tyva Republits) Ust-Ordynsky avtonomny okrug (Ust-Orda Buryat Autonomous Okrug) [DELETED] Respublika Sakha (Yakutiya) Leningradskaya oblast' (Leningrad Oblast) Adygea (Adygea Republic} Astrakhanskaya oblast' (Astrakhan Oblast) Arkhangelskaya oblast' (Arkhangelsk Oblast) Belgorodskaya oblast' (Belgorod Oblast) Bryanskaya oblast' (Bryansk Oblast) Chechenskaya Respublika (Chechnya) Chuvashiya (Chuvashia Republic) (Chuvash Republic) Dagestan Republits (Dagestan Republic) Respublika Ingushetiya (Republic of Ingushetia) Ivanovskaya oblast' (Ivanovo Oblast) Yaroslavskaya oblast' (Yaroslavl Oblast) Kabardino-Balkarskaya Respublika (Kabardino-Balkaria) Karachay-Cherkessia (Karachay-Cherkess Republic) Kaluzhskaya oblast' (Kaluga Oblast) Kirovskaya oblast' (Kirov Oblast) Respublika Karelia (Karelia Republic) Respublika Kalmykiya (Kalmykia Republic) (Kalmykia) Respúblika Komi (Komi Republic) Komi-Permyatsky avtonomny okrug (Komi-Permyak Autonomous Okrug) [DELETED] Krasnodarskiy kray (Krasnodar Krai) Kostromskaya oblast' (Kostroma Oblast) Kurskaya oblast' (Kursk Oblast) Leningradskaya oblast' (Leningrad Oblast) Lipetsk Oblast (Lipetskaya oblast') Moskva (Moscow) Respublika Mordoviya (Republic of Mordovia) Moskovskaya oblast' (Moscow Oblast) Respublika Mariy El (Mari El Republic) Murmanskaya oblast' (Murmansk Oblast) Nizhegorodskaya oblast' (Nizhny Novgorod Oblast) Nenetsky avtonomny okrug (Nenets Autonomous Okrug) Novgorodskaya oblast' (Novgorod Oblast) Orlovskaya oblast' (Oryol Oblast) Penzenskaya oblast' (Penza Oblast) Permskiy kray (Perm Krai) Pskovskaya oblast' (Pskov Oblast) Ryazanskaya oblast' (Ryazan Oblast) Rostovskaya oblast' (Rostov Oblast) Saratovskaya oblast' (Saratov Oblast) Smolenskaya oblast' (Smolensk Oblast) Severnaya Osetiya (North Ossetia-Alania) (North Ossetia-Alania Republic) Sankt-Peterburg (Saint Petersburg) Samarskaya oblast' (Samara Oblast) Stavropolskiy kray (Stavropol Krai) Respublika Tatarstan (Tatarstan) (Tatarstan Republic) Tambovskaya oblast' (Tambov Oblast) Tulskaya oblast' (Tula Oblast) Tverskaya oblast' (Tver Oblast) Udmurtskaja Respublika (Udmurt Republic) Ulyanovskaya oblast' (Ulyanovsk Oblast) Volgogradskaya oblast' (Volgograd Oblast) Vladimirskaya oblast' (Vladimir Oblast) Vologodskaya oblast' (Vologda Oblast) Voronezhskaya oblast' (Voronezh Oblast) Arkhangelskaya oblast' (Arkhangelsk Oblast) Aleutians East Borough Aleutians West Census Area Anchorage Municipality Bethel Census Area Bristol Bay Borough Denali Borough Dillingham Census Area Fairbanks North Star Borough Haines Borough Hoonah-Angoon Census Area Juneau City and Borough Kenai Peninsula Borough Ketchikan Gateway Borough Kodiak Island Borough Lake and Peninsula Borough Matanuska-Susitna Borough Nome Census Area North Slope Borough Northwest Arctic Borough Petersburg Census Area Prince of Wales-Hyder Census Area Sitka City and Borough Skagway Municipality Southeast Fairbanks Census Area Valdez-Cordova Census Area Wade Hampton Census Area Wrangell City and Borough Yakutat City and Borough Yukon-Koyukuk Census Area Prince of Wales-Outer-Ketichikan Census Area Skagway-Hoonah-Angoon Census Area Autauga Baldwin Barbour Bibb Blount Bullock Butler Calhoun Chambers Cherokee Chilton Choctaw Clarke Clay Cleburne Coffee Colbert Conecuh Coosa Covington Crenshaw Cullman Dale Dallas DeKalb Elmore Escambia Etowah Fayette Franklin Geneva Greene Hale Henry Houston Jackson Jefferson Lamar Lauderdale Lawrence Lee Limestone Lowndes Macon Madison Marengo Marion Marshall Mobile Monroe Montgomery Morgan Perry Pickens Pike Randolph Russell St. Clair Shelby Sumter Talladega Tallapoosa Tuscaloosa Walker Washington Wilcox Winston Arkansas Ashley Baxter Benton Boone Bradley Calhoun Carroll Chicot Clark Clay Cleburne Cleveland Columbia Conway Craighead Crawford Crittenden Cross Dallas Desha Drew Faulkner Franklin Fulton Garland Grant Greene Hempstead Hot Spring Howard Independence Izard Jackson Jefferson Johnson Lafayette Lawrence Lee Lincoln Little River Logan Lonoke Madison Marion Miller Mississippi Monroe Montgomery Nevada Newton Ouachita Perry Phillips Pike Poinsett Polk Pope Prairie Pulaski Randolph St. Francis Saline Scott Searcy Sebastian Sevier Sharp Stone Union Van Buren Washington White Woodruff Yell Apache Cochise Coconino Gila Graham Greenlee La Paz Maricopa Mohave Navajo Pima Pinal Santa Cruz Yavapai Yuma Alameda Alpine Amador Butte Calaveras Colusa Contra Costa Del Norte El Dorado Fresno Glenn Humboldt Imperial Inyo Kern Kings Lake Lassen Los Angeles Madera Marin Mariposa Mendocino Merced Modoc Mono Monterey Napa Nevada Orange Placer Plumas Riverside Sacramento San Benito San Bernardino San Diego San Francisco San Joaquin San Luis Obispo San Mateo Santa Barbara Santa Clara Santa Cruz Shasta Sierra Siskiyou Solano Sonoma Stanislaus Sutter Tehama Trinity Tulare Tuolumne Ventura Yolo Yuba Adams Alamosa Arapahoe Archuleta Baca Bent Boulder Broomfield Chaffee Cheyenne Clear Creek Conejos Costilla Crowley Custer Delta Denver Dolores Douglas Eagle El Paso Elbert Fremont Garfield Gilpin Grand Gunnison Hinsdale Huerfano Jackson Jefferson Kiowa Kit Carson La Plata Lake Larimer Las Animas Lincoln Logan Mesa Mineral Moffat Montezuma Montrose Morgan Otero Ouray Park Phillips Pitkin Prowers Pueblo Rio Blanco Rio Grande Routt Saguache San Juan San Miguel Sedgwick Summit Teller Washington Weld Yuma Fairfield Hartford Litchfield Middlesex New Haven New London Tolland Windham Kent New Castle Sussex Alachua Baker Bay Bradford Brevard Broward Calhoun Charlotte Citrus Clay Collier Columbia DeSoto Dixie Duval Escambia Flagler Franklin Gadsden Gilchrist Glades Gulf Hamilton Hardee Hendry Hernando Highlands Hillsborough Holmes Indian River Jackson Jefferson Lafayette Lake Lee Leon Levy Liberty Madison Manatee Marion Martin Miami-Dade Monroe Nassau Okaloosa Okeechobee Orange Osceola Palm Beach Pasco Pinellas Polk Putnam St. Johns St. Lucie Santa Rosa Sarasota Seminole Sumter Suwannee Taylor Union Volusia Wakulla Walton Washington Appling Atkinson Bacon Baker Baldwin Banks Barrow Bartow Ben Hill Berrien Bibb Bleckley Brantley Brooks Bryan Bulloch Burke Butts Calhoun Camden Candler Carroll Catoosa Charlton Chatham Chattahoochee Chattooga Cherokee Clarke Clay Clayton Clinch Cobb Coffee Colquitt Columbia Cook Coweta Crawford Crisp Dade Dawson Decatur DeKalb Dodge Dooly Dougherty Douglas Early Echols Effingham Elbert Emanuel Evans Fannin Fayette Floyd Forsyth Franklin Fulton Gilmer Glascock Glynn Gordon Grady Greene Gwinnett Habersham Hall Hancock Haralson Harris Hart Heard Henry Houston Irwin Jackson Jasper Jeff Davis Jefferson Jenkins Johnson Jones Lamar Lanier Laurens Lee Liberty Lincoln Long Lowndes Lumpkin Macon Madison Marion McDuffie McIntosh Meriwether Miller Mitchell Monroe Montgomery Morgan Murray Muscogee Newton Oconee Oglethorpe Paulding Peach Pickens Pierce Pike Polk Pulaski Putnam Quitman Rabun Randolph Richmond Rockdale Schley Screven Seminole Spalding Stephens Stewart Sumter Talbot Taliaferro Tattnall Taylor Telfair Terrell Thomas Tift Toombs Towns Treutlen Troup Turner Twiggs Union Upson Walker Walton Ware Warren Washington Wayne Webster Wheeler White Whitfield Wilcox Wilkes Wilkinson Worth Hawaii Honolulu Kalawao Kauai Maui Adair Adams Allamakee Appanoose Audubon Benton Black Hawk Boone Bremer Buchanan Buena Vista Butler Calhoun Carroll Cass Cedar Cerro Gordo Cherokee Chickasaw Clarke Clay Clayton Clinton Crawford Dallas Davis Decatur Delaware Des Moines Dickinson Dubuque Emmet Fayette Floyd Franklin Fremont Greene Grundy Guthrie Hamilton Hancock Hardin Harrison Henry Howard Humboldt Ida Iowa Jackson Jasper Jefferson Johnson Jones Keokuk Kossuth Lee Linn Louisa Lucas Lyon Madison Mahaska Marion Marshall Mills Mitchell Monona Monroe Montgomery Muscatine O'Brien Osceola Page Palo Alto Plymouth Pocahontas Polk Pottawattamie Poweshiek Ringgold Sac Scott Shelby Sioux Story Tama Taylor Union Van Buren Wapello Warren Washington Wayne Webster Winnebago Winneshiek Woodbury Worth Wright Ada Adams Bannock Bear Lake Benewah Bingham Blaine Boise Bonner Bonneville Boundary Butte Camas Canyon Caribou Cassia Clark Clearwater Custer Elmore Franklin Fremont Gem Gooding Idaho Jefferson Jerome Kootenai Latah Lemhi Lewis Lincoln Madison Minidoka Nez Perce Oneida Owyhee Payette Power Shoshone Teton Twin Falls Valley Washington Adams Alexander Bond Boone Brown Bureau Calhoun Carroll Cass Champaign Christian Clark Clay Clinton Coles Cook Crawford Cumberland DeKalb DeWitt Douglas DuPage Edgar Edwards Effingham Fayette Ford Franklin Fulton Gallatin Greene Grundy Hamilton Hancock Hardin Henderson Henry Iroquois Jackson Jasper Jefferson Jersey Jo Daviess Johnson Kane Kankakee Kendall Knox LaSalle Lake Lawrence Lee Livingston Logan Macon Macoupin Madison Marion Marshall Mason Massac McDonough McHenry McLean Menard Mercer Monroe Montgomery Morgan Moultrie Ogle Peoria Perry Piatt Pike Pope Pulaski Putnam Randolph Richland Rock Island St. Clair Saline Sangamon Schuyler Scott Shelby Stark Stephenson Tazewell Union Vermilion Wabash Warren Washington Wayne White Whiteside Will Williamson Winnebago Woodford Adams Allen Bartholomew Benton Blackford Boone Brown Carroll Cass Clark Clay Clinton Crawford Daviess DeKalb Dearborn Decatur Delaware Dubois Elkhart Fayette Floyd Fountain Franklin Fulton Gibson Grant Greene Hamilton Hancock Harrison Hendricks Henry Howard Huntington Jackson Jasper Jay Jefferson Jennings Johnson Knox Kosciusko LaPorte LaGrange Lake Lawrence Madison Marion Marshall Martin Miami Monroe Montgomery Morgan Newton Noble Ohio Orange Owen Parke Perry Pike Porter Posey Pulaski Putnam Randolph Ripley Rush Scott Shelby Spencer St. Joseph Starke Steuben Sullivan Switzerland Tippecanoe Tipton Union Vanderburgh Vermillion Vigo Wabash Warren Warrick Washington Wayne Wells White Whitley Allen Anderson Atchison Barber Barton Bourbon Brown Butler Chase Chautauqua Cherokee Cheyenne Clark Clay Cloud Coffey Comanche Cowley Crawford Decatur Dickinson Doniphan Douglas Edwards Elk Ellis Ellsworth Finney Ford Franklin Geary Gove Graham Grant Gray Greeley Greenwood Hamilton Harper Harvey Haskell Hodgeman Jackson Jefferson Jewell Johnson Kearny Kingman Kiowa Labette Lane Leavenworth Lincoln Linn Logan Lyon Marion Marshall McPherson Meade Miami Mitchell Montgomery Morris Morton Nemaha Neosho Ness Norton Osage Osborne Ottawa Pawnee Phillips Pottawatomie Pratt Rawlins Reno Republic Rice Riley Rooks Rush Russell Saline Scott Sedgwick Seward Shawnee Sheridan Sherman Smith Stafford Stanton Stevens Sumner Thomas Trego Wabaunsee Wallace Washington Wichita Wilson Woodson Wyandotte Adair Allen Anderson Ballard Barren Bath Bell Boone Bourbon Boyd Boyle Bracken Breathitt Breckinridge Bullitt Butler Caldwell Calloway Campbell Carlisle Carroll Carter Casey Christian Clark Clay Clinton Crittenden Cumberland Daviess Edmonson Elliott Estill Fayette Fleming Floyd Franklin Fulton Gallatin Garrard Grant Graves Grayson Green Greenup Hancock Hardin Harlan Harrison Hart Henderson Henry Hickman Hopkins Jackson Jefferson Jessamine Johnson Kenton Knott Knox Larue Laurel Lawrence Lee Leslie Letcher Lewis Lincoln Livingston Logan Lyon Madison Magoffin Marion Marshall Martin Mason McCracken McCreary McLean Meade Menifee Mercer Metcalfe Monroe Montgomery Morgan Muhlenberg Nelson Nicholas Ohio Oldham Owen Owsley Pendleton Perry Pike Powell Pulaski Robertson Rockcastle Rowan Russell Scott Shelby Simpson Spencer Taylor Todd Trigg Trimble Union Warren Washington Wayne Webster Whitley Wolfe Woodford Acadia Allen Ascension Assumption Avoyelles Beauregard Bienville Bossier Caddo Calcasieu Caldwell Cameron Catahoula Claiborne Concordia De Soto East Baton Rouge East Carroll East Feliciana Evangeline Franklin Grant Iberia Iberville Jackson Jefferson Jefferson Davis LaSalle Lafayette Lafourche Lincoln Livingston Madison Morehouse Natchitoches Orleans Ouachita Plaquemines Pointe Coupee Rapides Red River Richland Sabine St. Bernard St. Charles St. Helena St. James St. Landry St. Martin St. Mary St. Tammany St. John the Baptist Tangipahoa Tensas Terrebonne Union Vermilion Vernon Washington Webster West Baton Rouge West Carroll West Feliciana Winn Barnstable Berkshire Bristol Dukes Essex Franklin Hampden Hampshire Middlesex Nantucket Norfolk Plymouth Suffolk Worcester Allegany Anne Arundel Baltimore Baltimore City Calvert Caroline Carroll Cecil Charles Dorchester Frederick Garrett Harford Howard Kent Montgomery Prince George's Queen Anne's St. Mary's Somerset Talbot Washington Wicomico Worcester Androscoggin Aroostook Cumberland Franklin Hancock Kennebec Knox Lincoln Oxford Penobscot Piscataquis Sagadahoc Somerset Waldo Washington York Alcona Alger Allegan Alpena Antrim Arenac Baraga Barry Bay Benzie Berrien Branch Calhoun Cass Charlevoix Cheboygan Chippewa Clare Clinton Crawford Delta Dickinson Eaton Emmet Genesee Gladwin Gogebic Grand Traverse Gratiot Hillsdale Houghton Huron Ingham Ionia Iosco Iron Isabella Jackson Kalamazoo Kalkaska Kent Keweenaw Lake Lapeer Leelanau Lenawee Livingston Luce Mackinac Macomb Manistee Marquette Mason Mecosta Menominee Midland Missaukee Monroe Montcalm Montmorency Muskegon Newaygo Oakland Oceana Ogemaw Ontonagon Osceola Oscoda Otsego Ottawa Presque Isle Roscommon Saginaw St. Clair St. Joseph Sanilac Schoolcraft Shiawassee Tuscola Van Buren Washtenaw Wayne Wexford Aitkin Anoka Becker Beltrami Benton Big Stone Blue Earth Brown Carlton Carver Cass Chippewa Chisago Clay Clearwater Cook Cottonwood Crow Wing Dakota Dodge Douglas Faribault Fillmore Freeborn Goodhue Grant Hennepin Houston Hubbard Isanti Itasca Jackson Kanabec Kandiyohi Kittson Koochiching Lac qui Parle Lake Lake of the Woods Le Sueur Lincoln Lyon Mahnomen Marshall Martin McLeod Meeker Mille Lacs Morrison Mower Murray Nicollet Nobles Norman Olmsted Otter Tail Pennington Pine Pipestone Polk Pope Ramsey Red Lake Redwood Renville Rice Rock Roseau St. Louis Scott Sherburne Sibley Stearns Steele Stevens Swift Todd Traverse Wabasha Wadena Waseca Washington Watonwan Wilkin Winona Wright Yellow Medicine Adair Andrew Atchison Audrain Barry Barton Bates Benton Bollinger Boone Buchanan Butler Caldwell Callaway Camden Cape Girardeau Carroll Carter Cass Cedar Chariton Christian Clark Clay Clinton Cole Cooper Crawford Dade Dallas Daviess DeKalb Dent Douglas Dunklin Franklin Gasconade Gentry Greene Grundy Harrison Henry Hickory Holt Howard Howell Iron Jackson Jasper Jefferson Johnson Knox Laclede Lafayette Lawrence Lewis Lincoln Linn Livingston Macon Madison Maries Marion McDonald Mercer Miller Mississippi Moniteau Monroe Montgomery Morgan New Madrid Newton Nodaway Oregon Osage Ozark Pemiscot Perry Pettis Phelps Pike Platte Polk Pulaski Putnam Ralls Randolph Ray Reynolds Ripley St. Charles St. Clair St. Francois St. Louis St. Louis City Ste. Genevieve Saline Schuyler Scotland Scott Shannon Shelby Stoddard Stone Sullivan Taney Texas Vernon Warren Washington Wayne Webster Worth Wright Adams Alcorn Amite Attala Benton Bolivar Calhoun Carroll Chickasaw Choctaw Claiborne Clarke Clay Coahoma Copiah Covington DeSoto Forrest Franklin George Greene Grenada Hancock Harrison Hinds Holmes Humphreys Issaquena Itawamba Jackson Jasper Jefferson Jefferson Davis Jones Kemper Lafayette Lamar Lauderdale Lawrence Leake Lee Leflore Lincoln Lowndes Madison Marion Marshall Monroe Montgomery Neshoba Newton Noxubee Oktibbeha Panola Pearl River Perry Pike Pontotoc Prentiss Quitman Rankin Scott Sharkey Simpson Smith Stone Sunflower Tallahatchie Tate Tippah Tishomingo Tunica Union Walthall Warren Washington Wayne Webster Wilkinson Winston Yalobusha Yazoo Beaverhead Big Horn Blaine Broadwater Carbon Carter Cascade Chouteau Custer Daniels Dawson Deer Lodge Fallon Fergus Flathead Gallatin Garfield Glacier Golden Valley Granite Hill Jefferson Judith Basin Lake Lewis and Clark Liberty Lincoln Madison McCone Meagher Mineral Missoula Musselshell Park Petroleum Phillips Pondera Powder River Powell Prairie Ravalli Richland Roosevelt Rosebud Sanders Sheridan Silver Bow Stillwater Sweet Grass Teton Toole Treasure Valley Wheatland Wibaux Yellowstone Alamance Alexander Alleghany Anson Ashe Avery Beaufort Bertie Bladen Brunswick Buncombe Burke Cabarrus Caldwell Camden Carteret Caswell Catawba Chatham Cherokee Chowan Clay Cleveland Columbus Craven Cumberland Currituck Dare Davidson Davie Duplin Durham Edgecombe Forsyth Franklin Gaston Gates Graham Granville Greene Guilford Halifax Harnett Haywood Henderson Hertford Hoke Hyde Iredell Jackson Johnston Jones Lee Lenoir Lincoln Macon Madison Martin McDowell Mecklenburg Mitchell Montgomery Moore Nash New Hanover Northampton Onslow Orange Pamlico Pasquotank Pender Perquimans Person Pitt Polk Randolph Richmond Robeson Rockingham Rowan Rutherford Sampson Scotland Stanly Stokes Surry Swain Transylvania Tyrrell Union Vance Wake Warren Washington Watauga Wayne Wilkes Wilson Yadkin Yancey Adams Barnes Benson Billings Bottineau Bowman Burke Burleigh Cass Cavalier Dickey Divide Dunn Eddy Emmons Foster Golden Valley Grand Forks Grant Griggs Hettinger Kidder LaMoure Logan McHenry McIntosh McKenzie McLean Mercer Morton Mountrail Nelson Oliver Pembina Pierce Ramsey Ransom Renville Richland Rolette Sargent Sheridan Sioux Slope Stark Steele Stutsman Towner Traill Walsh Ward Wells Williams Adams Antelope Arthur Banner Blaine Boone Box Butte Boyd Brown Buffalo Burt Butler Cass Cedar Chase Cherry Cheyenne Clay Colfax Cuming Custer Dakota Dawes Dawson Deuel Dixon Dodge Douglas Dundy Fillmore Franklin Frontier Furnas Gage Garden Garfield Gosper Grant Greeley Hall Hamilton Harlan Hayes Hitchcock Holt Hooker Howard Jefferson Johnson Kearney Keith Keya Paha Kimball Knox Lancaster Lincoln Logan Loup Madison McPherson Merrick Morrill Nance Nemaha Nuckolls Otoe Pawnee Perkins Phelps Pierce Platte Polk Red Willow Richardson Rock Saline Sarpy Saunders Scotts Bluff Seward Sheridan Sherman Sioux Stanton Thayer Thomas Thurston Valley Washington Wayne Webster Wheeler York Belknap Carroll Cheshire Coos Grafton Hillsborough Merrimack Rockingham Strafford Sullivan Atlantic Bergen Burlington Camden Cape May Cumberland Essex Gloucester Hudson Hunterdon Mercer Middlesex Monmouth Morris Ocean Passaic Salem Somerset Sussex Union Warren Bernalillo Catron Chaves Cibola Colfax Curry De Baca Doña Ana Eddy Grant Guadalupe Harding Hidalgo Lea Lincoln Los Alamos Luna McKinley Mora Otero Quay Rio Arriba Roosevelt San Juan San Miguel Sandoval Santa Fe Sierra Socorro Taos Torrance Union Valencia Carson City Churchill Clark Douglas Elko Esmeralda Eureka Humboldt Lander Lincoln Lyon Mineral Nye Pershing Storey Washoe White Pine Albany Allegany Bronx Broome Cattaraugus Cayuga Chautauqua Chemung Chenango Clinton Columbia Cortland Delaware Dutchess Erie Essex Franklin Fulton Genesee Greene Hamilton Herkimer Jefferson Kings Lewis Livingston Madison Monroe Montgomery Nassau New York Niagara Oneida Onondaga Ontario Orange Orleans Oswego Otsego Putnam Queens Rensselaer Richmond Rockland St. Lawrence Saratoga Schenectady Schoharie Schuyler Seneca Steuben Suffolk Sullivan Tioga Tompkins Ulster Warren Washington Wayne Westchester Wyoming Yates Adams Allen Ashland Ashtabula Athens Auglaize Belmont Brown Butler Carroll Champaign Clark Clermont Clinton Columbiana Coshocton Crawford Cuyahoga Darke Defiance Delaware Erie Fairfield Fayette Franklin Fulton Gallia Geauga Greene Guernsey Hamilton Hancock Hardin Harrison Henry Highland Hocking Holmes Huron Jackson Jefferson Knox Lake Lawrence Licking Logan Lorain Lucas Madison Mahoning Marion Medina Meigs Mercer Miami Monroe Montgomery Morgan Morrow Muskingum Noble Ottawa Paulding Perry Pickaway Pike Portage Preble Putnam Richland Ross Sandusky Scioto Seneca Shelby Stark Summit Trumbull Tuscarawas Union Van Wert Vinton Warren Washington Wayne Williams Wood Wyandot Adair Alfalfa Atoka Beaver Beckham Blaine Bryan Caddo Canadian Carter Cherokee Choctaw Cimarron Cleveland Coal Comanche Cotton Craig Creek Custer Delaware Dewey Ellis Garfield Garvin Grady Grant Greer Harmon Harper Haskell Hughes Jackson Jefferson Johnston Kay Kingfisher Kiowa Latimer Le Flore Lincoln Logan Love Major Marshall Mayes McClain McCurtain McIntosh Murray Muskogee Noble Nowata Okfuskee Oklahoma Okmulgee Osage Ottawa Pawnee Payne Pittsburg Pontotoc Pottawatomie Pushmataha Roger Mills Rogers Seminole Sequoyah Stephens Texas Tillman Tulsa Wagoner Washington Washita Woods Woodward Baker Benton Clackamas Clatsop Columbia Coos Crook Curry Deschutes Douglas Gilliam Grant Harney Hood River Jackson Jefferson Josephine Klamath Lake Lane Lincoln Linn Malheur Marion Morrow Multnomah Polk Sherman Tillamook Umatilla Union Wallowa Wasco Washington Wheeler Yamhill Adams Allegheny Armstrong Beaver Bedford Berks Blair Bradford Bucks Butler Cambria Cameron Carbon Centre Chester Clarion Clearfield Clinton Columbia Crawford Cumberland Dauphin Delaware Elk Erie Fayette Forest Franklin Fulton Greene Huntingdon Indiana Jefferson Juniata Lackawanna Lancaster Lawrence Lebanon Lehigh Luzerne Lycoming McKean Mercer Mifflin Monroe Montgomery Montour Northampton Northumberland Perry Philadelphia Pike Potter Schuylkill Snyder Somerset Sullivan Susquehanna Tioga Union Venango Warren Washington Wayne Westmoreland Wyoming York Bristol Kent Newport Providence Washington Abbeville Aiken Allendale Anderson Bamberg Barnwell Beaufort Berkeley Calhoun Charleston Cherokee Chester Chesterfield Clarendon Colleton Darlington Dillon Dorchester Edgefield Fairfield Florence Georgetown Greenville Greenwood Hampton Horry Jasper Kershaw Lancaster Laurens Lee Lexington Marion Marlboro McCormick Newberry Oconee Orangeburg Pickens Richland Saluda Spartanburg Sumter Union Williamsburg York Aurora Beadle Bennett Bon Homme Brookings Brown Brule Buffalo Butte Campbell Charles Mix Clark Clay Codington Corson Custer Davison Day Deuel Dewey Douglas Edmunds Fall River Faulk Grant Gregory Haakon Hamlin Hand Hanson Harding Hughes Hutchinson Hyde Jackson Jerauld Jones Kingsbury Lake Lawrence Lincoln Lyman Marshall McCook McPherson Meade Mellette Miner Minnehaha Moody Oglala Lakota Pennington Perkins Potter Roberts Sanborn Shannon Spink Stanley Sully Todd Tripp Turner Union Walworth Yankton Ziebach Anderson Bedford Benton Bledsoe Blount Bradley Campbell Cannon Carroll Carter Cheatham Chester Claiborne Clay Cocke Coffee Crockett Cumberland Davidson Decatur DeKalb Dickson Dyer Fayette Fentress Franklin Gibson Giles Grainger Greene Grundy Hamblen Hamilton Hancock Hardeman Hardin Hawkins Haywood Henderson Henry Hickman Houston Humphreys Jackson Jefferson Johnson Knox Lake Lauderdale Lawrence Lewis Lincoln Loudon Macon Madison Marion Marshall Maury McMinn McNairy Meigs Monroe Montgomery Moore Morgan Obion Overton Perry Pickett Polk Putnam Rhea Roane Robertson Rutherford Scott Sequatchie Sevier Shelby Smith Stewart Sullivan Sumner Tipton Trousdale Unicoi Union Van Buren Warren Washington Wayne Weakley White Williamson Wilson Anderson Andrews Angelina Aransas Archer Armstrong Atascosa Austin Bailey Bandera Bastrop Baylor Bee Bell Bexar Blanco Borden Bosque Bowie Brazoria Brazos Brewster Briscoe Brooks Brown Burleson Burnet Caldwell Calhoun Callahan Cameron Camp Carson Cass Castro Chambers Cherokee Childress Clay Cochran Coke Coleman Collin Collingsworth Colorado Comal Comanche Concho Cooke Coryell Cottle Crane Crockett Crosby Culberson Dallam Dallas Dawson DeWitt Deaf Smith Delta Denton Dickens Dimmit Donley Duval Eastland Ector Edwards El Paso Ellis Erath Falls Fannin Fayette Fisher Floyd Foard Fort Bend Franklin Freestone Frio Gaines Galveston Garza Gillespie Glasscock Goliad Gonzales Gray Grayson Gregg Grimes Guadalupe Hale Hall Hamilton Hansford Hardeman Hardin Harris Harrison Hartley Haskell Hays Hemphill Henderson Hidalgo Hill Hockley Hood Hopkins Houston Howard Hudspeth Hunt Hutchinson Irion Jack Jackson Jasper Jeff Davis Jefferson Jim Hogg Jim Wells Johnson Jones Karnes Kaufman Kendall Kenedy Kent Kerr Kimble King Kinney Kleberg Knox La Salle Lamar Lamb Lampasas Lavaca Lee Leon Liberty Limestone Lipscomb Live Oak Llano Loving Lubbock Lynn Madison Marion Martin Mason Matagorda Maverick McCulloch McLennan McMullen Medina Menard Midland Milam Mills Mitchell Montague Montgomery Moore Morris Motley Nacogdoches Navarro Newton Nolan Nueces Ochiltree Oldham Orange Palo Pinto Panola Parker Parmer Pecos Polk Potter Presidio Rains Randall Reagan Real Red River Reeves Refugio Roberts Robertson Rockwall Runnels Rusk Sabine San Augustine San Jacinto San Patricio San Saba Schleicher Scurry Shackelford Shelby Sherman Smith Somervell Starr Stephens Sterling Stonewall Sutton Swisher Tarrant Taylor Terrell Terry Throckmorton Titus Tom Green Travis Trinity Tyler Upshur Upton Uvalde Val Verde Van Zandt Victoria Walker Waller Ward Washington Webb Wharton Wheeler Wichita Wilbarger Willacy Williamson Wilson Winkler Wise Wood Yoakum Young Zapata Zavala Beaver Box Elder Cache Carbon Daggett Davis Duchesne Emery Garfield Grand Iron Juab Kane Millard Morgan Piute Rich Salt Lake San Juan Sanpete Sevier Summit Tooele Uintah Utah Wasatch Washington Wayne Weber Accomack Albemarle Alexandria City Alleghany Amelia Amherst Appomattox Arlington Augusta Bath Bedford Bedford City Bland Botetourt Bristol City Brunswick Buchanan Buckingham Buena Vista City Campbell Caroline Carroll Charles City Charlotte Charlottesville City Chesapeake City Chesterfield Clarke Clifton Forge City Colonial Heights City Covington City Craig Culpeper Cumberland Danville City Dickenson Dinwiddie Emporia City Essex Fairfax Fairfax City Falls Church City Fauquier Floyd Fluvanna Franklin Franklin City Frederick Fredericksburg City Galax City Giles Gloucester Goochland Grayson Greene Greensville Halifax Hampton City Hanover Harrisonburg City Henrico Henry Highland Hopewell City Isle of Wight James City King and Queen King George King William Lancaster Lee Lexington City Loudoun Louisa Lunenburg Lynchburg City Madison Manassas City Manassas Park City Martinsville City Mathews Mecklenburg Middlesex Montgomery Nelson New Kent Newport News City Norfolk City Northampton Northumberland Norton City Nottoway Orange Page Patrick Petersburg City Pittsylvania Poquoson City Portsmouth City Powhatan Prince Edward Prince George Prince William Pulaski Radford City Rappahannock Richmond Richmond City Roanoke Roanoke City Rockbridge Rockingham Russell Salem City Scott Shenandoah Smyth Southampton Spotsylvania Stafford Staunton City Suffolk City Surry Sussex Tazewell Virginia Beach City Warren Washington Waynesboro City Westmoreland Williamsburg City Winchester City Wise Wythe York Addison Bennington Caledonia Chittenden Essex Franklin Grand Isle Lamoille Orange Orleans Rutland Washington Windham Windsor Adams Asotin Benton Chelan Clallam Clark Columbia Cowlitz Douglas Ferry Franklin Garfield Grant Grays Harbor Island Jefferson King Kitsap Kittitas Klickitat Lewis Lincoln Mason Okanogan Pacific Pend Oreille Pierce San Juan Skagit Skamania Snohomish Spokane Stevens Thurston Wahkiakum Walla Walla Whatcom Whitman Yakima Adams Ashland Barron Bayfield Brown Buffalo Burnett Calumet Chippewa Clark Columbia Crawford Dane Dodge Door Douglas Dunn Eau Claire Florence Fond du Lac Forest Grant Green Green Lake Iowa Iron Jackson Jefferson Juneau Kenosha Kewaunee La Crosse Lafayette Langlade Lincoln Manitowoc Marathon Marinette Marquette Menominee Milwaukee Monroe Oconto Oneida Outagamie Ozaukee Pepin Pierce Polk Portage Price Racine Richland Rock Rusk St. Croix Sauk Sawyer Shawano Sheboygan Taylor Trempealeau Vernon Vilas Walworth Washburn Washington Waukesha Waupaca Waushara Winnebago Wood Barbour Berkeley Boone Braxton Brooke Cabell Calhoun Clay Doddridge Fayette Gilmer Grant Greenbrier Hampshire Hancock Hardy Harrison Jackson Jefferson Kanawha Lewis Lincoln Logan Marion Marshall Mason McDowell Mercer Mineral Mingo Monongalia Monroe Morgan Nicholas Ohio Pendleton Pleasants Pocahontas Preston Putnam Raleigh Randolph Ritchie Roane Summers Taylor Tucker Tyler Upshur Wayne Webster Wetzel Wirt Wood Wyoming Albany Big Horn Campbell Carbon Converse Crook Fremont Goshen Hot Springs Johnson Laramie Lincoln Natrona Niobrara Park Platte Sheridan Sublette Sweetwater Teton Uinta Washakie Weston Alagnak National Wild and Scenic River Alagnak River + Katmai National Park Alatna National Wild and Scenic River Aleutian World War II National Historic Area Aniachak National Wild and Scenic River Aniakchak Nat'l Preserve and Monument Aniakchak National Monument Aniakchak National Preserve Aniakchak River + Aniakchak National Monument Aniakchak River + Aniakchak National Preserve Bering Land Bridge National Preserve Cape Krusenstern National Monument Charley National Wild and Scenic River Chilikadrotna National Wild and Scenic River Chilikadrotna River + Lake Clark National Preserve Denali National Park Denali NP + Denali National Preserve Denali Preserve National Preserve Gates of the Arctic National Park Gates of the Arctic National Preserve Gates of the Arctic NP + Gates of the Arctic National Preserve Gates of the Arctic NP + Noatak National Preserve Glacier Bay National Park Glacier Bay National Preserve Glacier Bay NP + Glacier Bay National Preserve Inupiat Heritage Center John National Wild and Scenic River John River + Gates of The Arctic NP Katmai National Park Katmai National Preserve Katmai NP + Katmai National Preserve Kenai Fjords National Park Klondike Gold Rush National Historical Park Kobuk National Wild and Scenic River Kobuk River + Gates of The Arctic National Preserve Kobuk River + Gates of The Arctic NP Kobuk River + Kobuk Valley NP Kobuk Valley National Park Koyukuk National Wild and Scenic River (North Fork) Koyukuk River (North Fork) + Gates of The Arctic NP Lake Clark National Park Lake Clark National Preserve Lake Clark NP + Lake Clark National Preserve Mulchanta River + Lake Clark National Preserve Mulchanta River + Lake Clark NP Mulchatna National Wild and Scenic River Noatak National Preserve Noatak National Wild and Scenic River Noatak River + Gates of The Arctic NP Noatak River + Noatak National Preserve Salmon National Wild and Scenic River Salmon River + kobuk Valley NP Sitka National Historical Park Tinayguk National Wild and Scenic River Tinayguk River + Gates of The Arctic NP Tlikakila National Wild and Scenic River Tlikakila River + Lake Clark NP Wrangell-St. Elias National Park Wrangell-St. Elias National Preserve Wrangell-St. Elias NP + Wrangell-St. Elias National Preserve Yukon-Charley Rivers National Preserve Yukon-Charley Rivers Preserve + Charley River Horseshoe Bend National Military Park Little River Canyon National Preserve Natchez Trace Parkway Russell Cave National Monument Selma to Montgomery National Historic Trail Trail of Tears National Historic Trail Trail of Tears NHT + Little River Canyon PV Tuskegee Airmen National Historic Site Tuskegee Institute National Historic Site Arkansas Post National Memorial Buffalo National River Fort Smith National Historic Site Hot Springs National Park Little Rock Central High School National Historic Site Pea Ridge National Military Park President William Jefferson Clinton Birthplace Home National Historic Site Trail of Tears National Historic Trail Trail of Tears NHT + Arkansas Post NM Trail of Tears NHT + Fort Smith NHS Trail of Tears NHT + Pea Ridge NMP Canyon de Chelly National Monument Casa Grande Ruins National Monument Chiricahua National Monument Coronado National Memorial Fort Bowie National Historic Site Glen Canyon National Recreation Area Glen Canyon Rec Area + Rainbow Bridge National Monument Grand Canyon National Park Hohokam Pima National Monument Hubbell Trading Post National Historic Site Juan Bautista de Anza National Historic Trail Juan Bautista de Anza NHT + Tumacacori NHP Lake Mead National Recreation Area Montezuma Castle National Monument Navajo National Monument Old Spanish National Historic Trail Organ Pipe Cactus National Monument Petrified Forest National Park Pipe Spring National Monument Saguaro National Park Sunset Crater Volcano National Monument Tonto National Monument Tumacacori National Historical Park Tuzigoot National Monument Walnut Canyon National Monument Wupatki National Monument Cabrillo National Monument California National Historic Trail California NHT + Golden Gate NRA California NHT + Lassen Volcanic NP California NHT + Pony Express NHT Castle Mountains National Monument Cesar E. Chavez National Monument Channel Islands National Park Death Valley National Park Devils Postpile National Monument Eugene O'Neill National Historic Site Fort Point National Historic Site Golden Gate National Recreation Area Golden Gate Rec Area + Fort Point NHS Golden Gate Rec Area + Muir Woods NM John Muir National Historic Site Joshua Tree National Park Juan Bautista de Anza National Historic Trail Juan Bautista de Anza National Historic Trail + Golden Gate NRA + Fort Point NHS Juan Bautista de Anza National Historic Trail + Golden Gate NRA + Muir Woods NM Juan Bautista de Anza NHT + California NHT Juan Bautista de Anza NHT + Golden Gate NRA Juan Bautista de Anza NHT + John Muir NHS Juan Bautista de Anza NHT + Old Spanish NHT Juan Bautista de Anza NHT + Santa Monica Mountains NRA Kern National Wild and Scenic River Kern River + Sequoia NP Kings Canyon National Park Kings National Wild and Scenic River Kings River + Kings Canyon NP Lassen Volcanic National Park Lava Beds National Monument Manzanar National Historic Site Merced National Wild and Scenic River Merced River + Yosemite NP Mojave National Preserve Muir Woods National Monument Old Spanish National Historic Trail Old Spanish NHT + Mojave Natioal Preserve Pinnacles National Park Point Reyes National Seashore Pony Express National Historic Trail Pony Express NHT + Golden Gate NRA Port Chicago Naval Magazine National Memorial Redwood National Park Rosie the Riveter/World War II Home Front National Historical Park San Francisco Maritime National Historical Park Santa Monica Mountains National Recreation Area Sequoia National Park Tule Lake Unit Internment Camp National Monument Tuolumne National Wild and Scenic River Tuolumne River + Yosemite NP Whiskeytown Unit National Recreation Area Yosemite National Park Bent's Old Fort National Historic Site Black Canyon of the Gunnison National Park California National Historic Trail Colorado National Monument Curecanti National Recreation Area Dinosaur National Monument Florissant Fossil Beds National Monument Great Sand Dunes National Park Great Sand Dunes National Preserve Great Sand Dunes NP and Great Sand Dunes National Preserve Hovenweep National Monument Mesa Verde National Park Old Spanish National Historic Trail Old Spanish NHT + Colorado NM Old Spanish NHT + Curecanti NRA Old Spanish NHT + Great Sand Dunes National Preserve Old Spanish NHT + Great Sand Dunes NP and Preserve Pony Express National Historic Trail Rocky Mountain National Park Sand Creek Massacre National Historic Site Santa Fe National Historic Trail Santa Fe NHT + Bent's Old Fort NHS Yucca House National Monument Appalachian National Scenic Trail Eightmile National Wild and Scenic River Farmington National Wild and Scenic River New England National Scenic Trail New England NST + Washington-Rochambeau Revolutionary Route NHT Washington-Rochambeau Revolutionary Route National Historic Trail Weir Farm National Historic Site Captain John Smith Chesapeake National Historic Trail Carter G. Woodson Home National Historic Site Chesapeake and Ohio Canal National Historical Park Constitution Gardens Ford's Theatre National Historic Site Franklin Delano Roosevelt Memorial National Memorial Frederick Douglass National Historic Site George Washington Memorial Parkway Korean War Veterans National Memorial Lincoln Memorial National Memorial Lyndon Baines Johnson Memorial Grove on the Potomac National Memorial Martin Luther King, Jr. National Memorial Mary McLeod Bethune Council House National Historic Site Mary McLeod Bethune Council House NHS + Carter G. Woodson Home NHS National Capital Parks National Mall Pennsylvania Avenue National Historic Site Potomac Heritage National Scenic Trail Rock Creek Park Sewall-Belmont House National Historic Site Star-Spangled Banner National Historic Trail Theodore Roosevelt Island National Memorial Thomas Jefferson Memorial National Memorial Vietnam Veterans Memorial National Memorial Washington Monument National Memorial Washington-Rochambeau Revolutionary Route National Historic Trail Washington-Rochambeau Revolutionary Route NHT + George Washington Memorial Parkway White House World War I Memorial National Memorial World War II Memorial National Memorial Captain John Smith Chesapeake National Historic Trail First State National Historical Park Washington-Rochambeau Revolutionary Route National Historic Trail White Clay Creek National Wild and Scenic River Big Cypress National Preserve Biscayne National Park Canaveral National Seashore Castillo de San Marcos National Monument De Soto National Memorial Dry Tortugas National Park Everglades National Park Fort Caroline National Memorial Fort Caroline National Memorial + Timucuan Ecological and Historic Preserve Fort Matanzas National Monument Gulf Islands National Seashore Timucuan Ecological and Historic Preserve National Preserve Wekiva National Wild and Scenic River Andersonville National Historic Site Appalachian National Scenic Trail Chattahoochee River National Recreation Area Chickamauga and Chattanooga National Military Park Cumberland Island National Seashore Fort Frederica National Monument Fort Pulaski National Monument Jimmy Carter National Historic Site Kennesaw Mountain National Battlefield Park Martin Luther King, Jr. National Historic Site Ocmulgee National Monument Trail of Tears National Historic Trail Trail of Tears NHT + Chickamauga and Chattanooga NMP Ala Kahakai National Historic Trail Ala Kahakai NHT + Hawaii Volcanoes NP Ala Kahakai NHT + Kaloko-Honokohau NHP Ala Kahakai NHT + Pu'uhonua o Honaunau NHP Ala Kahakai NHT + Puukohola Heiau NHS Haleakala National Park Hawaii Volcanoes National Park Honouliuli National Monument Kalaupapa National Historical Park Kaloko-Honokohau National Historical Park Pu'uhonua o Honaunau National Historical Park Puukohola Heiau National Historic Site World War II Valor in the Pacific National Monument Effigy Mounds National Monument Herbert Hoover National Historic Site Lewis and Clark National Historic Trail Mormon Pioneer National Historic Trail Mormon Pioneer NHT + Lewis and Clark NHT California National Historic Trail California NHT + City of Rocks NR City of Rocks National Reserve Craters Of The Moon National Monument Craters of the Moon National Monument and Preserve Craters Of The Moon National Preserve Hagerman Fossil Beds National Monument Lewis and Clark National Historic Trail Lewis and Clark NHT + Nez Perce NHP Minidoka National Historic Site Nez Perce National Historical Park Oregon National Historic Trail Oregon NHT + California NHT Oregon NHT + Hagerman Fossil Beds NM Yellowstone National Park Chicago Portage National Historic Site Lewis and Clark National Historic Trail Lincoln Home National Historic Site Mormon Pioneer National Historic Trail Pullman National Monument Trail of Tears National Historic Trail George Rogers Clark National Historical Park Indiana Dunes National Lakeshore Lincoln Boyhood National Memorial Brown v. Board of Education National Historic Site California National Historic Trail California NHT + Oregon NHT + Pony Express NHT California NHT + Pony Express NHT Fort Larned National Historic Site Fort Scott National Historic Site Lewis and Clark + California NHT+ Pony Express NHT Lewis and Clark National Historic Trail Lewis and Clark NHT+ California NHT Nicodemus National Historic Site Oregon National Historic Trail Oregon NHT + California NHT Oregon NHT + Santa Fe NHT + California NHT Pony Express National Historic Trail Santa Fe National Historic Trail Santa Fe NHT + California NHT Santa Fe NHT + Fort Larned NHS Tallgrass Prairie National Preserve Abraham Lincoln Birthplace National Historical Park Big South Fork National River and Recreation Area Cumberland Gap National Historical Park Mammoth Cave National Park Trail of Tears National Historic Trail Cane River Creole NHP and Heritage Area National Historical Park El Camino Real de los Tejas National Historic Trail Jean Lafitte NHP and Preserve National Historical Park New Orleans Jazz National Historical Park Poverty Point National Monument Adams National Historical Park Appalachian National Scenic Trail Blackstone River Valley National Historical Park Boston National Historical Park Boston African American National Historic Site Boston Harbor Islands National Recreation Area Cape Cod National Seashore Frederick Law Olmsted National Historic Site John Fitzgerald Kennedy National Historic Site Longfellow House - Washington's Headquarters National Historic Site Lowell National Historical Park Minute Man National Historical Park New Bedford Whaling National Historical Park New England National Scenic Trail Salem Maritime National Historic Site Saugus Iron Works National Historic Site Springfield Armory National Historic Site Sudbury, Assabet and Concord National Wild and Scenic River Taunton National Wild and Scenic River Washington-Rochambeau Revolutionary Route National Historic Trail Washington-Rochambeau Revolutionary Route NHT + Boston Harbor Islands NRA Westfield National Wild and Scenic River Antietam National Battlefield Appalachian National Scenic Trail Appalachian Trail + Potomac Heritage NST + Chesapeake and Ohio Canal Assateague Island National Seashore Captain John Smith Chesapeake National Historic Trail Captain John Smith Chesapeake NHT + Fort McHenry NM and Shrine Captain John Smith Chesapeake NHT + Piscataway Park Captain John Smith Chesapeake NHT + Star-Spangled Banner NHT Catoctin Mountain Park Chesapeake and Ohio Canal National Historical Park Clara Barton National Historic Site Fort McHenry National Monument and Historic Shrine Fort Washington Park George Washington Memorial Parkway Greenbelt Park Hampton National Historic Site Harpers Ferry National Historical Park Harriet Tubman Underground Railroad National Monument Monocacy National Battlefield National Capital Parks Piscataway Park Potomac Heritage National Scenic Trail Star-Spangled Banner National Historic Trail Thomas Stone National Historic Site Washington-Rochambeau Revolutionary Route National Historic Trail Washington-Rochambeau Revolutionary Route NHT + Star-Spangled Banner NHT Washington-Rochambeau Revolutionary Route NHT + Star-Spangled Banner NHT + Fort McHenry NM Acadia National Park Appalachian National Scenic Trail Katahdin Woods and Waters National Monument Saint Croix Island International Historic Site Father Marquette National Memorial Isle Royale National Park Keweenaw National Historical Park North Country National Scenic Trail North Country NST + Father Marquette National Memorial North Country NST + Pictured Rocks National Lakeshore Pictured Rocks National Lakeshore River Raisin National Battlefield Park Sleeping Bear Dunes National Lakeshore Grand Portage National Monument Mississippi National River and Recreation Areas North Country National Scenic Trail Pipestone National Monument Saint Croix National Scenic Riverway Voyageurs National Park California National Historic Trail California NHT + Pony Express NHT George Washington Carver National Monument Harry S Truman National Historic Site Jefferson National Expansion Memorial National Memorial Lewis and Clark National Historic Trail Lewis and Clark NHT + Pony Express NHT Lewis and Clark NHT+ California NHT Oregon National Historic Trail Oregon NHT + California NHT Oregon NHT + Lewis and Clark NHT Oregon NHT + Santa Fe NHT + California NHT Ozark National Scenic Riverways Pony Express National Historic Trail Santa Fe National Historic Trail Santa Fe NHT + California NHT Trail of Tears National Historic Trail Ulysses S. Grant National Historic Site Wilson's Creek National Battlefield Brices Cross Roads National Battlefield Site Gulf Islands National Seashore Natchez National Historical Park Natchez Trace National Scenic Trail Natchez Trace Parkway Shiloh National Military Park Tupelo National Battlefield Vicksburg National Military Park Big Hole National Battlefield Bighorn Canyon National Recreation Area Flathead National Wild and Scenic River Flathead River + Glacier NP Fort Union Trading Post National Historic Site Glacier National Park Grant-Kohrs Ranch National Historic Site Lewis and Clark National Historic Trail Lewis and Clark NHT + Fort Union Trading Post NHS Lewis and Clark NHT + Nez Perce NHP Lewis and Clark NHT + Nez Perce NHP + Big Hole BF Little Bighorn Battlefield National Monument Nez Perce National Historical Park Nez Perce NHP + Big Hole BF Yellowstone National Park Appalachian National Scenic Trail Blue Ridge Parkway Blue Ridge Parkway + Great Smoky Mountain NP Cape Hatteras National Seashore Cape Lookout National Seashore Carl Sandburg Home National Historic Site Fort Raleigh National Historic Site Great Smoky Mountains National Park Guilford Courthouse National Military Park Moores Creek National Battlefield Overmountain Victory National Historic Trail Overmountain Victory NHT + Blue Ridge Parkway Trail of Tears National Historic Trail Wright Brothers National Memorial Fort Union Trading Post National Historic Site International Peace Garden Knife River Indian Villages National Historic Site Lewis and Clark National Historic Trail Lewis and Clark NHT + Fort Union Trading Post NHS Lewis and Clark NHT + Knife River Indian Villages NHS North Country National Scenic Trail North Country NHT + Lewis and Clark NHT Theodore Roosevelt National Park Agate Fossil Beds National Monument California National Historic Trail California NHT + Chimney Rock NHS California NHT + Oregon NHT + Pony Express NHT California NHT + Scotts Bluff MN Chimney Rock National Historic Site Homestead NM of America National Monument Lewis and Clark + California NHT+ Pony Express NHT Lewis and Clark National Historic Trail Lewis and Clark NHT + Missouri National Recreational River Lewis and Clark NHT+ California NHT Missouri National Recreational River Mormon Pioneer National Historic Trail Mormon Pioneer NHT + California NHT Mormon Pioneer NHT + Lewis and Clark NHT Niobrara National Wild and Scenic River Oregon National Historic Trail Oregon NHT + Mormon Pioneer NHT + California NHT + Pony Express NHT Oregon NHT + Mormon Pioneer NHT + California NHT + Pony Express NHT + Chimney Rock NHS Oregon NHT + Mormon Pioneer NHT + California NHT + Pony Express NHT + Scotts Bluff MN Oregon NHT + Santa Fe NHT + California NHT Pony Express National Historic Trail Pony Express NHT + Chimney Rock NHS Pony Express NHT + Scotts Bluff MN Scotts Bluff National Monument Appalachian National Scenic Trail Lamprey National Wild and Scenic River Saint-Gaudens National Historic Site Appalachian National Scenic Trail Appalachian National ScenicTrail + Delaware National Scenic River Appalachian National ScenicTrail + Delaware Water Gap Delaware National Scenic River Delaware Water Gap National Recreation Area Gateway National Recreation Area Great Egg Harbor National Scenic and Recreational River Maurice National Scenic and Recreational River Morristown National Historical Park Musconetcong National Wild and Scenic River New Jersey Coastal Heritage Trail Route New Jersey Coastal Heritage Trail Route + Great Egg Harbor National Scenic River New Jersey Coastal Heritage Trail Route + Maurice National Scenic River New Jersey Coastal Heritage Trail Route + Pinelands National Reserve New Jersey Coastal Heritage Trail Route + Pinelands National Reserve + Great Egg Harbor National Scenic River Paterson Great Falls National Historical Park Pinelands National Reserve Pinelands National Reserve + Great Egg Harbor National Scenic River Statue of Liberty National Monument Thomas Edison National Historical Park Washington-Rochambeau Revolutionary Route National Historic Trail Washington-Rochambeau Revolutionary Route NHT + Morristown Aztec Ruins National Monument Bandelier National Monument Capulin Volcano National Monument Carlsbad Caverns National Park Chaco Culture National Historical Park El Camino Real de Tierra Adentro National Historic Trail El Malpais National Monument El Morro National Monument Fort Union National Monument Gila Cliff Dwellings National Monument Manhattan Project National Historical Park Old Spanish National Historic Trail Old Spanish NHT + Aztec Ruins NM Pecos National Historical Park Petroglyph National Monument Salinas Pueblo Missions National Monument Santa Fe National Historic Trail Santa Fe NHT + Fort Union NM Santa Fe NHT + Pecos NHP Valles Caldera National Preserve White Sands National Monument California National Historic Trail California NHT + Pony Express NHT Death Valley National Park Great Basin National Park Lake Mead National Recreation Area Old Spanish National Historic Trail Old Spanish NHT + Lake Mead NRA Pony Express National Historic Trail Tule Springs Fossil Beds National Monument African Burial Ground National Monument Appalachian National Scenic Trail Captain John Smith Chesapeake National Historic Trail Castle Clinton National Monument Delaware National Scenic River Eleanor Roosevelt National Historic Site Federal Hall National Memorial Fire Island National Seashore Fort Stanwix National Monument Gateway National Recreation Area General Grant National Memorial Governors Island National Monument Hamilton Grange National Memorial Home of Franklin D. Roosevelt National Historic Site Kate Mullany National Historic Site Lower East Side Tenement National Historic Site Martin Van Buren National Historic Site North Country National Scenic Trail North Country NST + Fort Stanwix NM Sagamore Hill National Historic Site Saint Paul's Church National Historic Site Saratoga National Historical Park Statue of Liberty National Monument Stonewall National Monument Theodore Roosevelt Birthplace National Historic Site Theodore Roosevelt Inaugural National Historic Site Thomas Cole National Historic Site Upper Delaware Scenic and Recreation River Vanderbilt Mansion National Historic Site Washington-Rochambeau Revolutionary Route National Historic Trail Women's Rights National Historical Park Charles Young Buffalo Soldiers National Monument Cuyahoga Valley National Park Dayton Aviation Heritage National Historical Park Fallen Timbers Battlefield and Fort Miamis National Historic Site First Ladies National Historic Site Hopewell Culture National Historical Park James A. Garfield National Historic Site North Country National Scenic Trail North Country NST + Dayton Aviation Heritage NHP Perry's Victory and International Peace Memorial National Memorial William Howard Taft National Historic Site Chickasaw National Recreation Area Oklahoma City National Memorial Santa Fe National Historic Trail Trail of Tears National Historic Trail Trail of Tears NHT + Fort Smith NHS Washita Battlefield National Historic Site California National Historic Trail Crater Lake National Park Fort Vancouver National Historic Site John Day Fossil Beds National Monument Lewis and Clark National Historical Park Lewis and Clark National Historic Trail Lewis and Clark NHT + Lewis and Clark NHP Lewis and Clark NHT + Nez Perce NHP Nez Perce National Historical Park Oregon Caves National Monument Oregon National Historic Trail Oregon NHT + Lewis and Clark NHT Allegheny Portage Railroad National Historic Site Appalachian National Scenic Trail Appalachian National ScenicTrail + Delaware National Scenic River Appalachian National ScenicTrail + Delaware Water Gap Benjamin Franklin National Memorial Captain John Smith Chesapeake National Historic Trail Delaware National Scenic River Delaware Water Gap National Recreation Area Edgar Allan Poe National Historic Site Eisenhower National Historic Site First State National Historical Park Flight 93 National Memorial Fort Necessity National Battlefield Friendship Hill National Historic Site Gettysburg National Military Park Gloria Dei (Old Swedes') Church National Historic Site Hopewell Furnace National Historic Site Independence National Historical Park Johnstown Flood National Memorial North Country National Scenic Trail Potomac Heritage National Scenic Trail Steamtown National Historic Site Thaddeus Kosciuszko National Memorial Upper Delaware Scenic and Recreation River Valley Forge National Historical Park Washington-Rochambeau Revolutionary Route National Historic Trail Washington-Rochambeau Revolutionary Route NHT + Independence HP White Clay Creek National Wild and Scenic River Blackstone River Valley National Historical Park Roger Williams National Memorial Touro Synagogue National Historic Site Washington-Rochambeau Revolutionary Route National Historic Trail Appalachian Trail + Overmountain Men Victory Trail Charles Pinckney National Historic Site Congaree National Park Cowpens National Battlefield Fort Sumter National Monument Historic Camden Revolutionary War Site Kings Mountain National Military Park Ninety Six National Historic Site Overmountain Victory National Historic Trail Overmountain Victory NHT + Cowpens BF Overmountain Victory NHT + Kings Mountain MP Badlands National Park Jewel Cave National Monument Lewis and Clark National Historic Trail Lewis and Clark NHT + Missouri National Recreational River Minuteman Missile National Historic Site Missouri National Recreational River Mount Rushmore National Memorial Wind Cave National Park Andrew Johnson National Historic Site Appalachian National Scenic Trail Appalachian National ScenicTrail + Great Smoky Mountains NP Appalachian Trail + Overmountain Men Victory Trail Big South Fork National River and Recreation Area Chickamauga and Chattanooga National Military Park Cumberland Gap National Historical Park Fort Donelson National Battlefield Great Smoky Mountains National Park Manhattan Project National Historical Park Natchez Trace National Scenic Trail Natchez Trace Parkway Obed National Wild and Scenic River Overmountain Victory National Historic Trail Shiloh National Military Park Stones River National Battlefield Trail of Tears National Historic Trail Trail of Tears NHT + Chickamauga and Chattanooga NMP Trail of Tears NHT + Stones River BF Alibates Flint Quarries National Monument Amistad National Recreation Area Big Bend National Park Big Thicket National Preserve Chamizal National Memorial El Camino Real de los Tejas National Historic Trail El Camino Real de los Tejas NHT + San Antonio Missions NHP El Camino Real de Tierra Adentro National Historic Trail El Camino Real de Tierra Adentro NHT + Chamizal NM Fort Davis National Historic Site Guadalupe Mountains National Park Lake Meredith National Recreation Area Lyndon B. Johnson National Historical Park Padre Island National Seashore Palo Alto Battlefield National Historical Park Rio Grande River + Big Bend NP Rio Grande Wild and Scenic River San Antonio Missions National Historical Park Santa Fe National Historic Trail Waco Mammoth National Monument Arches National Park Bryce Canyon National Park California National Historic Trail California NHT + Pony Express NHT Canyonlands National Park Capitol Reef National Park Cedar Breaks National Monument Dinosaur National Monument Glen Canyon National Recreation Area Golden Spike National Historic Site Hovenweep National Monument Mormon Pioneer National Historic Trail Mormon Pioneer NHT + California NHT + Pony Express NHT Mormon Pioneer NHT + California NHT Mormon Pioneer NHT + Pony Express NHT Natural Bridges National Monument Old Spanish National Historic Trail Old Spanish NHT + Arches NP Pony Express National Historic Trail Rainbow Bridge National Monument Timpanogos Cave National Monument Virgin National Wild and Scenic River Virgin River + Zion NP Zion National Park Appalachian National Scenic Trail Appalachian National ScenicTrail + Shenandoah NP Appomattox Court House National Historical Park Arlington House National Memorial Assateague Island National Seashore Blue Ridge Parkway Booker T. Washington National Monument Captain John Smith Chesapeake National Historic Trail Captain John Smith Chesapeake NHT + Colonial NHP Captain John Smith Chesapeake NHT + George Washington Birthplace Captain John Smith Chesapeake NHT + Richmond NBP Captain John Smith Chesapeake NHT + Star-Spangled Banner NHT + George Washington Memorial Parkway Cedar Creek and Belle Grove National Historical Park Colonial National Historical Park Cumberland Gap National Historical Park Fort Monroe National Monument Fredericksburg and Spotsylvania County Battlefields Memorial National Military Park George Washington Birthplace National Monument George Washington Memorial Parkway Green Springs National Historic Landmark District Harpers Ferry National Historical Park Jamestown + Colonial NHP Jamestown National Historic Site Maggie L. Walker National Historic Site Manassas National Battlefield Park Natural Bridge Overmountain Victory National Historic Trail Petersburg National Battlefield Potomac Heritage National Scenic Trail Potomac Heritage NST + Prince William Forest Park Prince William Forest Park Red Hill Patrick Henry National Memorial Richmond National Battlefield Park Shenandoah National Park Star-Spangled Banner National Historic Trail Washington-Rochambeau Revolutionary Route National Historic Trail Washington-Rochambeau Revolutionary Route NHT + Potomac Heritage NST Wolf Trap National Park for the Performing Arts Appalachian National Scenic Trail Marsh-Billings-Rockefeller National Historical Park Missisquoi and Trout National Wild and Scenic River Ebey's Landing National Historical Reserve Fort Vancouver National Historic Site Klondike Gold Rush - Seattle Unit National Historical Park Lake Chelan National Recreation Area Lake Chelan NRA + North Cascades NP Lake Roosevelt (formerly Coulee Dam) National Recreation Area Lewis and Clark National Historical Park Lewis and Clark National Historic Trail Lewis and Clark NHT + Lewis and Clark NHP Manhattan Project National Historical Park Minidoka National Historic Site Mount Rainier National Park Nez Perce National Historical Park North Cascades National Park Olympic National Park Oregon National Historic Trail Oregon NHT + Lewis and Clark NHT + Fort Vancouver NHS Ross Lake National Recreation Area Ross Lake + North Cascades NP San Juan Island National Historical Park Whitman Mission National Historic Site Wing Luke Museum of the Asian Pacific American Experience Apostle Islands National Lakeshore Ice Age National Scenic Trail Ice Age National Scenic Trail + Saint Croix WR Ice Age National Scientific Reserve Ice Age NST + Ice Age National Scientific Reserve Ice Age NST + Saint Croix National Scenic Riverway + Ice Age National Scientific Reserve North Country National Scenic Trail North Country NST + Saint Croix National Scenic Riverway Saint Croix National Scenic Riverway Saint Croix WR + Ice Age National Scientific Reserve Appalachian National Scenic Trail Appalachian National ScenicTrail + Harpers Ferry HP Bluestone National Scenic River Chesapeake and Ohio Canal National Historical Park Gauley River National Recreation Area Harpers Ferry National Historical Park New River Gorge National River Bighorn Canyon National Recreation Area California National Historic Trail California NHT + Fort Laramie NHS California NHT + Pony Express NHT Devils Tower National Monument Fort Laramie National Historic Site Fossil Butte National Monument Grand Teton National Park John D. Rockefeller Parkway + Grand Teton NP John D. Rockefeller Parkway + Yellowstone NP John D. Rockefeller, Jr. Memorial Parkway Mormon Pioneer National Historic Trail Mormon Pioneer NHT + California NHT + Pony Express NHT Oregon National Historic Trail Oregon NHT + California NHT Oregon NHT + Mormon Pioneer NHT + California NHT + Pony Express NHT Oregon NHT + Mormon Pioneer NHT + California NHT + Pony Express NHT + Fort Laramie NHS Oregon NHT + Santa Fe NHT + California NHT Pony Express National Historic Trail Pony Express NHT + Fort Laramie NHS Yellowstone National Park Hawaii Alabama Arizona Arkansas California Colorado Connecticut Delaware District of Columbia Florida Georgia Idaho Illinois Indiana Iowa Kansas Kentucky Louisiana Maine Maryland Massachusetts Michigan Minnesota Mississippi Missouri Montana Nebraska Nevada New Hampshire New Jersey New Mexico New York North Carolina North Dakota Ohio Oklahoma Oregon Pennsylvania Rhode Island South Carolina South Dakota Tennessee Texas Utah Vermont Virginia Washington West Virginia Wisconsin Wyoming Alaska CALL DXCC GRIDSQUARE ITUZ CQZ IOTA ZERR US_STATE US_COUNTY US_PARK ZERR US_STATE US_COUNTY US_PARK ZERR CA_PROVINCE CA_US_PARK ZERR RU_OBLAST ZERR RU_OBLAST ZERR US_STATE US_COUNTY US_PARK ZERR RU_OBLAST ZERR RU_OBLAST ZERR RU_OBLAST ZERR CN_PROVINCE ZERR AU_STATE ZERR DX_US_PARK ZERR DX_US_PARK ZERR DX_US_PARK ZERR DX_US_PARK ZERR DX_US_PARK ZERR JA_PREFECTURE JA_CITY_GUN_KU ZERR FI_KUNTA ZERR FI_KUNTA ZERR FI_KUNTA ZERR AM AMTOR ARDOP ATV C4FM CHIP CLOVER CONTESTI CW DATA DIGITALVOICE DOMINO DSTAR FAX FM FSK31 FSK441 FST4 FT4 FT8 GTOR HELL HFSK IMAGE ISCAT JT4 JT65 JT6M JT9 MFSK16 MFSK8 MINIRTTY MSK144 MT63 OLIVIA OPERA PACKET PACTOR PAX PHONE PSK10 PSK125 PSK2K PSK31 PSK63 PSK63F PSKAM PSKFEC31 Q15 Q65 QRA64 ROS RTTY RTTYM SSB SSTV T10 THOR THROB VOI WINMOR WSPR Aircraft Scatter Aurora-E Aurora Back scatter EchoLink Earth-Moon-Earth Sporadic E F2 Reflection Field Aligned Irregularities Ionoscatter IRLP Meteor scatter Rain scatter Satellite Trans-equatorial Tropospheric ducting lotw-help@arrl.org Logbook of the World https://www.arrl.org/lotw/ AISAT-1 AMSAT India APRS Digipeater AMSAT-OSCAR 10 AMSAT-OSCAR 109 AMSAT-OSCAR 13 AMSAT-OSCAR 16 OSCAR 21/RS-14 AMRAD-OSCAR 27 AMSAT-OSCAR 3 AMSAT-OSCAR 4 AMSAT-OSCAR 40 AMSAT-OSCAR 51 AMSAT-OSCAR 6 AMSAT-OSCAR 7 AMSAT-OSCAR 73 AMSAT-OSCAR 8 AMSAT-OSCAR 85 (Fox-1A) AMSAT-OSCAR 91 (RadFxSat / Fox-1B) AMSAT-OSCAR 92 (Fox-1D) ARISS OSCAR 24 BIT Progress-OSCAR 102 (CAS-7B) Bayi Kepu Weixing 1 CAS-2T LilacSat-2 CAMSAT 4A (CAS-4A) CAMSAT 4B (CAS-4B) Delfi OSCAR-64 FUNcube-3 Emirates-OSCAR 88 (Nayif-1) CAS-5A Fuji-OSCAR 12 Fuji-OSCAR 20 Fuji-OSCAR 29 Fuji-OSCAR 99 (NEXUS) FalconSAT 3 HuskySat OSCAR 107 HO-113 Hope-OSCAR 119 Hope-Oscar 68 INSPIRE-Sat7 GreenCube Indonesia-OSCAR 86 (LAPAN-ORARI) Jordan-OSCAR 97(JY1Sat) ARISSat-1 LEDSAT Lusat-OSCAR 19 LituanicaSAT-1 LUSEX-OSCAR 87 LilacSat-OSCAR 90 (LilacSat-1) Cubesat Cubesat MIR Packet Digipeater Mirsat-1 Navy-OSCAR 103 (BRICSAT 2) Navy-OSCAR 104 (PSAT 2) Navy-OSCAR 44 BRICsat PSAT Phillipines-OSCAR-101 (Diwata-2) Qatar-OSCAR 100 (Es'hail-2/P4A) Radio Sputnik 1 Radio Sputnik 10 Radio Sputnik 11 Radio Sputnik 12 Radio Sputnik 13 Radio Sputnik 15 Radio Sputnik 2 Radio Sputnik 44 (DOSAAF-85) Radio Sputnik 5 Radio Sputnik 6 Radio Sputnik 7 Radio Sputnik 8 Shuttle Amateur Radio Experiment (SAREX) Digipeater Sunsat-OSCAR 35 Saudi-OSCAR 41 Saudi-OSCAR 50 Sumbandila Oscar 67 Taurus-1 (Jinniuzuo-1) Tevel-1 Tevel-2 Tevel-3 Tevel-4 Tevel-5 Tevel-6 Tevel-7 Tevel-8 TQ-OSCAR 108 (CAS-6 / TQ-1) UKube-1 (FUNcube-2) UOSAT-OSCAR 14 CubeSat VUsat-OSCAR 52 Hope 2A (CAS-3A) Hope 2B (CAS-3B) Hope 2C (CAS-3C) Hope 2D (CAS-3D) Hope 2E (CAS-3E) Hope 2F (CAS-2F) tqsl-2.7.2/src/cabrillo.h0000644000175000017500000000746114534122221015236 0ustar rmurphyrmurphy/*************************************************************************** cabrillo.h - description ------------------- begin : Thu Dec 5 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #ifndef __CABRILLO_H #define __CABRILLO_H #include "tqsllib.h" #undef CLIENT_STATIC #ifndef LOTW_SERVER #define CLIENT_STATIC static ///< Static linkage #else #define CLIENT_STATIC #endif /*! \file */ /** \defgroup Cabrillo Cabrillo API * * These functions and data structures provide a means of parsing a Cabrillo * file into its component fields. * * For convenience, the returned fields are identified using field names * from the \link ADIF ADIF \endlink specification. */ /** @{ */ #define TQSL_CABRILLO_MAX_FIELDS 12 ///< Max field count #define TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX 64 ///< Max field name length #define TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX 40 ///< Max field value length /// Cabrillo status values typedef enum { TQSL_CABRILLO_NO_ERROR, TQSL_CABRILLO_EOF, TQSL_CABRILLO_NO_START_RECORD, TQSL_CABRILLO_NO_CONTEST_RECORD, TQSL_CABRILLO_UNKNOWN_CONTEST, TQSL_CABRILLO_BAD_FIELD_DATA, TQSL_CABRILLO_EOR, } TQSL_CABRILLO_ERROR_TYPE; ///< Error type /*! \enum TQSL_CABRILLO_FREQ_TYPE * Frequency type: HF, VHF, or UNKNOWN */ typedef enum { TQSL_CABRILLO_HF, TQSL_CABRILLO_VHF, TQSL_CABRILLO_UNKNOWN, } TQSL_CABRILLO_FREQ_TYPE; // Minimum field number for callsign and default field number // For VHF, default should be 7. #define TQSL_MIN_CABRILLO_MAP_FIELD 5 ///< First possible call-worked field #define TQSL_DEF_CABRILLO_MAP_FIELD 8 ///< Default call-worked field /** Cabrillo field data: * * \li \c name - ADIF field name * \li \c value - Field content */ typedef struct { ///< Cabrillo field char name[TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX +1]; ///< Field name char value[TQSL_CABRILLO_FIELD_VALUE_LENGTH_MAX +1]; ///< Field value } tqsl_cabrilloField; typedef void * tQSL_Cabrillo; ///< Opaque cabrillo log type #ifdef __cplusplus extern "C" { #endif /** Get the Cabrillo error message that corresponds to a particular error value */ DLLEXPORT const char* CALLCONVENTION tqsl_cabrilloGetError(TQSL_CABRILLO_ERROR_TYPE err); /** Initialize a Cabrillo file for reading */ DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo(tQSL_Cabrillo *cabp, const char *filename); /** Get the Contest name as specified in the Cabrillo CONTEST line */ DLLEXPORT int CALLCONVENTION tqsl_getCabrilloContest(tQSL_Cabrillo cab, char *buf, int bufsiz); /** Get the Frequency type (HF or VHF) as determined by the contest */ DLLEXPORT int CALLCONVENTION tqsl_getCabrilloFreqType(tQSL_Cabrillo cab, TQSL_CABRILLO_FREQ_TYPE *type); /** Get the current line number (starting from 1) of the input file */ DLLEXPORT int CALLCONVENTION tqsl_getCabrilloLine(tQSL_Cabrillo cab, int *lineno); /** Get the text of the current Cabrillo record */ DLLEXPORT const char* CALLCONVENTION tqsl_getCabrilloRecordText(tQSL_Cabrillo cab); /** Get the next field of the Cabrillo record * * \c err is set to \c TQSL_CABRILLO_NO_ERROR or \c TQSL_CABRILLO_EOR (end-of-record) * if \c field was populated with data. If \c err == \c TQSL_CABRILLO_EOR, this * is the last field of the record. * * \c err == \c TQSL_CABRILLO_EOF when there is no more data available. */ DLLEXPORT int CALLCONVENTION tqsl_getCabrilloField(tQSL_Cabrillo cab, tqsl_cabrilloField *field, TQSL_CABRILLO_ERROR_TYPE *err); /** Finish reading a Cabrillo file and release its resources */ DLLEXPORT int CALLCONVENTION tqsl_endCabrillo(tQSL_Cabrillo *cabp); #ifdef __cplusplus } #endif /** @} */ #endif // __CABRILLO_H tqsl-2.7.2/src/cabrillo.cpp0000644000175000017500000005461214534122221015571 0ustar rmurphyrmurphy/*************************************************************************** cabrillo.cpp - description ------------------- begin : Thu Dec 5 2002 copyright : (C) 2002 by ARRL author : Jon Bloom email : jbloom@arrl.org revision : $Id$ ***************************************************************************/ #define TQSLLIB_DEF #include #include #include #include #include #include #include #include "tqsllib.h" #include "tqslerrno.h" #include "winstrdefs.h" using std::map; using std::string; #define TQSL_CABRILLO_MAX_RECORD_LENGTH 120 DLLEXPORTDATA TQSL_CABRILLO_ERROR_TYPE tQSL_Cabrillo_Error; static char errmsgbuf[256]; static char errmsgdata[128]; struct TQSL_CABRILLO; static int freq_to_band(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp); static int freq_to_mhz(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp); static int mode_xlat(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp); static int time_fixer(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp); struct cabrillo_field_def { const char *name; int loc; int (*process)(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp); }; static cabrillo_field_def cabrillo_dummy[] = { { "CALL", 6, 0 }, { "BAND", 0, freq_to_band }, { "MODE", 1, mode_xlat }, { "QSO_DATE", 2, 0 }, { "TIME_ON", 3, time_fixer }, { "FREQ", 0, freq_to_mhz }, { "MYCALL", 4, 0 }, }; /* // Cabrillo QSO template specs // Call in field 6 static cabrillo_field_def cabrillo_c6[] = { { "BAND", 0, freq_to_band }, { "MODE", 1, mode_xlat }, { "QSO_DATE", 2, 0 }, { "TIME_ON", 3, time_fixer }, { "CALL", 6, 0 }, { "FREQ", 0, 0 }, { "MYCALL", 4, 0 }, }; // Call in field 7 static cabrillo_field_def cabrillo_c7[] = { { "BAND", 0, freq_to_band }, { "MODE", 1, mode_xlat }, { "QSO_DATE", 2, 0 }, { "TIME_ON", 3, time_fixer }, { "CALL", 7, 0 }, { "FREQ", 0, 0 }, { "MYCALL", 4, 0 }, }; // Call in field 8 static cabrillo_field_def cabrillo_c8[] = { { "BAND", 0, freq_to_band }, { "MODE", 1, mode_xlat }, { "QSO_DATE", 2, 0 }, { "TIME_ON", 3, time_fixer }, { "CALL", 8, 0 }, { "FREQ", 0, 0 }, { "MYCALL", 4, 0 }, }; // Call in field 9 static cabrillo_field_def cabrillo_c9[] = { { "BAND", 0, freq_to_band }, { "MODE", 1, mode_xlat }, { "QSO_DATE", 2, 0 }, { "TIME_ON", 3, time_fixer }, { "CALL", 9, 0 }, { "FREQ", 0, 0 }, { "MYCALL", 4, 0 }, }; */ struct cabrillo_contest { char *contest_name; TQSL_CABRILLO_FREQ_TYPE type; cabrillo_field_def *fields; int nfields; }; struct TQSL_CABRILLO { int sentinel; FILE *fp; char *filename; cabrillo_contest *contest; int field_idx; char rec[TQSL_CABRILLO_MAX_RECORD_LENGTH+1]; char *datap; int line_no; char *fields[TQSL_CABRILLO_MAX_FIELDS]; }; #define CAST_TQSL_CABRILLO(p) ((struct TQSL_CABRILLO *)p) static TQSL_CABRILLO * check_cabrillo(tQSL_Cabrillo cabp) { if (tqsl_init()) return 0; if (cabp == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 0; } if (CAST_TQSL_CABRILLO(cabp)->sentinel != 0x2449) return 0; return CAST_TQSL_CABRILLO(cabp); } static char * tqsl_parse_cabrillo_record(char *rec) { char *cp = strchr(rec, ':'); if (!cp) return 0; *cp++ = 0; if (strlen(rec) > TQSL_CABRILLO_FIELD_NAME_LENGTH_MAX) return 0; while (isspace(*cp)) cp++; char *sp; if ((sp = strchr(cp, '\r')) != 0) *sp = '\0'; if ((sp = strchr(cp, '\n')) != 0) *sp = '\0'; for (sp = cp + strlen(cp); sp != cp; ) { sp--; if (isspace(*sp)) *sp = '\0'; else break; } for (sp = rec; *sp; sp++) *sp = toupper(*sp); return cp; } static int freq_to_band(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp) { if (!strcasecmp(fp->value, "light")) { strncpy(fp->value, "SUBMM", sizeof fp->value); return 0; } int freq = strtol(fp->value, NULL, 10); const char *band = 0; if (freq < 30) { // Handle known CT misbehavior if (!strcmp(fp->value, "7")) freq = 7000; if (!strcmp(fp->value, "14")) freq = 14000; if (!strcmp(fp->value, "21")) freq = 21000; if (!strcmp(fp->value, "28")) freq = 28000; } if (freq >= 1800 && freq <= 2000) band = "160M"; else if (freq >= 3500 && freq <= 4000) band = "80M"; else if (freq >= 7000 && freq <= 7300) band = "40M"; else if (freq >= 10100 && freq <= 10150) band = "30M"; else if (freq >= 14000 && freq <= 14350) band = "20M"; else if (freq >= 18068 && freq <= 18168) band = "17M"; else if (freq >= 21000 && freq <= 21450) band = "15M"; else if (freq >= 24890 && freq <= 24990) band = "12M"; else if (freq >= 28000 && freq <= 29700) band = "10M"; else if (freq == 50) band = "6M"; else if (freq == 70) band = "4M"; else if (freq == 144) band = "2M"; else if (freq == 222) band = "1.25M"; else if (freq == 432) band = "70CM"; else if (freq == 902 || freq == 903) band = "33CM"; else if (!strcasecmp(fp->value, "1.2G") || !strcasecmp(fp->value, "1.2")) band = "23CM"; else if (!strcasecmp(fp->value, "2.3G") || !strcasecmp(fp->value, "2.3")) band = "13CM"; else if (!strcasecmp(fp->value, "3.4G") || !strcasecmp(fp->value, "3.4")) band = "9CM"; else if (!strcasecmp(fp->value, "5.7G") || !strcasecmp(fp->value, "5.7")) band = "6CM"; else if (!strcasecmp(fp->value, "10G") || !strcasecmp(fp->value, "10")) band = "3CM"; else if (!strcasecmp(fp->value, "24G") || !strcasecmp(fp->value, "24")) band = "1.25CM"; else if (!strcasecmp(fp->value, "47G") || !strcasecmp(fp->value, "47")) band = "6MM"; else if (!strcasecmp(fp->value, "75G") || !strcasecmp(fp->value, "75") || !strcasecmp(fp->value, "76G") || !strcasecmp(fp->value, "76")) band = "4MM"; else if (!strcasecmp(fp->value, "119G") || !strcasecmp(fp->value, "119") || !strcasecmp(fp->value, "122G") || !strcasecmp(fp->value, "122") || !strcasecmp(fp->value, "123G") || !strcasecmp(fp->value, "123")) band = "2.5MM"; else if (!strcasecmp(fp->value, "142G") || !strcasecmp(fp->value, "142") || !strcasecmp(fp->value, "134G") || !strcasecmp(fp->value, "134")) band = "2MM"; else if (!strcasecmp(fp->value, "241G") || !strcasecmp(fp->value, "241")|| !strcasecmp(fp->value, "242G") || !strcasecmp(fp->value, "242")) band = "1MM"; else if (!strcasecmp(fp->value, "300G") || !strcasecmp(fp->value, "300") || !strcasecmp(fp->value, "LIGHT")) band = "SUBMM"; if (band && cab->contest->type == TQSL_CABRILLO_UNKNOWN) { if (freq < 1000) cab->contest->type = TQSL_CABRILLO_VHF; else cab->contest->type = TQSL_CABRILLO_HF; } if (band == 0) return 1; strncpy(fp->value, band, sizeof fp->value); return 0; } static int freq_to_mhz(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp) { if (!strcasecmp(fp->value, "light")) { return 0; } int freq = strtol(fp->value, NULL, 10); double freqmhz = freq; freqmhz /= 1000; if (freq < 30) { // Handle known CT misbehavior if (freq == 7) freqmhz = 7.0; if (freq == 14) freqmhz = 14.0; if (freq == 21) freqmhz = 21.0; if (freq == 28) freqmhz = 28.0; } // VHF+ if (!strcasecmp(fp->value, "50")) freqmhz = 50.0; else if (!strcasecmp(fp->value, "70")) freqmhz = 70.0; else if (!strcasecmp(fp->value, "144")) freqmhz = 144.0; else if (!strcasecmp(fp->value, "222")) freqmhz = 222.0; else if (!strcasecmp(fp->value, "432")) freqmhz = 432.0; else if (!strcasecmp(fp->value, "902") || !strcasecmp(fp->value, "903")) freqmhz = 902.0; else if (!strcasecmp(fp->value, "1.2G") || !strcasecmp(fp->value, "1.2")) freqmhz = 1240.0; else if (!strcasecmp(fp->value, "2.3G") || !strcasecmp(fp->value, "2.3")) freqmhz = 2300.0; else if (!strcasecmp(fp->value, "3.4G") || !strcasecmp(fp->value, "3.4")) freqmhz = 3300.0; else if (!strcasecmp(fp->value, "5.7G") || !strcasecmp(fp->value, "5.7")) freqmhz = 5650.0; else if (!strcasecmp(fp->value, "10G") || !strcasecmp(fp->value, "10")) freqmhz = 10000.0; else if (!strcasecmp(fp->value, "24G") || !strcasecmp(fp->value, "24")) freqmhz = 24000.0; else if (!strcasecmp(fp->value, "47G") || !strcasecmp(fp->value, "47")) freqmhz = 47000.0; else if (!strcasecmp(fp->value, "75G") || !strcasecmp(fp->value, "75") || !strcasecmp(fp->value, "76G") || !strcasecmp(fp->value, "76")) freqmhz = 75500.0; else if (!strcasecmp(fp->value, "119G") || !strcasecmp(fp->value, "119")) freqmhz = 119980.0; else if (!strcasecmp(fp->value, "142G") || !strcasecmp(fp->value, "142")) freqmhz = 142000.0; else if (!strcasecmp(fp->value, "241G") || !strcasecmp(fp->value, "241") || !strcasecmp(fp->value, "242G") || !strcasecmp(fp->value, "242")) freqmhz = 241000.0; else if (!strcasecmp(fp->value, "300G") || !strcasecmp(fp->value, "300")) freqmhz = 300000.0; if (freqmhz > 0 && cab->contest->type == TQSL_CABRILLO_UNKNOWN) { if (freqmhz >= 50.0) // VHF cab->contest->type = TQSL_CABRILLO_VHF; else cab->contest->type = TQSL_CABRILLO_HF; } snprintf(fp->value, sizeof fp->value, "%#f", freqmhz); return 0; } static char * tqsl_strtoupper(char *str) { for (char *cp = str; *cp != '\0'; cp++) *cp = toupper(*cp); return str; } /* * Read a line from a cabrillo file. * Start with stripping whitespace, read up until any line-ending character * (\r \n) * Replaces fgets which has a fixed line ending (\n). */ static char *fgets_cab(char *s, int size, FILE *stream) { int status; int ws; while (1) { ws = fgetc(stream); if (ws == EOF) { return 0; } if (!isspace(ws)) { break; } } ungetc(ws, stream); // Push that back onto the stream char format[20]; snprintf(format, sizeof format, "%%%d[^\r\n]", size - 1); // Format allows what's left up to \r or \n status = fscanf(stream, format, s); if (status == 0) return NULL; s[size-1] = '\0'; return s; } static int mode_xlat(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp) { static map modes; static bool modes_loaded = false; if (!modes_loaded) { tqslTrace("mode_xlat", "Loading Cab modes"); modes_loaded = true; // Set default modes modes["CW"] = "CW"; modes["PH"] = "SSB"; modes["FM"] = "FM"; modes["RY"] = "RTTY"; modes["DG"] = "DATA"; FILE *cfile; char modebuf[80]; #ifdef _WIN32 string default_path = string(tQSL_RsrcDir) + "\\cab_modes.dat"; string user_path = string(tQSL_BaseDir) + "\\cab_modes.dat"; #else string default_path = string(tQSL_RsrcDir) + "/cab_modes.dat"; string user_path = string(tQSL_BaseDir) + "/cab_modes.dat"; #endif #ifdef _WIN32 wchar_t* wfilename = utf8_to_wchar(default_path.c_str()); if ((cfile = _wfopen(wfilename, L"r")) == NULL) { #else if ((cfile = fopen(default_path.c_str(), "r")) == NULL) { #endif tqslTrace("mode_xlat", "Can't open def mode file %s: %m", default_path.c_str()); } else { while(fgets(modebuf, sizeof modebuf, cfile)) { for (char *p = modebuf + (strlen(modebuf) - 1); p >= modebuf; p--) { if (*p == '\n' || *p == '\r') { *p = '\0'; } else { break; } } char *mode = strtok(modebuf, ","); char *map = strtok(NULL, ","); if (mode && map) modes[tqsl_strtoupper(mode)] = tqsl_strtoupper(map); } } #ifdef _WIN32 free(wfilename); #endif #ifdef _WIN32 wfilename = utf8_to_wchar(user_path.c_str()); if ((cfile = _wfopen(wfilename, L"r")) == NULL) { #else if ((cfile = fopen(user_path.c_str(), "r")) == NULL) { #endif tqslTrace("mode_xlat", "Can't open user mode file %s: %m", user_path.c_str()); } else { while(fgets(modebuf, sizeof modebuf, cfile)) { for (char *p = modebuf + (strlen(modebuf) - 1); p >= modebuf; p--) { if (*p == '\n' || *p == '\r') { *p = '\0'; } else { break; } } char *mode = strtok(modebuf, ","); char *map = strtok(NULL, ","); if (mode && map) modes[tqsl_strtoupper(mode)] = tqsl_strtoupper(map); } } } map::iterator it; it = modes.find(tqsl_strtoupper(fp->value)); if (it != modes.end()) { strncpy(fp->value, it->second.c_str(), sizeof fp->value); return 0; } return 1; // not found } static int time_fixer(TQSL_CABRILLO *cab, tqsl_cabrilloField *fp) { if (strlen(fp->value) == 0) return 0; char *cp; for (cp = fp->value; *cp; cp++) if (!isdigit(*cp)) break; if (*cp) return 1; snprintf(fp->value, sizeof fp->value, "%04d", static_cast(strtol(fp->value, NULL, 10))); return 0; } static void tqsl_free_cabrillo_contest(struct cabrillo_contest *c) { if (c->contest_name) free(c->contest_name); if (c->fields) free(c->fields); free(c); } static struct cabrillo_contest * tqsl_new_cabrillo_contest(const char *contest_name, int call_field, int contest_type) { cabrillo_contest *c = static_cast(calloc(1, sizeof(struct cabrillo_contest))); if (c == NULL) return NULL; if ((c->contest_name = strdup(contest_name)) == NULL) { tqsl_free_cabrillo_contest(c); return NULL; } c->type = (TQSL_CABRILLO_FREQ_TYPE)contest_type; if ((c->fields = (struct cabrillo_field_def *)calloc(1, sizeof cabrillo_dummy)) == NULL) { tqsl_free_cabrillo_contest(c); return NULL; } memcpy(c->fields, cabrillo_dummy, sizeof cabrillo_dummy); c->fields[0].loc = call_field-1; c->nfields = sizeof cabrillo_dummy / sizeof cabrillo_dummy[0]; return c; } static void tqsl_free_cab(struct TQSL_CABRILLO *cab) { if (!cab || cab->sentinel != 0x2449) return; cab->sentinel = 0; if (cab->filename) free(cab->filename); if (cab->fp) fclose(cab->fp); if (cab->contest) tqsl_free_cabrillo_contest(cab->contest); free(cab); } DLLEXPORT int CALLCONVENTION tqsl_beginCabrillo(tQSL_Cabrillo *cabp, const char *filename) { tqslTrace("tqsl_beginCabrillo", "cabp=0x%lx, filename=%s", cabp, filename); TQSL_CABRILLO_ERROR_TYPE terrno; if (filename == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } struct TQSL_CABRILLO *cab; cab = (struct TQSL_CABRILLO *)calloc(1, sizeof(struct TQSL_CABRILLO)); if (cab == NULL) { tQSL_Error = TQSL_ALLOC_ERROR; goto err; } cab->sentinel = 0x2449; cab->field_idx = -1; #ifdef _WIN32 wchar_t * wfilename = utf8_to_wchar(filename); if ((cab->fp = _wfopen(wfilename, L"rb, ccs=UTF-8")) == NULL) { free_wchar(wfilename); #else if ((cab->fp = fopen(filename, "r")) == NULL) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_beginCabrillo", "open error, errno=%d, error=%s", errno, strerror(errno)); goto err; } #ifdef _WIN32 free(wfilename); #endif char *cp; terrno = TQSL_CABRILLO_NO_START_RECORD; while ((cp = fgets_cab(cab->rec, sizeof cab->rec, cab->fp)) != 0) { cab->line_no++; if (tqsl_parse_cabrillo_record(cab->rec) != 0 && strstr(cab->rec, "START-OF-LOG")) break; } if (cp != 0) { terrno = TQSL_CABRILLO_NO_CONTEST_RECORD; while ((cp = fgets_cab(cab->rec, sizeof cab->rec, cab->fp)) != 0) { cab->line_no++; char *vp; if ((vp = tqsl_parse_cabrillo_record(cab->rec)) != 0 && !strcmp(cab->rec, "CONTEST") && strtok(vp, " \t\r\n") != 0) { terrno = TQSL_CABRILLO_UNKNOWN_CONTEST; int callfield, contest_type; if (tqsl_getCabrilloMapEntry(vp, &callfield, &contest_type)) { // No defined contest with this name. // callfield comes back as 0 contest_type = TQSL_CABRILLO_UNKNOWN; } cab->contest = tqsl_new_cabrillo_contest(vp, callfield, contest_type); if (cab->contest == 0) { strncpy(errmsgdata, vp, sizeof errmsgdata); cp = 0; } break; } } } if (cp == 0) { if (ferror(cab->fp)) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; tqslTrace("tqsl_beginCabrillo", "read error, errno=%d, error=%s", errno, strerror(errno)); goto err; } tQSL_Cabrillo_Error = terrno; tQSL_Error = TQSL_CABRILLO_ERROR; goto err; } if ((cab->filename = strdup(filename)) == NULL) { tQSL_Error = TQSL_ALLOC_ERROR; goto err; } *((struct TQSL_CABRILLO **)cabp) = cab; return 0; err: strncpy(tQSL_ErrorFile, filename, sizeof tQSL_ErrorFile); tQSL_ErrorFile[sizeof tQSL_ErrorFile-1] = 0; tqsl_free_cab(cab); return 1; } DLLEXPORT int CALLCONVENTION tqsl_endCabrillo(tQSL_Cabrillo *cabp) { tqslTrace("tqsl_endCabrillo", "cabp=0x%lx", cabp); TQSL_CABRILLO *cab; if (cabp == 0) return 0; cab = CAST_TQSL_CABRILLO(*cabp); if (!cab || cab->sentinel != 0x2449) return 0; tqsl_free_cab(cab); *cabp = 0; return 0; } DLLEXPORT const char* CALLCONVENTION tqsl_cabrilloGetError(TQSL_CABRILLO_ERROR_TYPE err) { const char *msg = 0; switch (err) { case TQSL_CABRILLO_NO_ERROR: msg = "Cabrillo success"; break; case TQSL_CABRILLO_EOF: msg = "Cabrillo end-of-file"; break; case TQSL_CABRILLO_EOR: msg = "Cabrillo end-of-record"; break; case TQSL_CABRILLO_NO_START_RECORD: msg = "Cabrillo missing START-OF-LOG record"; break; case TQSL_CABRILLO_NO_CONTEST_RECORD: msg = "Cabrillo missing CONTEST record"; break; case TQSL_CABRILLO_UNKNOWN_CONTEST: snprintf(errmsgbuf, sizeof errmsgbuf, "Cabrillo unknown CONTEST: %s", errmsgdata); msg = errmsgbuf; break; case TQSL_CABRILLO_BAD_FIELD_DATA: snprintf(errmsgbuf, sizeof errmsgbuf, "Cabrillo field data error in %s field", errmsgdata); msg = errmsgbuf; break; } if (!msg) { snprintf(errmsgbuf, sizeof errmsgbuf, "Cabrillo unknown error: %d", err); if (errmsgdata[0] != '\0') snprintf(errmsgbuf + strlen(errmsgbuf), sizeof errmsgbuf - strlen(errmsgbuf), " (%s)", errmsgdata); msg = errmsgbuf; } tqslTrace("tqsl_cabrilloGetError", "msg=%s", msg); errmsgdata[0] = '\0'; return msg; } DLLEXPORT int CALLCONVENTION tqsl_getCabrilloField(tQSL_Cabrillo cabp, tqsl_cabrilloField *field, TQSL_CABRILLO_ERROR_TYPE *error) { TQSL_CABRILLO *cab; cabrillo_field_def *fp; const char *fielddat; if ((cab = check_cabrillo(cabp)) == 0) return 1; if (field == 0 || error == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (cab->datap == 0 || cab->field_idx < 0 || cab->field_idx >= cab->contest->nfields) { char *cp; while ((cp = fgets_cab(cab->rec, sizeof cab->rec, cab->fp)) != 0) { cab->line_no++; cab->datap = tqsl_parse_cabrillo_record(cab->rec); if (cab->datap != 0) { if (!strcasecmp(cab->rec, "QSO")) { cab->field_idx = 0; char *fieldp = strtok(cab->datap, " \t\r\n"); memset(cab->fields, 0, sizeof cab->fields); for (int i = 0; fieldp && i < static_cast(sizeof cab->fields / sizeof cab->fields[0]); i++) { cab->fields[i] = fieldp; fieldp = strtok(0, " \t\r\n"); } break; } else if (!strcasecmp(cab->rec, "END-OF-LOG")) { *error = TQSL_CABRILLO_EOF; return 0; } } } if (cp == 0) { if (ferror(cab->fp)) { tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; goto err; } else { *error = TQSL_CABRILLO_EOF; return 0; } } } // Record data is okay and field index is valid. fp = cab->contest->fields + cab->field_idx; strncpy(field->name, fp->name, sizeof field->name); if (fp->loc < 0) { // New contest // try to guess which field has the 'call-worked' for (int i = 6; i < TQSL_CABRILLO_MAX_FIELDS && cab->fields[i]; i++) { char *p = cab->fields[i]; // Simple parse: a callsign is at least 4 chars long // and has at least one digit and at least one letter // Nothing but alphnumeric and '/' allowed. // First, eliminate grid squares if (strlen(p) == 4) { if (isalpha(p[0]) && isalpha(p[1]) && isdigit(p[2]) && isdigit(p[3])) continue; } int nlet = 0, ndig = 0; for (; *p; p++) { if (isdigit(*p)) { ndig++; } else if (isalpha(*p)) { nlet++; } else if (*p != '/') { ndig = 0; nlet = 0; break; } } if (nlet > 0 && ndig > 0 && nlet+ndig > 3) { // OK, looks like a callsign. Is it possibly a gridsquare? if (strlen(p) == 6) { if ((isalpha(p[0]) && toupper(p[0]) < 'S') && (isalpha(p[1]) && toupper(p[1]) < 'S') && (isdigit(p[2]) && isdigit(p[3])) && (isalpha(p[4]) && toupper(p[4]) < 'Y') && (isalpha(p[5]) && toupper(p[5]) < 'Y')) continue; // Gridsquare. Don't use it. } if (fp->loc < 0) { // No callsign candidate yet fp->loc = i; } else { tQSL_Cabrillo_Error = TQSL_CABRILLO_UNKNOWN_CONTEST; tQSL_Error = TQSL_CABRILLO_ERROR; snprintf(errmsgdata, sizeof errmsgdata, "%s\nUnable to find a unique call-worked field.\n" "Please define a custom Cabrillo entry for this contest.\n", cab->contest->contest_name); goto err; } } } if (fp->loc < 0) { // Still can't find a call. Have to bail. tQSL_Cabrillo_Error = TQSL_CABRILLO_UNKNOWN_CONTEST; tQSL_Error = TQSL_CABRILLO_ERROR; snprintf(errmsgdata, sizeof errmsgdata, "%s\nUnable to find a valid call-worked field.\n" "Please define a custom Cabrillo entry for this contest.\n", cab->contest->contest_name); goto err; } } fielddat = cab->fields[fp->loc]; if (fielddat == 0) { tQSL_Cabrillo_Error = TQSL_CABRILLO_BAD_FIELD_DATA; tQSL_Error = TQSL_CABRILLO_ERROR; strncpy(errmsgdata, field->name, sizeof errmsgdata); goto err; } strncpy(field->value, fielddat, sizeof field->value); if (fp->process && fp->process(cab, field)) { tQSL_Cabrillo_Error = TQSL_CABRILLO_BAD_FIELD_DATA; tQSL_Error = TQSL_CABRILLO_ERROR; strncpy(errmsgdata, field->name, sizeof errmsgdata); goto err; } cab->field_idx++; if (cab->field_idx >= cab->contest->nfields) *error = TQSL_CABRILLO_EOR; else *error = TQSL_CABRILLO_NO_ERROR; return 0; err: cab->datap = NULL; // Ignore this strncpy(tQSL_ErrorFile, cab->filename, sizeof tQSL_ErrorFile); tQSL_ErrorFile[sizeof tQSL_ErrorFile-1] = 0; return 1; } DLLEXPORT int CALLCONVENTION tqsl_getCabrilloContest(tQSL_Cabrillo cabp, char *buf, int bufsiz) { TQSL_CABRILLO *cab; if ((cab = check_cabrillo(cabp)) == 0) return 1; if (buf == 0 || bufsiz <= 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } if (bufsiz < static_cast(strlen(cab->contest->contest_name))+1) { tQSL_Error = TQSL_BUFFER_ERROR; return 1; } strncpy(buf, cab->contest->contest_name, bufsiz); return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCabrilloFreqType(tQSL_Cabrillo cabp, TQSL_CABRILLO_FREQ_TYPE *type) { TQSL_CABRILLO *cab; if ((cab = check_cabrillo(cabp)) == 0) return 1; if (type == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *type = cab->contest->type; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getCabrilloLine(tQSL_Cabrillo cabp, int *lineno) { TQSL_CABRILLO *cab; if ((cab = check_cabrillo(cabp)) == 0) return 1; if (lineno == 0) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *lineno = cab->line_no; return 0; } DLLEXPORT const char* CALLCONVENTION tqsl_getCabrilloRecordText(tQSL_Cabrillo cabp) { TQSL_CABRILLO *cab; if ((cab = check_cabrillo(cabp)) == 0) return 0; return cab->rec; } tqsl-2.7.2/src/adif.h0000644000175000017500000001167014534122221014347 0ustar rmurphyrmurphy/*************************************************************************** adif.h - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002 by ARRL email : MSimcik@localhost.localdomain revision : $Id$ ***************************************************************************/ #ifndef __ADIF_H #define __ADIF_H #include "tqsllib.h" #include #include /*! \file */ /** \defgroup ADIF ADIF API * * These functions and data structures provide a means of parsing an ADIF * file into its component fields, along with range-checking the field contents. */ /** @{ */ #define TQSL_ADIF_FIELD_NAME_LENGTH_MAX 64 ///< Max length of ADIF field #define TQSL_ADIF_FIELD_SIZE_LENGTH_MAX 10 ///< Max length of field name #define TQSL_ADIF_FIELD_TYPE_LENGTH_MAX 1 ///< Max length of field type /*! \enum TQSL_ADIF_BOOLEAN * Boolean type - TRUE/FALSE */ #ifndef TQSL_ADIF_BOOLEAN typedef enum { TQSL_FALSE, TQSL_TRUE } TQSL_ADIF_BOOLEAN; #endif typedef void * tQSL_ADIF; ///< Opaque ADIF type /// Specifies the type of range limits to apply to a field typedef enum { TQSL_ADIF_RANGE_TYPE_NONE, TQSL_ADIF_RANGE_TYPE_MINMAX, TQSL_ADIF_RANGE_TYPE_ENUMERATION } TQSL_ADIF_RANGE_TYPE; /// Response values returned from tqsl_getADIFField() typedef enum { TQSL_ADIF_GET_FIELD_SUCCESS, TQSL_ADIF_GET_FIELD_NO_NAME_MATCH, TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH, TQSL_ADIF_GET_FIELD_NO_RANGE_MATCH, TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH, TQSL_ADIF_GET_FIELD_NO_RESULT_ALLOCATION, TQSL_ADIF_GET_FIELD_NAME_LENGTH_OVERFLOW, TQSL_ADIF_GET_FIELD_DATA_LENGTH_OVERFLOW, TQSL_ADIF_GET_FIELD_SIZE_OVERFLOW, TQSL_ADIF_GET_FIELD_TYPE_OVERFLOW, TQSL_ADIF_GET_FIELD_ERRONEOUS_STATE, TQSL_ADIF_GET_FIELD_EOF } TQSL_ADIF_GET_FIELD_ERROR; /** An ADIF field definition */ typedef struct { char name[TQSL_ADIF_FIELD_NAME_LENGTH_MAX + 1]; ///< Field name char type[TQSL_ADIF_FIELD_TYPE_LENGTH_MAX + 1]; ///< Field type TQSL_ADIF_RANGE_TYPE rangeType; ///< Range type unsigned int max_length; ///< Max length long signed min_value; ///< Min value long signed max_value; ///< Max value const char **enumStrings; ///< Enumerated values void *userPointer; ///< user pointer } tqsl_adifFieldDefinitions; /** Field returned from parsing */ typedef struct { char name[TQSL_ADIF_FIELD_NAME_LENGTH_MAX + 1]; ///< Field name char size[TQSL_ADIF_FIELD_SIZE_LENGTH_MAX + 1]; ///< Size char type[TQSL_ADIF_FIELD_TYPE_LENGTH_MAX + 1]; ///< Type unsigned char *data; ///< data unsigned int adifNameIndex; ///< Name index void *userPointer; ///< User pointer int line_no; ///< Input line where the tag was found } tqsl_adifFieldResults; /* function prototypes */ #ifdef __cplusplus extern "C" { #endif /** Get the ADIF error message that corresponds to a particular error value */ DLLEXPORT const char* CALLCONVENTION tqsl_adifGetError(TQSL_ADIF_GET_FIELD_ERROR status); /** Initialize an ADIF file for reading */ DLLEXPORT int CALLCONVENTION tqsl_beginADIF(tQSL_ADIF *adifp, const char *filename); /** Get the next field from an ADIF file * * \li \c adif - ADIF handle returned from tqsl_beginADIF() * \li \c field - pointer to struct that contains the field data and description * \li \c status - pointer to returned status variable * \li \c adifFields - pointer to an array of field-definition structures. The last * item in the array should have an empty string as its \c name member. * \li \c typesDefined - pointer to an array of char pointers that define the * allowed field-type strings. The last item in the array should point to * an empty string. * \li \c allocator - pointer to a function that returns a pointer to a memory * block of the specified size. This function will be called at most one * time during a call to tqsl_getADIFField. The returned pointer will then * be used to populate the \c data member of \c field. The caller is * responsible for freeing this memory, if needed. */ DLLEXPORT int CALLCONVENTION tqsl_getADIFField(tQSL_ADIF adif, tqsl_adifFieldResults *field, TQSL_ADIF_GET_FIELD_ERROR *status, const tqsl_adifFieldDefinitions *adifFields, const char * const *typesDefined, unsigned char *(*allocator)(size_t) ); /** Get the current line number (starting from 1) of the input file */ DLLEXPORT int CALLCONVENTION tqsl_getADIFLine(tQSL_ADIF adif, int *lineno); /** End and release an ADIF file */ DLLEXPORT int CALLCONVENTION tqsl_endADIF(tQSL_ADIF *adifp); /** Form an ADIF field string. * * N.B. On systems that distinguish text-mode files from binary-mode files, * notably Windows, the text should be written in binary mode. */ DLLEXPORT int CALLCONVENTION tqsl_adifMakeField(const char *fieldname, char type, const unsigned char *value, int len, unsigned char *buf, int buflen); #ifdef __cplusplus } #endif /** @} */ #endif /* __ADIF_H */ tqsl-2.7.2/src/adif.cpp0000644000175000017500000003625014534122221014703 0ustar rmurphyrmurphy/*************************************************************************** adif.c - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002 by ARRL email : MSimcik@localhost.localdomain revision : $Id$ ***************************************************************************/ #define TQSLLIB_DEF #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "sysconfig.h" #endif #include "tqsllib.h" #include "tqslerrno.h" #include "winstrdefs.h" typedef enum { TQSL_ADIF_STATE_BEGIN, TQSL_ADIF_STATE_GET_NAME, TQSL_ADIF_STATE_GET_SIZE, TQSL_ADIF_STATE_GET_TYPE, TQSL_ADIF_STATE_GET_DATA, TQSL_ADIF_STATE_DONE } TQSL_ADIF_STATE; struct TQSL_ADIF { int sentinel; FILE *fp; char *filename; int line_no; }; #define CAST_TQSL_ADIF(p) ((struct TQSL_ADIF *)p) static char ADIF_ErrorField[TQSL_ADIF_FIELD_NAME_LENGTH_MAX + 1]; static TQSL_ADIF * check_adif(tQSL_ADIF adif) { if (tqsl_init()) return 0; if (adif == 0) return 0; if (CAST_TQSL_ADIF(adif)->sentinel != 0x3345) { tqslTrace("check_adif", "adif no valid sentinel"); return 0; } return CAST_TQSL_ADIF(adif); } static void free_adif(TQSL_ADIF *adif) { tqslTrace("free_adif", NULL); if (adif && adif->sentinel == 0x3345) { adif->sentinel = 0; if (adif->filename) free(adif->filename); if (adif->fp) fclose(adif->fp); free(adif); } } DLLEXPORT int CALLCONVENTION tqsl_beginADIF(tQSL_ADIF *adifp, const char *filename) { tqslTrace("tqsl_beginADIF", "adifp=0x%lx, filename=%s", adifp, filename); if (filename == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } struct TQSL_ADIF *adif; adif = (struct TQSL_ADIF *)calloc(1, sizeof(struct TQSL_ADIF)); if (adif == NULL) { tQSL_Error = TQSL_ALLOC_ERROR; goto err; } adif->sentinel = 0x3345; ADIF_ErrorField[0] = '\0'; tqslTrace("tqsl_beginADIF", "Preparing to open file"); #ifdef _WIN32 wchar_t *wfilename = utf8_to_wchar(filename); if ((adif->fp = _wfopen(wfilename, L"rb, ccs=UTF-8")) == NULL) { free_wchar(wfilename); #else if ((adif->fp = fopen(filename, "rb")) == NULL) { #endif tQSL_Error = TQSL_SYSTEM_ERROR; tQSL_Errno = errno; strncpy(tQSL_ErrorFile, filename, sizeof tQSL_ErrorFile); tQSL_ErrorFile[sizeof tQSL_ErrorFile-1] = 0; tqslTrace("tqsl_beginADIF", "Error %d errno %d file %s", tQSL_Error, tQSL_Errno, filename); goto err; } #ifdef _WIN32 free_wchar(wfilename); #endif if ((adif->filename = strdup(filename)) == NULL) { tQSL_Error = TQSL_ALLOC_ERROR; goto err; } *((struct TQSL_ADIF **)adifp) = adif; return 0; err: free_adif(adif); return 1; } DLLEXPORT int CALLCONVENTION tqsl_endADIF(tQSL_ADIF *adifp) { tqslTrace("tqsl_endADIF", "adifp=0x%lx", adifp); TQSL_ADIF *adif; if (adifp == 0) return 0; adif = CAST_TQSL_ADIF(*adifp); free_adif(adif); *adifp = 0; return 0; } DLLEXPORT int CALLCONVENTION tqsl_getADIFLine(tQSL_ADIF adifp, int *lineno) { TQSL_ADIF *adif; if (!(adif = check_adif(adifp))) return 1; if (lineno == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *lineno = adif->line_no; return 0; } static void strCatChar(char *str, int character) { while (*str) str++; *str++ = character; *str = '\0'; } DLLEXPORT const char* CALLCONVENTION tqsl_adifGetError(TQSL_ADIF_GET_FIELD_ERROR status) { const char *fmt; static char errorText[512]; switch( status ) { case TQSL_ADIF_GET_FIELD_SUCCESS: fmt = "ADIF success"; break; case TQSL_ADIF_GET_FIELD_NO_NAME_MATCH: fmt = "ADIF field %s no name match"; break; case TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH: fmt = "ADIF field %s no type match"; break; case TQSL_ADIF_GET_FIELD_NO_RANGE_MATCH: fmt = "ADIF field %s no range match"; break; case TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH: fmt = "ADIF field %s no enumeration match"; break; case TQSL_ADIF_GET_FIELD_NO_RESULT_ALLOCATION: fmt = "ADIF field %s no result allocation"; break; case TQSL_ADIF_GET_FIELD_NAME_LENGTH_OVERFLOW: fmt = "ADIF field %s name length overflow"; break; case TQSL_ADIF_GET_FIELD_DATA_LENGTH_OVERFLOW: fmt = "ADIF field %s data length overflow"; break; case TQSL_ADIF_GET_FIELD_SIZE_OVERFLOW: fmt = "ADIF field %s size overflow"; break; case TQSL_ADIF_GET_FIELD_TYPE_OVERFLOW: fmt = "ADIF field %s type overflow"; break; case TQSL_ADIF_GET_FIELD_ERRONEOUS_STATE: fmt = "ADIF erroneously executing default state"; break; case TQSL_ADIF_GET_FIELD_EOF: fmt = "ADIF field %s reached End of File"; break; default: fmt = "ADIF unknown error"; break; } snprintf(errorText, sizeof errorText, fmt, ADIF_ErrorField); tqslTrace("tqsl_getADIFError", "error=%s", errorText); return( errorText ); } static TQSL_ADIF_GET_FIELD_ERROR tqsl_adifGetField(tqsl_adifFieldResults *field, FILE *filehandle, const tqsl_adifFieldDefinitions *adifFields, const char * const *typesDefined, unsigned char *(*allocator)(size_t), int *line_no) { TQSL_ADIF_GET_FIELD_ERROR status; TQSL_ADIF_STATE adifState; int currentCharacter; unsigned int iIndex; unsigned int dataLength; unsigned int dataIndex = 0; TQSL_ADIF_BOOLEAN recordData; /* get the next name value pair */ status = TQSL_ADIF_GET_FIELD_SUCCESS; adifState = TQSL_ADIF_STATE_BEGIN; /* assume that we do not wish to record this data */ recordData = TQSL_FALSE; /* clear the field buffers */ field->name[0] = '\0'; field->size[0] = '\0'; field->type[0] = '\0'; field->data = NULL; field->adifNameIndex = 0; field->userPointer = NULL; field->line_no = -1; while(adifState != TQSL_ADIF_STATE_DONE) { if (EOF != (currentCharacter = fgetc(filehandle))) { if (*line_no == 0) *line_no = 1; if (currentCharacter == '\n') (*line_no)++; switch(adifState) { case TQSL_ADIF_STATE_BEGIN: /* GET STARTED */ /* find the field opening "<", ignoring everything else */ if ('<' == currentCharacter) { adifState = TQSL_ADIF_STATE_GET_NAME; } break; case TQSL_ADIF_STATE_GET_NAME: /* GET FIELD NAME */ /* add field name characters to buffer, until '>' or ':' found */ if (('>' == currentCharacter) || (':' == currentCharacter)) { /* find if the name is a match to a LoTW supported field name */ field->line_no = *line_no; status = TQSL_ADIF_GET_FIELD_NO_NAME_MATCH; adifState = TQSL_ADIF_STATE_GET_SIZE; for(iIndex = 0; (TQSL_ADIF_GET_FIELD_NO_NAME_MATCH == status) && (0 != adifFields[iIndex].name[0]); iIndex++) { /* case insensitive compare */ if (0 == strcasecmp(field->name, adifFields[iIndex].name) || 0 == strcasecmp(adifFields[iIndex].name, "*")) { /* set name index */ field->adifNameIndex = iIndex; /* copy user pointer */ field->userPointer = adifFields[iIndex].userPointer; /* since we know the name, record the data */ recordData = TQSL_TRUE; status = TQSL_ADIF_GET_FIELD_SUCCESS; } if ('>' == currentCharacter) { adifState = TQSL_ADIF_STATE_DONE; } } } else if (strlen(field->name) < TQSL_ADIF_FIELD_NAME_LENGTH_MAX) { /* add to field match string */ strCatChar(field->name, currentCharacter); } else { status = TQSL_ADIF_GET_FIELD_NAME_LENGTH_OVERFLOW; adifState = TQSL_ADIF_STATE_DONE; } break; case TQSL_ADIF_STATE_GET_SIZE: /* GET FIELD SIZE */ /* adding field size characters to buffer, until ':' or '>' found */ if ((':' == currentCharacter) || ('>' == currentCharacter)) { /* reset data copy offset */ dataIndex = 0; /* see if any size was read in */ if (0 != field->size[0]) { /* convert data size to integer */ dataLength = strtol(field->size, NULL, 10); } else { dataLength = 0; } if (':' == currentCharacter) { /* get the type */ adifState = TQSL_ADIF_STATE_GET_TYPE; } else { /* no explicit type, set to LoTW default */ strncpy(field->type, adifFields[(field->adifNameIndex)].type, sizeof field->type); /* get the data */ adifState = dataLength == 0 ? TQSL_ADIF_STATE_DONE : TQSL_ADIF_STATE_GET_DATA; } /* only allocate if we care about the data */ if (recordData) { if (dataLength <= adifFields[(field->adifNameIndex)].max_length) { /* allocate space for data results, and ASCIIZ */ if (NULL != (field->data = (*allocator)(dataLength + 1))) { /* ASCIIZ terminator */ field->data[dataIndex] = 0; } else { status = TQSL_ADIF_GET_FIELD_NO_RESULT_ALLOCATION; adifState = TQSL_ADIF_STATE_DONE; } } else { strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_DATA_LENGTH_OVERFLOW; adifState = TQSL_ADIF_STATE_DONE; } } } else if (strlen(field->size) < TQSL_ADIF_FIELD_SIZE_LENGTH_MAX) { /* add to field size string */ strCatChar(field->size, currentCharacter); } else { strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_SIZE_OVERFLOW; adifState = TQSL_ADIF_STATE_DONE; } break; case TQSL_ADIF_STATE_GET_TYPE: /* GET FIELD TYPE */ /* get the number of characters in the value data */ if ('>' == currentCharacter) { /* check what type of field this is */ /* place default type in, if necessary */ if (0 == field->type[0]) { strncpy(field->type, adifFields[(field->adifNameIndex)].type, sizeof field->type); adifState = dataLength == 0 ? TQSL_ADIF_STATE_DONE : TQSL_ADIF_STATE_GET_DATA; } else { /* find if the type is a match to a LoTW supported data type */ strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH; adifState = TQSL_ADIF_STATE_DONE; for( iIndex = 0; (TQSL_ADIF_GET_FIELD_NO_TYPE_MATCH == status) && (0 != typesDefined[iIndex][0]); iIndex++ ) { /* case insensitive compare */ if (0 == strcasecmp(field->type, typesDefined[iIndex])) { status = TQSL_ADIF_GET_FIELD_SUCCESS; adifState = dataLength == 0 ? TQSL_ADIF_STATE_DONE : TQSL_ADIF_STATE_GET_DATA; } } } } else if (strlen(field->type) < TQSL_ADIF_FIELD_TYPE_LENGTH_MAX) { /* add to field type string */ strCatChar(field->type, currentCharacter); } else { strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_TYPE_OVERFLOW; adifState = TQSL_ADIF_STATE_DONE; } break; case TQSL_ADIF_STATE_GET_DATA: /* GET DATA */ /* read in the prescribed number of characters to form the value */ if (0 != dataLength--) { /* only record if we care about the data */ if (recordData) { /* ASCIIZ copy that is tolerant of binary data too */ field->data[dataIndex++] = (unsigned char)currentCharacter; field->data[dataIndex] = 0; } if (0 == dataLength) adifState = TQSL_ADIF_STATE_DONE; } else { adifState = TQSL_ADIF_STATE_DONE; } break; case TQSL_ADIF_STATE_DONE: /* DONE, should never get here */ default: strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_ERRONEOUS_STATE; adifState = TQSL_ADIF_STATE_DONE; break; } } else { status = TQSL_ADIF_GET_FIELD_EOF; adifState = TQSL_ADIF_STATE_DONE; } } if (TQSL_ADIF_GET_FIELD_SUCCESS == status) { /* check data for enumeration match and range errors */ /* match enumeration */ signed long dataValue; switch(adifFields[(field->adifNameIndex)].rangeType) { case TQSL_ADIF_RANGE_TYPE_NONE: break; case TQSL_ADIF_RANGE_TYPE_MINMAX: dataValue = strtol((const char *)field->data, NULL, 10); if ((dataValue < adifFields[(field->adifNameIndex)].min_value) || (dataValue > adifFields[(field->adifNameIndex)].max_value)) { strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_NO_RANGE_MATCH; } break; case TQSL_ADIF_RANGE_TYPE_ENUMERATION: strncpy(ADIF_ErrorField, field->name, sizeof(ADIF_ErrorField)); status = TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH; for( iIndex = 0; (status == TQSL_ADIF_GET_FIELD_NO_ENUMERATION_MATCH) && (0 != adifFields[(field->adifNameIndex)].enumStrings[iIndex][0]); iIndex++) { /* case insensitive compare */ if (field->data && (0 == strcasecmp((const char *)field->data, adifFields[(field->adifNameIndex)].enumStrings[iIndex]))) { status = TQSL_ADIF_GET_FIELD_SUCCESS; ADIF_ErrorField[0] = '\0'; } } break; } } return( status ); } DLLEXPORT int CALLCONVENTION tqsl_getADIFField(tQSL_ADIF adifp, tqsl_adifFieldResults *field, TQSL_ADIF_GET_FIELD_ERROR *status, const tqsl_adifFieldDefinitions *adifFields, const char * const *typesDefined, unsigned char *(*allocator)(size_t) ) { TQSL_ADIF *adif; if (!(adif = check_adif(adifp))) return 1; if (field == NULL || status == NULL || adifFields == NULL || typesDefined == NULL || allocator == NULL) { tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } *status = tqsl_adifGetField(field, adif->fp, adifFields, typesDefined, allocator, &(adif->line_no)); return 0; } static unsigned char * tqsl_condx_copy(const unsigned char *src, int slen, unsigned char *dest, int *len) { if (slen == 0) return dest; if (slen < 0) slen = strlen((const char *)src); if (*len < slen) { tQSL_Error = TQSL_BUFFER_ERROR; return NULL; } memcpy(dest, src, slen); *len -= slen; return dest+slen; } /* Output an ADIF field to a file descriptor. */ DLLEXPORT int CALLCONVENTION tqsl_adifMakeField(const char *fieldname, char type, const unsigned char *value, int len, unsigned char *buf, int buflen) { if (fieldname == NULL || buf == NULL || buflen <= 0) { /* Silly caller */ tQSL_Error = TQSL_ARGUMENT_ERROR; return 1; } unsigned char *cp; if ((cp = tqsl_condx_copy((const unsigned char *)"<", 1, buf, &buflen)) == NULL) return 1; if ((cp = tqsl_condx_copy((const unsigned char *)fieldname, -1, cp, &buflen)) == NULL) return 1; if (value != NULL && len < 0) len = strlen((const char *)value); if (value != NULL && len != 0) { char nbuf[20]; if ((cp = tqsl_condx_copy((const unsigned char *)":", 1, cp, &buflen)) == NULL) return 1; snprintf(nbuf, sizeof nbuf, "%d", len); if ((cp = tqsl_condx_copy((const unsigned char *)nbuf, -1, cp, &buflen)) == NULL) return 1; if (type && type != ' ' && type != '\0') { if ((cp = tqsl_condx_copy((const unsigned char *)":", 1, cp, &buflen)) == NULL) return 1; if ((cp = tqsl_condx_copy((const unsigned char *)&type, 1, cp, &buflen)) == NULL) return 1; } if ((cp = tqsl_condx_copy((const unsigned char *)">", 1, cp, &buflen)) == NULL) return 1; if ((cp = tqsl_condx_copy(value, len, cp, &buflen)) == NULL) return 1; } else { if ((cp = tqsl_condx_copy((const unsigned char *)">", 1, cp, &buflen)) == NULL) return 1; } if ((cp = tqsl_condx_copy((const unsigned char *)"", 1, cp, &buflen)) == NULL) return 1; return 0; } tqsl-2.7.2/src/LICENSE0000644000175000017500000000450714534122221014301 0ustar rmurphyrmurphyLicense Terms and Conditions Copyright (C) 2001-2020 American Radio Relay League, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Any redistribution of source code must retain the above copyright notice, this list of conditions and the disclaimer shown in Paragraph 5 (below). 2. Redistribution in binary form must reproduce the above copyright notice, this list of conditions and the disclaimer shown in Paragraph 5 (below) in the documentation and/or other materials provided with the distribution. 3. Products derived from or including this software may not use "Logbook of the World" or "LoTW" or any other American Radio Relay League, Incorporated trademarks or servicemarks in their names without prior written permission of the ARRL. See Paragraph 6 (below) for contact information. 4. Use of this software does not imply endorsement by ARRL of products derived from or including this software and vendors may not claim such endorsement. 5. Disclaimer: This software is provided "as-is" without representation, guarantee or warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability or of fitness for a particular purpose. The entire risk as to the quality and performance of the software is solely with you. Should the software prove defective, you (and not the American Radio Relay League, its officers, directors, employees or agents) assume the entire cost of all necessary servicing, repair or correction. In no event will ARRL be liable to you or to any third party for any damages, whether direct or indirect, including lost profits, lost savings, or other incidental or consequential damages arising out of the use or inability to use such software, regardless of whether ARRL has been advised of the possibility of such damages. 6. Contact information: American Radio Relay League, Inc. Attn: Logbook of the World Manager 225 Main St Newington, CT 06111 voice: 860-594-0200 fax: 860-594-0259 email: logbook@arrl.org Worldwide Web: www.arrl.org This software consists of voluntary contributions made by many individuals on behalf of the ARRL. More information on the "Logbook of The World" project and the ARRL is available from the ARRL Web site at www.arrl.org. tqsl-2.7.2/src/Doxyfile0000755000175000017500000033760614534122221015016 0ustar rmurphyrmurphy# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the configuration # file that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "TrustedQSL Library API" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doxygen # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all generated output in the proper direction. # Possible values are: None, LTR, RTL and Context. # The default value is: None. OUTPUT_TEXT_DIRECTION = None # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be # interpreted by doxygen. # The default value is: NO. JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # By default Python docstrings are displayed as preformatted text and doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the # doxygen's special commands can be used and the contents of the docstring # documentation blocks is shown as doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. # When you need a literal { or } or , in the value part of an alias you have to # escape them by means of a backslash (\), this can lead to conflicts with the # commands \{ and \} for these it is advised to use the version @{ and @} or use # a double escape (\\{ and \\}) ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice # sources only. Doxygen will then generate output that is more tailored for that # language. For instance, namespaces will be presented as modules, types will be # separated into more groups, etc. # The default value is: NO. OPTIMIZE_OUTPUT_SLICE = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 # The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which efficively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If this flag is set to YES, the name of an unnamed parameter in a declaration # will be determined by the corresponding definition. By default unnamed # parameters remain unnamed in the output. # The default value is: YES. RESOLVE_UNNAMED_PARAMS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # With the correct setting of option CASE_SENSE_NAMES doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that # are not case sensitive the option should be be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. If # EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. # Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = tqsllib-doc.h \ tqsllib.h \ tqslerrno.h \ adif.h \ cabrillo.h \ tqslconvert.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), # *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, # *.ucf, *.qsf and *.ice. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for # which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to # YES then doxygen will add the directory of each input to the include path. # The default value is: YES. CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the # path to the directory containing a file called compile_commands.json. This # file is the compilation database (see: # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the # options used when the source files were built. This is equivalent to # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = NO # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = tqsllib.css # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To # create a documentation set, doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: # https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. # Possible values are: png (the default) and svg (looks nicer but requires the # pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. # The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /