Compare commits

...

69 Commits

Author SHA1 Message Date
Andreas Buff b9c4bfc54d rm header build phase, increase min iOS version 2022-02-28 15:19:03 +01:00
Andreas Buff c63b71ce79 Merge branch 'IOS-2913' 2021-12-04 12:14:17 +01:00
Andreas Buff bcdda9f55a IOS-2913 fixes: iOS bridging header cant find account settings headers 2021-12-04 11:19:48 +01:00
roker 7e8a7dd836 re-activate all the Posteo domains which were removed for unknown reasons. 2021-04-08 18:18:02 +02:00
roker 67461fdb03 LAS-28 "add support for mailfence.com" 2021-03-31 09:44:11 +02:00
Andreas Buff c51a99d185 IOS-2748 - adds test to reproduce LAS-32 2021-03-30 16:37:26 +02:00
Andreas Buff 8145cd6220 replaces .hgignore with .gitignore and add Xcode and macOS related ignores 2021-03-30 13:19:11 +02:00
roker 652239d964 LAS-31 "add AccountSettings for @pep.digital" 2021-03-02 10:40:54 +01:00
roker e75d9130e6 LAS-30: re-built ISP DB to add "e foundation". 2021-02-24 16:11:14 +01:00
roker 205d60e292 LAS-30: add config for "e foundation" 2021-02-24 16:08:49 +01:00
Roker 291bf2bf70 merge double head, caused by parallel merges done intentionally by Dirk and me. :-) 2020-10-20 16:13:44 +02:00
Roker 603e6a463d new ISP DB: 935 instead of 879 entries. 2020-10-20 16:12:58 +02:00
Roker 28299af7c8 give AS_PROTO_EXCHANGE a lower precedence, so it is only selected if neither IMAP, POP nor SMTP is supported. 2020-10-20 16:09:46 +02:00
Dirk Zimmermann 069d7ecb59 Added tag tag_for_1.1.300 for changeset c9af356f901d 2020-10-20 16:07:12 +02:00
Dirk Zimmermann a2a4f2e8e6 merge IOS-2259 2020-10-20 16:05:08 +02:00
Roker 0c6b2b257c add support for protocol "exchange" 2020-10-20 15:56:21 +02:00
Roker b652c2fabd add support for TLS. UNFINISHED! 2020-10-20 15:34:43 +02:00
Dirk Zimmermann 5523e22f12 close branch 2020-10-19 09:32:08 +02:00
Dirk Zimmermann eb46711fab IOS-2259 Adapt yahoo query to (current) reality 2020-10-01 13:41:58 +02:00
Roker 7793794fa5 LAS-27: change mail servers for pEp.security into mail.pep.security, change SMTP from STARTTLS to SSL. 2020-02-27 12:12:23 +01:00
Roker 11ece8e115 LAS-22 & LAS-23: add test for autoconfig fetch via HTTP for peptest.ch domain 2019-10-17 15:14:26 +02:00
Roker 69b80d5c4d add simple HTTP client in http_get_file() function (necessary for LAS-22 and LAS-23) 2019-10-17 12:20:10 +02:00
Roker 4b787c2d91 LAS-26 add server config for exchange.peptest.ch 2019-10-07 17:38:22 +02:00
Roker 5e8204d10e update tinyxml2 from version 4.0.1 to 7.1.0. –> no interface changes. :-) 2019-09-23 11:05:11 +02:00
Roker d58871da43 wrap overlong lines. 2019-09-23 11:03:29 +02:00
Roker 6a7d389c01 LAS-25: add o365.peptest.ch 2019-09-09 10:47:28 +02:00
Roker bd1adcead4 change method flags: remove AS_FLAG_USE_HEURISTICS, add AS_FLAG_USE_GUESSING as dangerous online guessing, trial&error method; fix name for AUTOCONFIG method: it is not DNS-related! 2019-08-28 16:10:46 +02:00
Roker 6eb1dd65dc LAS-24 – re-run ISP table generation 2019-06-27 15:23:13 +02:00
Roker d1a339817d LAS-24 - fix syntax 2019-06-27 15:21:51 +02:00
Roker 4fcc43f620 LAS-24 "Add M-Net customer domains for Auto-Setup" - add provider config file 2019-06-27 15:20:02 +02:00
buff 990738bd6d less warnings 2019-06-20 18:08:41 +02:00
buff 36d9467f6a Xcode: update to recommended settings 2019-06-19 23:11:00 +02:00
buff 36fe4372bd silences warnings for documentation comments 2019-06-19 23:04:01 +02:00
Dirk Zimmermann da8b67d939 IOS-1480 IPHONEOS_DEPLOYMENT_TARGET = 10.0 2019-03-14 09:34:36 +01:00
Dirk Zimmermann 0014edb61c IOS-1226 xcode update project 2018-08-08 10:44:28 +02:00
Roker 88d94c7ce4 okay 2nd try: first probe for "_imaps", than for "_imap" 2018-07-25 12:28:56 +02:00
Roker 8ebaad87e5 (no JIRA ticket) – use DNS SRV label "_imaps._tcp", too, as specified in RFC 6186. 2018-07-25 10:01:47 +02:00
Roker bf58884058 LAS-20 + LAS-21: ISP DB recompiled with new entries. 2018-05-28 11:04:34 +02:00
Roker 3a4e3776f3 add ../examples/* to list of XML files for ISP DB generation 2018-05-28 11:03:28 +02:00
Roker 659dbb5600 LAS-21: add pep.security to examples 2018-05-28 10:56:52 +02:00
Roker dd15362ca4 LAS-20: add pep-security.net to examples 2018-05-28 10:53:34 +02:00
Dirk Zimmermann dcc049c624 build for arm64 armv7s armv7 2018-05-24 15:21:56 +02:00
Dirk Zimmermann 3facba78d8 build for arm64 armv7s armv7 2018-05-24 10:05:00 +02:00
Dirk Zimmermann 5497b9fd47 arm64 only 2018-05-18 12:00:59 +02:00
buff 72a053a455 for test target also, changes Apple Development Team to SA (was AG) 2018-05-15 15:41:58 +02:00
buff 5f1296aac4 changes Apple Development Team to SA (was AG) 2018-05-15 15:21:24 +02:00
Roker bb641d072e #fix LAS-19: we accidentally returned a far too long hostname 2018-02-07 13:00:41 +01:00
Roker ba485c7052 let's xml2cxx compile again! sorry, folks. 2018-02-06 15:29:23 +01:00
Roker fee8a42469 LAS-17: move internal names AS_Server_DB and AccountSettings_DB into namespace "account_settings". 2018-02-06 13:29:18 +01:00
Roker 9e3e4ebc52 LAS-18: set as->status to AS_OK when SRC query was successful. 2018-02-06 13:05:16 +01:00
Dirk Zimmermann e69982522a IOS-914 constants for provider ID yahoo/gmail 2018-01-31 11:15:25 +01:00
Dirk Zimmermann 5b159af529 IOS-914 test for gmail 2018-01-31 11:07:29 +01:00
Dirk Zimmermann 46e3af89f1 IOS-914 export providerID to ObjC clients 2018-01-31 11:04:14 +01:00
Roker f1fa27e1d8 merge double head 2018-01-31 09:04:53 +01:00
Roker 6f8eb6436f LAS-16: add API function AS_get_provider_id(). 2018-01-31 09:04:37 +01:00
Dirk Zimmermann eb7512f9cf IOS-914 yahoo -> oauth2 -> correct tests 2018-01-30 17:13:20 +01:00
Roker 898336eca2 merge double head 2018-01-30 17:07:06 +01:00
Roker 141baa40aa add tests for AS_ACCESS and for yahoo.com 2018-01-30 17:06:39 +01:00
Roker 06e7d8297f fix ISP DB - remove ymail.com and rocketmail.com which contains outdated aliases for yahoo.com 2018-01-30 17:06:15 +01:00
Dirk Zimmermann 953e73e3f2 IOS-914 AccountSettingsProtocol.supportsOAuth2 2018-01-30 17:05:03 +01:00
Dirk Zimmermann 6a8dda19c7 IOS-914 rm empty code 2018-01-30 16:09:38 +01:00
Dirk Zimmermann 45cb8a717d IOS-914 testing several flags, including AS_FLAG_USE_ANY_LOCAL 2018-01-30 16:07:57 +01:00
Dirk Zimmermann 22871a52d7 IOS-914 AccountSettings.supportsOAuth2 2018-01-30 16:07:56 +01:00
Roker 0f4f1b6ef5 oops: (AS_FLAG_USE_DNS_SRV & AS_FLAG_USE_ANY_LOCAL) must be evaluate to 0. Thanks, Dirk! 2018-01-29 17:40:10 +01:00
Roker 5478cd6b8a change Yahoo to use OAuth2, as requested in LAS-8 by Dirk. 2018-01-29 11:52:55 +01:00
Roker 240a955332 add many domains for posteo 2018-01-15 09:15:31 +01:00
Roker b4b7facf30 merge double head 2018-01-15 08:55:32 +01:00
Roker 49425bb6f4 LAS-15: add posteo.net and icloud.com to ISP DB 2018-01-15 08:55:10 +01:00
Dirk Zimmermann bb1ba802d8 LAS-14 has been fixed 2017-12-12 16:03:00 +01:00
29 changed files with 3355 additions and 1909 deletions

70
.gitignore vendored Normal file
View File

@ -0,0 +1,70 @@
# 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

View File

@ -1,6 +0,0 @@
regexp
\.DS_Store
xcuserdata/.*
\.orig$
\.git/
\.gitkeep

23
example/e.foundation Normal file
View File

@ -0,0 +1,23 @@
<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>

61
example/m-net Normal file
View File

@ -0,0 +1,61 @@
<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>

22
example/mailfence Normal file
View File

@ -0,0 +1,22 @@
<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>

21
example/pep-security.net Normal file
View File

@ -0,0 +1,21 @@
<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>

21
example/pep.digital Normal file
View File

@ -0,0 +1,21 @@
<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>

21
example/pep.security Normal file
View File

@ -0,0 +1,21 @@
<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>

View File

@ -52,6 +52,15 @@ 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.

View File

@ -31,12 +31,19 @@ typedef enum _AS_STATUS
typedef enum _AS_FLAGS
{
AS_FLAG_USE_LOCAL_ISP_DB = 0x0010, ///< use local ISP database
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
// 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_FLAGS;
@ -44,6 +51,7 @@ typedef enum _AS_FLAGS
typedef enum _AS_ACCESS
{
/// 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

View File

@ -10,18 +10,18 @@ test: accountSettings_test
isp_db: isp_db.cc
isp_db.cc: xml2cxx
./xml2cxx ../../autoconfig/* > $@
./xml2cxx ../../autoconfig/* ../example/* > $@
xml2cxx: xml2cxx.o tinyxml2.o account_settings_internal.o stringpool.o
${CXX} -o $@ $^
accountSettings_test: accountSettings_test.o libAccountSettings.a
${CXX} -o $@ $^ -lldns
${CXX} -o $@ $^ -lldns -lcrypto -lssl
libAccountSettings.a: account_settings_internal.o implementation.o \
isp_db.o \
isp_db.o http_client.o \
from_srv.o
ar rcs $@ $^
${AR} rcs $@ $^
%.o : %.cc %.hh
${CXX} -o $@ -c $<

View File

@ -1,7 +1,9 @@
// 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>
@ -19,25 +21,26 @@ 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} },
{ "example@gmx.de" , {"imap.gmx.net", 993} },
{ "example@yandex.ua", {"imap.yandex.com", 993} },
{ "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} },
};
// stored in ISP DB
const std::vector< KeyValue< TestHost> > outgoingServer =
{
{ "lib_as@peptest.ch", {"peptest.ch", 587} },
{ "example@gmx.de" , {"mail.gmx.net", 465} },
{ "example@yandex.ua", {"smtp.yandex.com", 465} },
{ "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} },
};
//
template<class TestData, class Function >
bool testServers( const TestData& testData, Function testFunc )
@ -66,6 +69,14 @@ 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);
}
@ -82,22 +93,49 @@ 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)
{
printf("#%d : ", a);
std::cout << a << ": " << std::endl;
auto as = std::unique_ptr<AccountSettings>{ new AccountSettings };
get_settings_from_srv( as.get(), "foo@bar.com", argv[a], "dummy");
printf("\n");
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;
}
}
}
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;

View File

@ -9,6 +9,7 @@
#include <set>
#include <ostream>
// public names, must be accessible from C, so no namespace here:
struct AS_Server
{
std::string name;
@ -30,6 +31,7 @@ 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
{
@ -47,4 +49,6 @@ struct AccountSettings_DB
AS_Server_DB outgoing;
};
} // end of namespace account_settings
#endif // ACCOUNT_SETTINGS_INTERNAL_HH

View File

@ -131,10 +131,15 @@ 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);
const std::string host = ldns_rdf_get_type(rdf_host)==LDNS_RDF_TYPE_DNAME ? std::string( (const char*)buf_host->_data, buf_host->_limit) : "{°?°}";
std::string host = ldns_rdf_get_type(rdf_host)==LDNS_RDF_TYPE_DNAME ? std::string( (const char*)buf_host->_data, buf_host->_position) : "{°?°}";
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 };
@ -149,14 +154,35 @@ 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& )
{
@ -170,11 +196,18 @@ 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;
}

102
src/http_client.cc Normal file
View File

@ -0,0 +1,102 @@
#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

39
src/http_client.hh Normal file
View File

@ -0,0 +1,39 @@
#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

View File

@ -108,6 +108,12 @@ 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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -47,15 +47,15 @@ distribution.
*/
/*
gcc:
g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
g++ -Wall -DTINYXML2_DEBUG 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 ) || defined (__DEBUG__)
# ifndef DEBUG
# define DEBUG
#if defined( _DEBUG ) || defined (__DEBUG__)
# ifndef TINYXML2_DEBUG
# define TINYXML2_DEBUG
# endif
#endif
@ -79,7 +79,7 @@ distribution.
#endif
#if defined(DEBUG)
#if defined(TINYXML2_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,9 +98,20 @@ distribution.
/* Versioning, past 1.0.14:
http://semver.org/
*/
static const int TIXML2_MAJOR_VERSION = 4;
static const int TIXML2_MINOR_VERSION = 0;
static const int TIXML2_PATCH_VERSION = 1;
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;
namespace tinyxml2
{
@ -118,8 +129,10 @@ 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 StrPair
class TINYXML2_LIB StrPair
{
public:
enum {
@ -179,7 +192,7 @@ private:
char* _end;
StrPair( const StrPair& other ); // not supported
void operator=( StrPair& other ); // not supported, use TransferTo()
void operator=( const StrPair& other ); // not supported, use TransferTo()
};
@ -192,10 +205,11 @@ 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() {
@ -264,12 +278,19 @@ 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;
}
@ -282,8 +303,9 @@ private:
TIXMLASSERT( cap > 0 );
if ( cap > _allocated ) {
TIXMLASSERT( cap <= INT_MAX / 2 );
int newAllocated = cap * 2;
const 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;
@ -314,7 +336,6 @@ public:
virtual void* Alloc() = 0;
virtual void Free( void* ) = 0;
virtual void SetTracked() = 0;
virtual void Clear() = 0;
};
@ -325,16 +346,16 @@ template< int ITEM_SIZE >
class MemPoolT : public MemPool
{
public:
MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
~MemPoolT() {
Clear();
MemPoolT< ITEM_SIZE >::Clear();
}
void Clear() {
// Delete the blocks.
while( !_blockPtrs.Empty()) {
Block* b = _blockPtrs.Pop();
delete b;
Block* lastBlock = _blockPtrs.Pop();
delete lastBlock;
}
_root = 0;
_currentAllocs = 0;
@ -375,14 +396,14 @@ public:
++_nUntracked;
return result;
}
virtual void Free( void* mem ) {
if ( !mem ) {
return;
}
--_currentAllocs;
Item* item = static_cast<Item*>( mem );
#ifdef DEBUG
#ifdef TINYXML2_DEBUG
memset( item, 0xfe, sizeof( *item ) );
#endif
item->next = _root;
@ -505,10 +526,8 @@ 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,
@ -519,6 +538,7 @@ enum XMLError {
XML_ERROR_PARSING,
XML_CAN_NOT_CONVERT_TEXT,
XML_NO_TEXT_NODE,
XML_ELEMENT_DEPTH_EXCEEDED,
XML_ERROR_COUNT
};
@ -551,7 +571,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()
@ -562,7 +582,7 @@ public:
}
return ch == ':' || ch == '_';
}
inline static bool IsNameChar( unsigned char ch ) {
return IsNameStartChar( ch )
|| isdigit( ch )
@ -579,7 +599,7 @@ public:
TIXMLASSERT( nChar >= 0 );
return strncmp( p, q, nChar ) == 0;
}
inline static bool IsUTF8Continuation( char p ) {
return ( p & 0x80 ) != 0;
}
@ -597,6 +617,7 @@ 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 );
@ -605,7 +626,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.
@ -857,6 +878,21 @@ 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.
@ -889,8 +925,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.
*/
@ -904,10 +940,10 @@ public:
void* GetUserData() const { return _userData; }
protected:
XMLNode( XMLDocument* );
explicit XMLNode( XMLDocument* );
virtual ~XMLNode();
virtual char* ParseDeep( char*, StrPair*, int* );
virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
XMLDocument* _document;
XMLNode* _parent;
@ -972,10 +1008,10 @@ public:
virtual bool ShallowEqual( const XMLNode* compare ) const;
protected:
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
virtual ~XMLText() {}
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
private:
bool _isCData;
@ -1003,10 +1039,10 @@ public:
virtual bool ShallowEqual( const XMLNode* compare ) const;
protected:
XMLComment( XMLDocument* doc );
explicit XMLComment( XMLDocument* doc );
virtual ~XMLComment();
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr);
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
private:
XMLComment( const XMLComment& ); // not supported
@ -1042,10 +1078,10 @@ public:
virtual bool ShallowEqual( const XMLNode* compare ) const;
protected:
XMLDeclaration( XMLDocument* doc );
explicit XMLDeclaration( XMLDocument* doc );
virtual ~XMLDeclaration();
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
private:
XMLDeclaration( const XMLDeclaration& ); // not supported
@ -1077,10 +1113,10 @@ public:
virtual bool ShallowEqual( const XMLNode* compare ) const;
protected:
XMLUnknown( XMLDocument* doc );
explicit XMLUnknown( XMLDocument* doc );
virtual ~XMLUnknown();
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
private:
XMLUnknown( const XMLUnknown& ); // not supported
@ -1129,6 +1165,12 @@ 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;
@ -1163,6 +1205,8 @@ 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
@ -1178,7 +1222,9 @@ public:
void SetAttribute( unsigned value );
/// Set the attribute to value.
void SetAttribute(int64_t value);
/// Set the attribute to value.
/// Set the attribute to value.
void SetAttribute(uint64_t value);
/// Set the attribute to value.
void SetAttribute( bool value );
/// Set the attribute to value.
void SetAttribute( double value );
@ -1188,7 +1234,7 @@ public:
private:
enum { BUF_SIZE = 200 };
XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
virtual ~XMLAttribute() {}
XMLAttribute( const XMLAttribute& ); // not supported
@ -1266,6 +1312,8 @@ 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()
@ -1312,6 +1360,15 @@ 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 );
@ -1337,14 +1394,25 @@ 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.
If successful, the result of the conversion
will be written to 'value'. If not successful, nothing will
be written to 'value'. This allows you to provide default
@ -1355,27 +1423,31 @@ public:
QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
@endverbatim
*/
int QueryAttribute( const char* name, int* value ) const {
XMLError QueryAttribute( const char* name, int* value ) const {
return QueryIntAttribute( name, value );
}
int QueryAttribute( const char* name, unsigned int* value ) const {
XMLError QueryAttribute( const char* name, unsigned int* value ) const {
return QueryUnsignedAttribute( name, value );
}
int QueryAttribute(const char* name, int64_t* value) const {
XMLError QueryAttribute(const char* name, int64_t* value) const {
return QueryInt64Attribute(name, value);
}
int QueryAttribute( const char* name, bool* value ) const {
XMLError QueryAttribute(const char* name, uint64_t* value) const {
return QueryUnsigned64Attribute(name, value);
}
XMLError QueryAttribute( const char* name, bool* value ) const {
return QueryBoolAttribute( name, value );
}
int QueryAttribute( const char* name, double* value ) const {
XMLError QueryAttribute( const char* name, double* value ) const {
return QueryDoubleAttribute( name, value );
}
int QueryAttribute( const char* name, float* value ) const {
XMLError QueryAttribute( const char* name, float* value ) const {
return QueryFloatAttribute( name, value );
}