forked from pEp.foundation/libAccountSettings
Compare commits
5 Commits
Author | SHA1 | Date |
---|---|---|
|
5a49f837a1 | |
|
afbcf7421a | |
|
ddb405d480 | |
|
85565bbd79 | |
|
c2c1e0d67c |
|
@ -1,70 +0,0 @@
|
|||
# Xcode
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xccheckout
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
playground.xcworkspace
|
||||
|
||||
## Swift Package Manager
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
# Package.pins
|
||||
# Package.resolved
|
||||
.build/
|
||||
|
||||
## Xcode Patch ###
|
||||
**/xcshareddata/WorkspaceSettings.xcsettings
|
||||
|
||||
# macOS
|
||||
|
||||
## General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
## Icon must end with two \r
|
||||
Icon
|
||||
|
||||
## Thumbnails
|
||||
._*
|
||||
|
||||
## Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
## Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
|
@ -0,0 +1,6 @@
|
|||
regexp
|
||||
\.DS_Store
|
||||
xcuserdata/.*
|
||||
\.orig$
|
||||
\.git/
|
||||
\.gitkeep
|
|
@ -1,23 +0,0 @@
|
|||
<clientConfig version="1.1">
|
||||
<emailProvider id="e-foundation">
|
||||
<domain>e.email</domain>
|
||||
<domain>ecloud.global</domain>
|
||||
|
||||
<displayName>e Foundation</displayName>
|
||||
<displayShortName>e Foundation</displayShortName>
|
||||
<incomingServer type="imap">
|
||||
<hostname>mail.ecloud.global</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</incomingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>mail.ecloud.global</hostname>
|
||||
<port>587</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
</emailProvider>
|
||||
</clientConfig>
|
|
@ -1,61 +0,0 @@
|
|||
<clientConfig version="1.1">
|
||||
<emailProvider id="M-net">
|
||||
<domain>16000-kbits.de</domain>
|
||||
<domain>7fun.de</domain>
|
||||
<domain>a-city.de</domain>
|
||||
<domain>alpenbazi.de</domain>
|
||||
<domain>amberg-mail.de</domain>
|
||||
<domain>augustakom.net</domain>
|
||||
<domain>bayern-mail.de</domain>
|
||||
<domain>club-goes-uefacup.de</domain>
|
||||
<domain>dachau-mail.de</domain>
|
||||
<domain>erding-mail.de</domain>
|
||||
<domain>es-laendle.de</domain>
|
||||
<domain>familien-postfach.de</domain>
|
||||
<domain>fcn-cluberer.de</domain>
|
||||
<domain>frankenbeutel-mail.de</domain>
|
||||
<domain>franken-ist-cool.de</domain>
|
||||
<domain>franken-online.de</domain>
|
||||
<domain>ich-liebe-franken.de</domain>
|
||||
<domain>ich-mag-net.de</domain>
|
||||
<domain>ingolstadt-mail.de</domain>
|
||||
<domain>loewen-mail.de</domain>
|
||||
<domain>maxi-allgaeu.de</domain>
|
||||
<domain>maxi-bayern.de</domain>
|
||||
<domain>maxi-dsl.de</domain>
|
||||
<domain>maxi-schwaben.de</domain>
|
||||
<domain>mnet-mail.de</domain>
|
||||
<domain>mnet-online.de</domain>
|
||||
<domain>muenchen-ist-toll.de</domain>
|
||||
<domain>muenchen-mail.de</domain>
|
||||
<domain>muenchen-surf.de</domain>
|
||||
<domain>myway.de</domain>
|
||||
<domain>nefkom.info</domain>
|
||||
<domain>nefkom.net</domain>
|
||||
<domain>neumarkt-mail.de</domain>
|
||||
<domain>post-ist-da.de</domain>
|
||||
<domain>regensburg-mail.de</domain>
|
||||
<domain>rotgruenweiss.de</domain>
|
||||
<domain>starnberg-mail.de</domain>
|
||||
<domain>unser-postfach.de</domain>
|
||||
<domain>weissblautsv.de</domain>
|
||||
<domain>wir-datschiburger.de</domain>
|
||||
|
||||
<displayName>M-net Telekommunikations GmbH</displayName>
|
||||
<displayShortName>M-net</displayShortName>
|
||||
<incomingServer type="imap">
|
||||
<hostname>imap.mnet-online.de</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</incomingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>mail.mnet-online.de</hostname>
|
||||
<port>587</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
</emailProvider>
|
||||
</clientConfig>
|
|
@ -1,22 +0,0 @@
|
|||
<clientConfig version="1.1">
|
||||
<emailProvider id="Mailfence">
|
||||
<domain>mailfence.com</domain>
|
||||
|
||||
<displayName>Mailfence</displayName>
|
||||
<displayShortName>Mailfence</displayShortName>
|
||||
<incomingServer type="imap">
|
||||
<hostname>imap.mailfence.com</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</incomingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>smtp.mailfence.com</hostname>
|
||||
<port>465</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
</emailProvider>
|
||||
</clientConfig>
|
|
@ -1,21 +0,0 @@
|
|||
<clientConfig version="1.1">
|
||||
<emailProvider id="pep-security.net">
|
||||
<domain>pep-security.net</domain>
|
||||
<displayName>pEp Security S.A.</displayName>
|
||||
<displayShortName>pEp Security S.A.</displayShortName>
|
||||
<incomingServer type="imap">
|
||||
<hostname>mail.pep-security.net</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</incomingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>mail.pep-security.net</hostname>
|
||||
<port>587</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
</emailProvider>
|
||||
</clientConfig>
|
|
@ -1,21 +0,0 @@
|
|||
<clientConfig version="1.1">
|
||||
<emailProvider id="pep.digital">
|
||||
<domain>pep.digital</domain>
|
||||
<displayName>p≡p Security S.A.</displayName>
|
||||
<displayShortName>p≡p Security S.A.</displayShortName>
|
||||
<incomingServer type="imap">
|
||||
<hostname>mail.peptest.ch</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</incomingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>mail.peptest.ch</hostname>
|
||||
<port>465</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
</emailProvider>
|
||||
</clientConfig>
|
|
@ -1,21 +0,0 @@
|
|||
<clientConfig version="1.1">
|
||||
<emailProvider id="pep.security">
|
||||
<domain>pep.security</domain>
|
||||
<displayName>p≡p Security S.A.</displayName>
|
||||
<displayShortName>p≡p Security S.A.</displayShortName>
|
||||
<incomingServer type="imap">
|
||||
<hostname>mail.pep.security</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</incomingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>mail.pep.security</hostname>
|
||||
<port>465</port>
|
||||
<socketType>SSL</socketType>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
</emailProvider>
|
||||
</clientConfig>
|
|
@ -52,15 +52,6 @@ const struct AccountSettings* get_account_settings(const char* accountName, cons
|
|||
AS_STATUS AS_get_status(const struct AccountSettings* account_settings);
|
||||
|
||||
|
||||
/** get the privder id string of the account_settings
|
||||
*
|
||||
* @param account_settings the account settings your want to get provider id
|
||||
* @return the provider id, if any. Might be NULL or empty string.
|
||||
The pointer points to internal r/o data in accountSettings, do not delete it!
|
||||
*/
|
||||
const char* AS_get_provider_id(const struct AccountSettings* account_settings);
|
||||
|
||||
|
||||
/** get the server settings for "incoming" messages (e.g. IMAP or POP3)
|
||||
* @param accountSettings guess what
|
||||
* @return the server for incoming messages associated with the accountSettings.
|
||||
|
|
|
@ -31,27 +31,21 @@ typedef enum _AS_STATUS
|
|||
typedef enum _AS_FLAGS
|
||||
{
|
||||
AS_FLAG_USE_LOCAL_ISP_DB = 0x0010, ///< use local ISP database
|
||||
// FIXME: local-only heuristics? Is that possible/sensible?
|
||||
// AS_FLAG_USE_HEURISTICS = 0x0020, ///< use heuristics from account's domain name
|
||||
AS_FLAG_USE_ANY_LOCAL = 0x000F, ///< use all local (without communication to 3rd parties) methods in ascending order
|
||||
|
||||
AS_FLAG_USE_MOZ_AUTOCONFIG = 0x0100, ///< fetch account config via Mozilla's "autoconfig" method
|
||||
AS_FLAG_USE_MS_AUTODISCOVER = 0x0200, ///< fetch account config via Microsoft's "autodiscover" method
|
||||
AS_FLAG_USE_DNS_SRV = 0x0400, ///< use DNS SRV records for the mail domain
|
||||
AS_FLAG_USE_ONLINE_ISP_DB = 0x0800, ///< ask https://live.mozillamessaging.com/autoconfig/v1.1/$DOMAINNAME
|
||||
AS_FLAG_USE_ANY_ONLINE = 0x0F00, ///< try all (almost) reliable online configuration methods in ascending order
|
||||
|
||||
AS_FLAG_USE_GUESSING = 0x1000, ///< guess server names and try to detect its login methods. MAY BE DANGEROUS!
|
||||
|
||||
AS_FLAG_USE_ANY = 0xFFFF ///< try first local, than network methods
|
||||
AS_FLAG_USE_HEURISTICS = 0x0020, ///< use heuristics from account's domain name
|
||||
AS_FLAG_USE_ANY_LOCAL = 0x00FF, ///< use all local (without communication to 3rd parties) methods in ascending order
|
||||
AS_FLAG_USE_DNS_AUTOCONFIG = 0x0100, ///< fetch account config from "autodiscover/autoconfig" servers
|
||||
AS_FLAG_USE_DNS_SRV = 0x0110, ///< use DNS SRV records for the mail domain
|
||||
AS_FLAG_USE_ONLINE_ISP_DB = 0x0800, ///< ask https://live.mozillamessaging.com/autoconfig/v1.1/$DOMAINNAME
|
||||
AS_FLAG_USE_ANY = 0xFFFF ///< try first local, than network methods
|
||||
} AS_FLAGS;
|
||||
|
||||
|
||||
//! Combination of protocol, socket type & authentication type
|
||||
typedef enum _AS_ACCESS
|
||||
{
|
||||
AS_ACCESS_UNKNOWN = 0, ///< unknown / undetermined authentication type. Used as error value.
|
||||
|
||||
/// protocols
|
||||
AS_PROTO_EXCHANGE = 0x00008, ///< both (?) - selected with very low precedence
|
||||
AS_PROTO_POP3 = 0x00011, ///< incoming
|
||||
AS_PROTO_IMAP = 0x00012, ///< incoming
|
||||
AS_PROTO_SMTP = 0x00021, ///< outgoing
|
||||
|
|
23
src/Makefile
23
src/Makefile
|
@ -2,6 +2,19 @@
|
|||
|
||||
CXX=c++ -Wall -O0 -std=c++11 -g -I../include/ -I/usr/local/include -L/usr/local/lib
|
||||
|
||||
###############
|
||||
#
|
||||
# Dear maintainer! Please set up this definition for your system:
|
||||
# platform dependend libraries:
|
||||
|
||||
# Linux:
|
||||
LIBS=-lldns -lpthread -lboost_system
|
||||
|
||||
|
||||
#
|
||||
############ end of platform-dependend config, I hope so ########
|
||||
|
||||
|
||||
all: libAccountSettings.a test
|
||||
|
||||
test: accountSettings_test
|
||||
|
@ -10,18 +23,20 @@ test: accountSettings_test
|
|||
isp_db: isp_db.cc
|
||||
|
||||
isp_db.cc: xml2cxx
|
||||
./xml2cxx ../../autoconfig/* ../example/* > $@
|
||||
./xml2cxx ../../autoconfig/* > $@
|
||||
|
||||
xml2cxx: xml2cxx.o tinyxml2.o account_settings_internal.o stringpool.o
|
||||
${CXX} -o $@ $^
|
||||
|
||||
accountSettings_test: accountSettings_test.o libAccountSettings.a
|
||||
${CXX} -o $@ $^ -lldns -lcrypto -lssl
|
||||
${CXX} -o $@ $^ ${LIBS}
|
||||
|
||||
libAccountSettings.a: account_settings_internal.o implementation.o \
|
||||
isp_db.o http_client.o \
|
||||
isp_db.o \
|
||||
boost_asio.o \
|
||||
from_heuristics.o \
|
||||
from_srv.o
|
||||
${AR} rcs $@ $^
|
||||
ar rcs $@ $^
|
||||
|
||||
%.o : %.cc %.hh
|
||||
${CXX} -o $@ -c $<
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// unit test program for libAccountSettings
|
||||
|
||||
#include "../include/account_settings_c.h"
|
||||
#include "account_settings_internal.hh"
|
||||
#include "from_srv.hh"
|
||||
#include "http_client.hh"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
@ -21,26 +19,25 @@ struct TestHost
|
|||
{
|
||||
std::string name;
|
||||
int port;
|
||||
unsigned access;
|
||||
};
|
||||
|
||||
// stored in ISP DB
|
||||
const std::vector< KeyValue< TestHost> > incomingServer =
|
||||
{
|
||||
{ "lib_as@peptest.ch", {"peptest.ch" , 993, AS_PROTO_IMAP | AS_SOCK_SSL | AS_AUTH_PW_CLEARTEXT} },
|
||||
{ "example@gmx.de" , {"imap.gmx.net" , 993, AS_PROTO_IMAP | AS_SOCK_SSL | AS_AUTH_PW_CLEARTEXT} },
|
||||
{ "example@yandex.ua", {"imap.yandex.com", 993, AS_PROTO_IMAP | AS_SOCK_SSL | AS_AUTH_PW_CLEARTEXT} },
|
||||
{ "example@yahoo.com", {"imap.mail.yahoo.com", 993, AS_PROTO_IMAP | AS_SOCK_SSL | AS_AUTH_OAUTH2} },
|
||||
{ "lib_as@peptest.ch", {"peptest.ch", 993} },
|
||||
{ "example@gmx.de" , {"imap.gmx.net", 993} },
|
||||
{ "example@yandex.ua", {"imap.yandex.com", 993} },
|
||||
};
|
||||
|
||||
// stored in ISP DB
|
||||
const std::vector< KeyValue< TestHost> > outgoingServer =
|
||||
{
|
||||
{ "lib_as@peptest.ch", {"peptest.ch" , 587, AS_PROTO_SMTP | AS_SOCK_STARTTLS | AS_AUTH_PW_CLEARTEXT} },
|
||||
{ "example@gmx.de" , {"mail.gmx.net" , 465, AS_PROTO_SMTP | AS_SOCK_SSL | AS_AUTH_PW_CLEARTEXT} },
|
||||
{ "example@yandex.ua", {"smtp.yandex.com", 465, AS_PROTO_SMTP | AS_SOCK_SSL | AS_AUTH_PW_CLEARTEXT} },
|
||||
{ "lib_as@peptest.ch", {"peptest.ch", 587} },
|
||||
{ "example@gmx.de" , {"mail.gmx.net", 465} },
|
||||
{ "example@yandex.ua", {"smtp.yandex.com", 465} },
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
template<class TestData, class Function >
|
||||
bool testServers( const TestData& testData, Function testFunc )
|
||||
|
@ -69,14 +66,6 @@ bool testServers( const TestData& testData, Function testFunc )
|
|||
okay = false;
|
||||
}
|
||||
|
||||
const AS_ACCESS acc = AS_get_access_method(srv);
|
||||
if( acc != AS_ACCESS(t.value.access) )
|
||||
{
|
||||
std::cerr << "Got access method " << std::hex << acc << ", expected " << t.value.access << " for account " << t.key << std::dec << "!\n";
|
||||
okay = false;
|
||||
}
|
||||
|
||||
|
||||
free_account_settings(as);
|
||||
}
|
||||
|
||||
|
@ -93,49 +82,22 @@ bool testSRV()
|
|||
}
|
||||
|
||||
|
||||
bool testHttp()
|
||||
{
|
||||
using account_settings::http_get_file;
|
||||
|
||||
bool okay = true;
|
||||
|
||||
okay &= (http_get_file("autoconfig.peptest.ch", 80, "/mail/config-v1.1.xml", false).size() > 0);
|
||||
|
||||
bool invalid_host = false;
|
||||
try
|
||||
{
|
||||
http_get_file("invalid-host.pep.lol", 80, "/dontmatter", false);
|
||||
}catch(...)
|
||||
{
|
||||
invalid_host = true;
|
||||
}
|
||||
okay &= invalid_host;
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
try{
|
||||
if(argc>1)
|
||||
{
|
||||
for(int a=1; a<argc; ++a)
|
||||
{
|
||||
std::cout << a << ": " << std::endl;
|
||||
printf("#%d : ", a);
|
||||
auto as = std::unique_ptr<AccountSettings>{ new AccountSettings };
|
||||
get_settings_from_srv( as.get(), "foo@bar.com", argv[a], "dummy");
|
||||
if( AS_get_status( as.get() ) == AS_OK )
|
||||
{
|
||||
std::cout << *as.get() << std::endl;
|
||||
}else{
|
||||
std::cout << "No SRV record for \"" << argv[a] << "\". :-(" << std::endl;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
bool all_okay = true;
|
||||
all_okay &= testServers( incomingServer, &AS_get_incoming );
|
||||
all_okay &= testServers( outgoingServer, &AS_get_outgoing );
|
||||
all_okay &= testHttp();
|
||||
|
||||
all_okay &= testSRV();
|
||||
|
||||
std::cout << "***\t" << (all_okay ? "All tests are okay." : "ERROS happened") << std::endl;
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <set>
|
||||
#include <ostream>
|
||||
|
||||
// public names, must be accessible from C, so no namespace here:
|
||||
struct AS_Server
|
||||
{
|
||||
std::string name;
|
||||
|
@ -31,7 +30,6 @@ std::ostream& operator<<(std::ostream& o, const AS_Server& srv);
|
|||
std::ostream& operator<<(std::ostream& o, const AccountSettings& as);
|
||||
|
||||
|
||||
namespace account_settings {
|
||||
// for static ISP DB:
|
||||
struct AS_Server_DB
|
||||
{
|
||||
|
@ -49,6 +47,4 @@ struct AccountSettings_DB
|
|||
AS_Server_DB outgoing;
|
||||
};
|
||||
|
||||
} // end of namespace account_settings
|
||||
|
||||
#endif // ACCOUNT_SETTINGS_INTERNAL_HH
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#include "boost_asio.hh"
|
||||
|
||||
// compile the whole boost.asio stuff here once, instead of in every header:
|
||||
#include <boost/asio/impl/src.hpp>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef LAS_BOOST_ASIO_HH
|
||||
#define LAS_BOOST_ASIO_HH
|
||||
|
||||
// for separate compilation this macro must be defined before any boost.asio header is included
|
||||
#define BOOST_ASIO_SEPARATE_COMPILATION
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
#include "from_heuristics.hh"
|
||||
#include "account_settings_internal.hh"
|
||||
#include <ldns/ldns.h>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include "boost_asio.hh"
|
||||
|
||||
|
||||
class protocol_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
protocol_error() : std::runtime_error("Protocol error!")
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace bio = boost::asio;
|
||||
using bio::ip::tcp;
|
||||
|
||||
// TODO: implement!
|
||||
class Protocol
|
||||
{
|
||||
public:
|
||||
Protocol() {}
|
||||
virtual ~Protocol() {}
|
||||
|
||||
/// (re)initialize the protocol and thet the AS_Server to initial state
|
||||
virtual void init(AS_Server& ass) = 0;
|
||||
|
||||
/// say something to the server. if nothing to say in this state, it returns empty string
|
||||
virtual std::string put() = 0;
|
||||
|
||||
/// return true if guessing was successful
|
||||
virtual bool get(const std::string& s) = 0;
|
||||
};
|
||||
|
||||
|
||||
class Imap : public Protocol
|
||||
{
|
||||
public:
|
||||
Imap() {}
|
||||
virtual ~Imap() {}
|
||||
virtual void init(AS_Server& ass) override { /* TODO: implement! */ }
|
||||
virtual std::string put() override { return ""; }
|
||||
virtual bool get(const std::string& s) override { return s.empty(); }
|
||||
};
|
||||
|
||||
|
||||
AS_Server pingpong(const std::string& server, int port, Protocol& p)
|
||||
{
|
||||
AS_Server ass{ "", -1, AS_ACCESS_UNKNOWN, "" };
|
||||
try{
|
||||
std::vector<char> buffer(2048);
|
||||
bio::io_service ios;
|
||||
tcp::resolver res(ios);
|
||||
tcp::resolver::query query( server, std::to_string(port) );
|
||||
for(auto iter = res.resolve(query); iter != tcp::resolver::iterator(); ++iter)
|
||||
{
|
||||
p.init(ass);
|
||||
tcp::socket s(ios);
|
||||
bio::connect(s, iter);
|
||||
boost::system::error_code err;
|
||||
|
||||
while(ass.access == AS_ACCESS_UNKNOWN)
|
||||
{
|
||||
const std::string output = p.put();
|
||||
if(!output.empty())
|
||||
{
|
||||
bio::write(s, bio::buffer(output), err);
|
||||
}
|
||||
|
||||
const size_t length = s.read_some( boost::asio::buffer(buffer), err);
|
||||
if(!err || err == bio::error::eof)
|
||||
{
|
||||
if( p.get( std::string( buffer.data(), buffer.data()+length) ) )
|
||||
{
|
||||
return ass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(std::runtime_error&) { /* just return what we have so far */ }
|
||||
|
||||
return ass;
|
||||
}
|
||||
|
||||
|
||||
AS_Server probe_server(const std::string& domain, std::initializer_list<std::string> names, std::initializer_list<int> ports, Protocol& p )
|
||||
{
|
||||
for(auto port : ports)
|
||||
for(auto name : names)
|
||||
{
|
||||
const std::string server = domain + "." + name;
|
||||
const AS_Server ass = pingpong(server, port, p);
|
||||
if(ass.access != AS_ACCESS_UNKNOWN)
|
||||
return ass;
|
||||
}
|
||||
|
||||
return AS_Server{ "", -1, AS_ACCESS_UNKNOWN, "" };
|
||||
}
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
||||
|
||||
AccountSettings* get_settings_from_heuristics(AccountSettings* as, const std::string& accountName, const std::string& domain, const std::string& provider)
|
||||
{
|
||||
if(as==nullptr)
|
||||
{
|
||||
throw std::runtime_error("get_settings_from_heuristics shall not be called with NULL pointer!");
|
||||
}
|
||||
|
||||
// fprintf(stderr, "== IMAP ==\n");
|
||||
try{
|
||||
Imap imap_protocol;
|
||||
as->incoming = probe_server( domain, {"imap", "mail", "imaps", "imapmail", "imap-mail", "mx", "", "mbox"}, {143, 993}, imap_protocol );
|
||||
}catch( const protocol_error& )
|
||||
{
|
||||
// ignore protocol errors
|
||||
}
|
||||
|
||||
// fprintf(stderr, "== SMTP ==\n");
|
||||
try{
|
||||
Imap smtp_protocol;
|
||||
as->outgoing = probe_server( domain, {"smtp", "mail", "smtps", "smtpmail", "smtp-mail", "mx", "", "smtpauth",}, {25, 587, 465}, smtp_protocol );
|
||||
}catch( const protocol_error& )
|
||||
{
|
||||
// ignore protocol errors
|
||||
}
|
||||
|
||||
return as;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef ACCOUNT_SETTINGS_FROM_HEURISTICS_HH
|
||||
#define ACCOUNT_SETTINGS_FROM_HEURISTICS_HH
|
||||
|
||||
#include "account_settings_internal.hh"
|
||||
|
||||
AccountSettings* get_settings_from_heuristics(AccountSettings* as, const std::string& accountName, const std::string& domain, const std::string& provider);
|
||||
|
||||
#endif // ACCOUNT_SETTINGS_FROM_HEURISTICS_HH
|
|
@ -131,15 +131,10 @@ SRV get_srv_server(const std::string& domain, const std::string& service)
|
|||
ldns_buffer* buf_host = ldns_buffer_new(128);
|
||||
ldns_rdf2buffer_str_dname( buf_host, rdf_host);
|
||||
|
||||
std::string host = ldns_rdf_get_type(rdf_host)==LDNS_RDF_TYPE_DNAME ? std::string( (const char*)buf_host->_data, buf_host->_position) : "{°?°}";
|
||||
const std::string host = ldns_rdf_get_type(rdf_host)==LDNS_RDF_TYPE_DNAME ? std::string( (const char*)buf_host->_data, buf_host->_limit) : "{°?°}";
|
||||
ldns_buffer_free(buf_host);
|
||||
buf_host=nullptr;
|
||||
|
||||
while( (host.size() > 0) && (host.back() == '.') )
|
||||
{
|
||||
host.pop_back();
|
||||
}
|
||||
|
||||
// printf("***\tPrio: %u, Weight: %u, Port: %u, Host: \"%s\".\n", priority, weight, port, host.c_str());
|
||||
|
||||
return SRV{ priority, weight, port, host };
|
||||
|
@ -154,35 +149,14 @@ AccountSettings* get_settings_from_srv(AccountSettings* as, const std::string& a
|
|||
{
|
||||
throw std::runtime_error("get_settings_from_srv shall not be called with NULL pointer!");
|
||||
}
|
||||
|
||||
bool imap_okay = false;
|
||||
bool smtp_okay = false;
|
||||
|
||||
// fprintf(stderr, "== IMAPS ==\n");
|
||||
try{
|
||||
const SRV imap_srv = get_srv_server( domain, "_imaps._tcp" );
|
||||
if(imap_srv.is_valid())
|
||||
{
|
||||
as->incoming.name = imap_srv.hostname;
|
||||
as->incoming.port = imap_srv.port;
|
||||
as->incoming.access = AS_ACCESS(AS_PROTO_IMAP | AS_SOCK_SSL);
|
||||
imap_okay = true;
|
||||
}
|
||||
}catch( const DNS_error& )
|
||||
{
|
||||
// ignore unsuccessful DNS queries
|
||||
}
|
||||
|
||||
// fprintf(stderr, "== IMAP ==\n");
|
||||
if( !imap_okay ) // let's try with plain IMAP nexr (with possibly STARTTLS later)
|
||||
try{
|
||||
const SRV imap_srv = get_srv_server( domain, "_imap._tcp" );
|
||||
if(imap_srv.is_valid())
|
||||
{
|
||||
as->incoming.name = imap_srv.hostname;
|
||||
as->incoming.port = imap_srv.port;
|
||||
as->incoming.access = AS_PROTO_IMAP;
|
||||
imap_okay = true;
|
||||
}
|
||||
}catch( const DNS_error& )
|
||||
{
|
||||
|
@ -196,18 +170,11 @@ AccountSettings* get_settings_from_srv(AccountSettings* as, const std::string& a
|
|||
{
|
||||
as->outgoing.name = smtp_srv.hostname;
|
||||
as->outgoing.port = smtp_srv.port;
|
||||
as->outgoing.access = AS_PROTO_SMTP;
|
||||
smtp_okay = true;
|
||||
}
|
||||
}catch( const DNS_error& )
|
||||
{
|
||||
// ignore unsuccessful DNS queries
|
||||
}
|
||||
|
||||
if(imap_okay && smtp_okay)
|
||||
{
|
||||
as->status = AS_OK;
|
||||
}
|
||||
|
||||
return as;
|
||||
}
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
#include "http_client.hh"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
|
||||
namespace account_settings
|
||||
{
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
namespace ssl = boost::asio::ssl;
|
||||
|
||||
// returns the content of the given http://host:port/path as string
|
||||
// might throw HttpError
|
||||
// implementation based on https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio/example/cpp03/http/client/sync_client.cpp
|
||||
// (Boost license 1.0)
|
||||
std::string http_get_file(const std::string& host, int port, const std::string& path, bool tls)
|
||||
{
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
// Get a list of endpoints corresponding to the server name.
|
||||
tcp::resolver resolver(io_context);
|
||||
tcp::resolver::results_type endpoints = resolver.resolve(host, std::to_string(port));
|
||||
|
||||
tcp::socket* socket = nullptr;
|
||||
if(tls)
|
||||
{
|
||||
ssl::context ctx(ssl::context::sslv23);
|
||||
|
||||
}else{
|
||||
// Try each endpoint until we successfully establish a connection.
|
||||
socket = new tcp::socket(io_context);
|
||||
boost::asio::connect(*socket, endpoints);
|
||||
}
|
||||
// Form the request. We specify the "Connection: close" header so that the
|
||||
// server will close the socket after transmitting the response. This will
|
||||
// allow us to treat all data up until the EOF as the content.
|
||||
boost::asio::streambuf request;
|
||||
std::ostream request_stream(&request);
|
||||
request_stream << "GET " << path << " HTTP/1.0\r\n"
|
||||
<< "Host: " << host << "\r\n"
|
||||
<< "Accept: */*\r\n"
|
||||
<< "Connection: close\r\n\r\n";
|
||||
|
||||
// Send the request.
|
||||
boost::asio::write(*socket, request);
|
||||
|
||||
// Read the response status line. The response streambuf will automatically
|
||||
// grow to accommodate the entire line. The growth may be limited by passing
|
||||
// a maximum size to the streambuf constructor.
|
||||
boost::asio::streambuf response;
|
||||
boost::asio::read_until(*socket, response, "\r\n");
|
||||
|
||||
// Check that response is OK.
|
||||
std::istream response_stream(&response);
|
||||
std::string http_version;
|
||||
response_stream >> http_version;
|
||||
unsigned int status_code;
|
||||
response_stream >> status_code;
|
||||
std::string status_message;
|
||||
std::getline(response_stream, status_message);
|
||||
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
|
||||
{
|
||||
throw HttpError(host, port, path, -1, http_version);
|
||||
}
|
||||
|
||||
if (status_code != 200)
|
||||
{
|
||||
throw HttpError(host, port, path, status_code, status_message);
|
||||
}
|
||||
|
||||
// Read the response headers, which are terminated by a blank line.
|
||||
boost::asio::read_until(*socket, response, "\r\n\r\n");
|
||||
/*
|
||||
// Process the response headers.
|
||||
std::string header;
|
||||
while (std::getline(response_stream, header) && header != "\r")
|
||||
std::cout << header << "\n";
|
||||
std::cout << "\n";
|
||||
|
||||
// Write whatever content we already have to output.
|
||||
if (response.size() > 0)
|
||||
std::cout << &response;
|
||||
*/
|
||||
// Read until EOF, writing data to output as we go.
|
||||
std::string content;
|
||||
|
||||
boost::system::error_code error;
|
||||
while (boost::asio::read(*socket, response,
|
||||
boost::asio::transfer_at_least(1), error))
|
||||
{
|
||||
auto bufs = response.data();
|
||||
auto begin = boost::asio::buffers_begin(bufs);
|
||||
content.append(begin, begin + bufs.size());
|
||||
}
|
||||
|
||||
if (error != boost::asio::error::eof)
|
||||
throw boost::system::system_error(error);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
} // end of namespace account_settings
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef ACCOUNT_SETTINGS_HTTP_CLIENT_HH
|
||||
#define ACCOUNT_SETTINGS_HTTP_CLIENT_HH
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace account_settings
|
||||
{
|
||||
|
||||
class HttpError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
HttpError(const std::string& _host, int _port, const std::string& _path,
|
||||
int _error_code, const std::string& _error_message)
|
||||
: std::runtime_error{ "HTTP Error for http://" + _host + ":" + std::to_string(_port) + _path
|
||||
+ " : Status=" + std::to_string(_error_code) + (_error_message.empty() ? "" : (": " + _error_message) )}
|
||||
, host{_host}
|
||||
, port{_port}
|
||||
, path{_path}
|
||||
, error_code{_error_code}
|
||||
, error_message{_error_message}
|
||||
{}
|
||||
|
||||
// are public by intention
|
||||
const std::string host;
|
||||
const int port;
|
||||
const std::string path;
|
||||
const int error_code;
|
||||
const std::string error_message;
|
||||
};
|
||||
|
||||
|
||||
// returns the content of the given http://host:port/path as string
|
||||
// might throw HttpError
|
||||
std::string http_get_file(const std::string& host, int port, const std::string& path, bool tls);
|
||||
|
||||
} // end of namespace account_settings
|
||||
|
||||
#endif // ACCOUNT_SETTINGS_HTTP_CLIENT_HH
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdexcept>
|
||||
|
||||
#include "from_srv.hh"
|
||||
#include "from_heuristics.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -97,6 +98,11 @@ const AccountSettings* get_account_settings(const char* accountName, const char*
|
|||
{
|
||||
get_settings_from_srv(dyn_as, accountName, domain, (provider?provider:"") );
|
||||
}
|
||||
|
||||
if( dyn_as->status != AS_OK && (flags & AS_FLAG_USE_HEURISTICS) )
|
||||
{
|
||||
get_settings_from_heuristics(dyn_as, accountName, domain, provider );
|
||||
}
|
||||
|
||||
return dyn_as;
|
||||
}
|
||||
|
@ -108,12 +114,6 @@ AS_STATUS AS_get_status(const struct AccountSettings* account_settings)
|
|||
}
|
||||
|
||||
|
||||
const char* AS_get_provider_id(const struct AccountSettings* account_settings)
|
||||
{
|
||||
return account_settings ? account_settings->id.c_str() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
const AS_Server* AS_get_incoming(const AccountSettings* as)
|
||||
{
|
||||
return &as->incoming;
|
||||
|
|
3535
src/isp_db.cc
3535
src/isp_db.cc
File diff suppressed because it is too large
Load Diff
568
src/tinyxml2.cc
568
src/tinyxml2.cc
File diff suppressed because it is too large
Load Diff
337
src/tinyxml2.hh
337
src/tinyxml2.hh
|
@ -47,15 +47,15 @@ distribution.
|
|||
*/
|
||||
/*
|
||||
gcc:
|
||||
g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
|
||||
g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
|
||||
|
||||
Formatting, Artistic Style:
|
||||
AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
|
||||
*/
|
||||
|
||||
#if defined( _DEBUG ) || defined (__DEBUG__)
|
||||
# ifndef TINYXML2_DEBUG
|
||||
# define TINYXML2_DEBUG
|
||||
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
||||
# ifndef DEBUG
|
||||
# define DEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -79,7 +79,7 @@ distribution.
|
|||
#endif
|
||||
|
||||
|
||||
#if defined(TINYXML2_DEBUG)
|
||||
#if defined(DEBUG)
|
||||
# if defined(_MSC_VER)
|
||||
# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
|
||||
# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
|
||||
|
@ -98,20 +98,9 @@ distribution.
|
|||
/* Versioning, past 1.0.14:
|
||||
http://semver.org/
|
||||
*/
|
||||
static const int TIXML2_MAJOR_VERSION = 7;
|
||||
static const int TIXML2_MINOR_VERSION = 1;
|
||||
static const int TIXML2_PATCH_VERSION = 0;
|
||||
|
||||
#define TINYXML2_MAJOR_VERSION 7
|
||||
#define TINYXML2_MINOR_VERSION 1
|
||||
#define TINYXML2_PATCH_VERSION 0
|
||||
|
||||
// A fixed element depth limit is problematic. There needs to be a
|
||||
// limit to avoid a stack overflow. However, that limit varies per
|
||||
// system, and the capacity of the stack. On the other hand, it's a trivial
|
||||
// attack that can result from ill, malicious, or even correctly formed XML,
|
||||
// so there needs to be a limit in place.
|
||||
static const int TINYXML2_MAX_ELEMENT_DEPTH = 100;
|
||||
static const int TIXML2_MAJOR_VERSION = 4;
|
||||
static const int TIXML2_MINOR_VERSION = 0;
|
||||
static const int TIXML2_PATCH_VERSION = 1;
|
||||
|
||||
namespace tinyxml2
|
||||
{
|
||||
|
@ -129,10 +118,8 @@ class XMLPrinter;
|
|||
pointers into the XML file itself, and will apply normalization
|
||||
and entity translation if actually read. Can also store (and memory
|
||||
manage) a traditional char[]
|
||||
|
||||
Isn't clear why TINYXML2_LIB is needed; but seems to fix #719
|
||||
*/
|
||||
class TINYXML2_LIB StrPair
|
||||
class StrPair
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
|
@ -192,7 +179,7 @@ private:
|
|||
char* _end;
|
||||
|
||||
StrPair( const StrPair& other ); // not supported
|
||||
void operator=( const StrPair& other ); // not supported, use TransferTo()
|
||||
void operator=( StrPair& other ); // not supported, use TransferTo()
|
||||
};
|
||||
|
||||
|
||||
|
@ -205,11 +192,10 @@ template <class T, int INITIAL_SIZE>
|
|||
class DynArray
|
||||
{
|
||||
public:
|
||||
DynArray() :
|
||||
_mem( _pool ),
|
||||
_allocated( INITIAL_SIZE ),
|
||||
_size( 0 )
|
||||
{
|
||||
DynArray() {
|
||||
_mem = _pool;
|
||||
_allocated = INITIAL_SIZE;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
~DynArray() {
|
||||
|
@ -278,19 +264,12 @@ public:
|
|||
return _allocated;
|
||||
}
|
||||
|
||||
void SwapRemove(int i) {
|
||||
TIXMLASSERT(i >= 0 && i < _size);
|
||||
TIXMLASSERT(_size > 0);
|
||||
_mem[i] = _mem[_size - 1];
|
||||
--_size;
|
||||
}
|
||||
|
||||
const T* Mem() const {
|
||||
TIXMLASSERT( _mem );
|
||||
return _mem;
|
||||
}
|
||||
|
||||
T* Mem() {
|
||||
T* Mem() {
|
||||
TIXMLASSERT( _mem );
|
||||
return _mem;
|
||||
}
|
||||
|
@ -303,9 +282,8 @@ private:
|
|||
TIXMLASSERT( cap > 0 );
|
||||
if ( cap > _allocated ) {
|
||||
TIXMLASSERT( cap <= INT_MAX / 2 );
|
||||
const int newAllocated = cap * 2;
|
||||
int newAllocated = cap * 2;
|
||||
T* newMem = new T[newAllocated];
|
||||
TIXMLASSERT( newAllocated >= _size );
|
||||
memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
|
||||
if ( _mem != _pool ) {
|
||||
delete [] _mem;
|
||||
|
@ -336,6 +314,7 @@ public:
|
|||
virtual void* Alloc() = 0;
|
||||
virtual void Free( void* ) = 0;
|
||||
virtual void SetTracked() = 0;
|
||||
virtual void Clear() = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -346,16 +325,16 @@ template< int ITEM_SIZE >
|
|||
class MemPoolT : public MemPool
|
||||
{
|
||||
public:
|
||||
MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
|
||||
MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
|
||||
~MemPoolT() {
|
||||
MemPoolT< ITEM_SIZE >::Clear();
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void Clear() {
|
||||
// Delete the blocks.
|
||||
while( !_blockPtrs.Empty()) {
|
||||
Block* lastBlock = _blockPtrs.Pop();
|
||||
delete lastBlock;
|
||||
Block* b = _blockPtrs.Pop();
|
||||
delete b;
|
||||
}
|
||||
_root = 0;
|
||||
_currentAllocs = 0;
|
||||
|
@ -396,14 +375,14 @@ public:
|
|||
++_nUntracked;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
virtual void Free( void* mem ) {
|
||||
if ( !mem ) {
|
||||
return;
|
||||
}
|
||||
--_currentAllocs;
|
||||
Item* item = static_cast<Item*>( mem );
|
||||
#ifdef TINYXML2_DEBUG
|
||||
#ifdef DEBUG
|
||||
memset( item, 0xfe, sizeof( *item ) );
|
||||
#endif
|
||||
item->next = _root;
|
||||
|
@ -526,8 +505,10 @@ enum XMLError {
|
|||
XML_ERROR_FILE_NOT_FOUND,
|
||||
XML_ERROR_FILE_COULD_NOT_BE_OPENED,
|
||||
XML_ERROR_FILE_READ_ERROR,
|
||||
XML_ERROR_ELEMENT_MISMATCH,
|
||||
XML_ERROR_PARSING_ELEMENT,
|
||||
XML_ERROR_PARSING_ATTRIBUTE,
|
||||
XML_ERROR_IDENTIFYING_TAG,
|
||||
XML_ERROR_PARSING_TEXT,
|
||||
XML_ERROR_PARSING_CDATA,
|
||||
XML_ERROR_PARSING_COMMENT,
|
||||
|
@ -538,7 +519,6 @@ enum XMLError {
|
|||
XML_ERROR_PARSING,
|
||||
XML_CAN_NOT_CONVERT_TEXT,
|
||||
XML_NO_TEXT_NODE,
|
||||
XML_ELEMENT_DEPTH_EXCEEDED,
|
||||
|
||||
XML_ERROR_COUNT
|
||||
};
|
||||
|
@ -571,7 +551,7 @@ public:
|
|||
static bool IsWhiteSpace( char p ) {
|
||||
return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
|
||||
}
|
||||
|
||||
|
||||
inline static bool IsNameStartChar( unsigned char ch ) {
|
||||
if ( ch >= 128 ) {
|
||||
// This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
|
||||
|
@ -582,7 +562,7 @@ public:
|
|||
}
|
||||
return ch == ':' || ch == '_';
|
||||
}
|
||||
|
||||
|
||||
inline static bool IsNameChar( unsigned char ch ) {
|
||||
return IsNameStartChar( ch )
|
||||
|| isdigit( ch )
|
||||
|
@ -599,7 +579,7 @@ public:
|
|||
TIXMLASSERT( nChar >= 0 );
|
||||
return strncmp( p, q, nChar ) == 0;
|
||||
}
|
||||
|
||||
|
||||
inline static bool IsUTF8Continuation( char p ) {
|
||||
return ( p & 0x80 ) != 0;
|
||||
}
|
||||
|
@ -617,7 +597,6 @@ public:
|
|||
static void ToStr( float v, char* buffer, int bufferSize );
|
||||
static void ToStr( double v, char* buffer, int bufferSize );
|
||||
static void ToStr(int64_t v, char* buffer, int bufferSize);
|
||||
static void ToStr(uint64_t v, char* buffer, int bufferSize);
|
||||
|
||||
// converts strings to primitive types
|
||||
static bool ToInt( const char* str, int* value );
|
||||
|
@ -626,7 +605,7 @@ public:
|
|||
static bool ToFloat( const char* str, float* value );
|
||||
static bool ToDouble( const char* str, double* value );
|
||||
static bool ToInt64(const char* str, int64_t* value);
|
||||
static bool ToUnsigned64(const char* str, uint64_t* value);
|
||||
|
||||
// Changes what is serialized for a boolean value.
|
||||
// Default to "true" and "false". Shouldn't be changed
|
||||
// unless you have a special testing or compatibility need.
|
||||
|
@ -878,21 +857,6 @@ public:
|
|||
*/
|
||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
|
||||
|
||||
/**
|
||||
Make a copy of this node and all its children.
|
||||
|
||||
If the 'target' is null, then the nodes will
|
||||
be allocated in the current document. If 'target'
|
||||
is specified, the memory will be allocated is the
|
||||
specified XMLDocument.
|
||||
|
||||
NOTE: This is probably not the correct tool to
|
||||
copy a document, since XMLDocuments can have multiple
|
||||
top level XMLNodes. You probably want to use
|
||||
XMLDocument::DeepCopy()
|
||||
*/
|
||||
XMLNode* DeepClone( XMLDocument* target ) const;
|
||||
|
||||
/**
|
||||
Test if 2 nodes are the same, but don't test children.
|
||||
The 2 nodes do not need to be in the same Document.
|
||||
|
@ -925,8 +889,8 @@ public:
|
|||
*/
|
||||
virtual bool Accept( XMLVisitor* visitor ) const = 0;
|
||||
|
||||
/**
|
||||
Set user data into the XMLNode. TinyXML-2 in
|
||||
/**
|
||||
Set user data into the XMLNode. TinyXML-2 in
|
||||
no way processes or interprets user data.
|
||||
It is initially 0.
|
||||
*/
|
||||
|
@ -940,10 +904,10 @@ public:
|
|||
void* GetUserData() const { return _userData; }
|
||||
|
||||
protected:
|
||||
explicit XMLNode( XMLDocument* );
|
||||
XMLNode( XMLDocument* );
|
||||
virtual ~XMLNode();
|
||||
|
||||
virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
|
||||
virtual char* ParseDeep( char*, StrPair*, int* );
|
||||
|
||||
XMLDocument* _document;
|
||||
XMLNode* _parent;
|
||||
|
@ -1008,10 +972,10 @@ public:
|
|||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||
|
||||
protected:
|
||||
explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
|
||||
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
|
||||
virtual ~XMLText() {}
|
||||
|
||||
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
||||
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
|
||||
|
||||
private:
|
||||
bool _isCData;
|
||||
|
@ -1039,10 +1003,10 @@ public:
|
|||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||
|
||||
protected:
|
||||
explicit XMLComment( XMLDocument* doc );
|
||||
XMLComment( XMLDocument* doc );
|
||||
virtual ~XMLComment();
|
||||
|
||||
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
|
||||
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr);
|
||||
|
||||
private:
|
||||
XMLComment( const XMLComment& ); // not supported
|
||||
|
@ -1078,10 +1042,10 @@ public:
|
|||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||
|
||||
protected:
|
||||
explicit XMLDeclaration( XMLDocument* doc );
|
||||
XMLDeclaration( XMLDocument* doc );
|
||||
virtual ~XMLDeclaration();
|
||||
|
||||
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
||||
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
|
||||
|
||||
private:
|
||||
XMLDeclaration( const XMLDeclaration& ); // not supported
|
||||
|
@ -1113,10 +1077,10 @@ public:
|
|||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||
|
||||
protected:
|
||||
explicit XMLUnknown( XMLDocument* doc );
|
||||
XMLUnknown( XMLDocument* doc );
|
||||
virtual ~XMLUnknown();
|
||||
|
||||
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
||||
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
|
||||
|
||||
private:
|
||||
XMLUnknown( const XMLUnknown& ); // not supported
|
||||
|
@ -1165,12 +1129,6 @@ public:
|
|||
return i;
|
||||
}
|
||||
|
||||
uint64_t Unsigned64Value() const {
|
||||
uint64_t i = 0;
|
||||
QueryUnsigned64Value(&i);
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Query as an unsigned integer. See IntValue()
|
||||
unsigned UnsignedValue() const {
|
||||
unsigned i=0;
|
||||
|
@ -1205,8 +1163,6 @@ public:
|
|||
XMLError QueryUnsignedValue( unsigned int* value ) const;
|
||||
/// See QueryIntValue
|
||||
XMLError QueryInt64Value(int64_t* value) const;
|
||||
/// See QueryIntValue
|
||||
XMLError QueryUnsigned64Value(uint64_t* value) const;
|
||||
/// See QueryIntValue
|
||||
XMLError QueryBoolValue( bool* value ) const;
|
||||
/// See QueryIntValue
|
||||
|
@ -1222,9 +1178,7 @@ public:
|
|||
void SetAttribute( unsigned value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute(int64_t value);
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute(uint64_t value);
|
||||
/// Set the attribute to value.
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( bool value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( double value );
|
||||
|
@ -1234,7 +1188,7 @@ public:
|
|||
private:
|
||||
enum { BUF_SIZE = 200 };
|
||||
|
||||
XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
|
||||
XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
|
||||
virtual ~XMLAttribute() {}
|
||||
|
||||
XMLAttribute( const XMLAttribute& ); // not supported
|
||||
|
@ -1312,8 +1266,6 @@ public:
|
|||
unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
|
||||
/// See IntAttribute()
|
||||
int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
|
||||
/// See IntAttribute()
|
||||
uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const;
|
||||
/// See IntAttribute()
|
||||
bool BoolAttribute(const char* name, bool defaultValue = false) const;
|
||||
/// See IntAttribute()
|
||||
|
@ -1360,15 +1312,6 @@ public:
|
|||
return a->QueryInt64Value(value);
|
||||
}
|
||||
|
||||
/// See QueryIntAttribute()
|
||||
XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {
|
||||
const XMLAttribute* a = FindAttribute(name);
|
||||
if(!a) {
|
||||
return XML_NO_ATTRIBUTE;
|
||||
}
|
||||
return a->QueryUnsigned64Value(value);
|
||||
}
|
||||
|
||||
/// See QueryIntAttribute()
|
||||
XMLError QueryBoolAttribute( const char* name, bool* value ) const {
|
||||
const XMLAttribute* a = FindAttribute( name );
|
||||
|
@ -1394,25 +1337,14 @@ public:
|
|||
return a->QueryFloatValue( value );
|
||||
}
|
||||
|
||||
/// See QueryIntAttribute()
|
||||
XMLError QueryStringAttribute(const char* name, const char** value) const {
|
||||
const XMLAttribute* a = FindAttribute(name);
|
||||
if (!a) {
|
||||
return XML_NO_ATTRIBUTE;
|
||||
}
|
||||
*value = a->Value();
|
||||
return XML_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Given an attribute name, QueryAttribute() returns
|
||||
XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
|
||||
can't be performed, or XML_NO_ATTRIBUTE if the attribute
|
||||
doesn't exist. It is overloaded for the primitive types,
|
||||
and is a generally more convenient replacement of
|
||||
QueryIntAttribute() and related functions.
|
||||
|
||||
|
||||