Compare commits

..

No commits in common. "807e0c35866ab5cc4ba3b9c7d281d3546f1bbe42" and "6301cbb5956eaffc72122e78a828c86b8e5ed567" have entirely different histories.

14 changed files with 150 additions and 254 deletions

View file

@ -1,29 +1,3 @@
#!/usr/bin/env bash #!/usr/bin/env bash
echo Removing old sample files… cp /var/www/html/sample-config/* /var/www/html/config/
rm /var/www/html/config/*.sample.ini
function write_file() {
while read line;
do
first_char=${line:0:1}
if [[ $first_char != ";" ]]; then
line="; "$line
fi
echo $line >> $2
done < $1
}
echo Setting up new sample config files…
def_conf="/var/www/html/default-config/config.default.ini"
new_conf="/var/www/html/config/config.sample.ini"
write_file $def_conf $new_conf
def_serv="/var/www/html/default-config/services.default.ini"
new_serv="/var/www/html/config/services.sample.ini"
write_file $def_serv $new_serv
echo Running HTTPD…
exec apache2-foreground exec apache2-foreground

11
examples/dashboard.html Normal file
View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>DAVDiscover Dashboard Example</title>
</head>
<body>
<p>This is to show the basic output of DAVDiscover, displaying the first few URLs</p>
</body>
</html>

View file

@ -22,36 +22,30 @@ class Init {
$loader->request_page(); $loader->request_page();
} }
private function get_config(){ private function get_config(){
// parse the default config file for default values // define the config file location
$default_config = parse_ini_file(Core::root_dir()."/default-config/config.default.ini", true); $config = Core::root_dir()."/config/config.ini";
// define the custom config file location
$config_file = Core::root_dir()."/config/config.ini";
$config = array();
if (file_exists($config_file)) {
// if a custom config file exists then parse that file too
$config = parse_ini_file($config_file, true);
}
// merge the default config with the custom config
Core::$Config = array_merge($default_config,$config);
Core::$Config["PrimaryDomain"] = Core::$Config["Domain"][0];
// parse the default services file for default values // if it doesn't exist, use the sample file
$default_services = parse_ini_file(Core::root_dir()."/default-config/services.default.ini", true); // YOU REALLY SHOULD HAVE YOUR OWN CONFIG FILE!!!
// define the custom services file location if (!file_exists($config)) {
$services_file = Core::root_dir()."/config/services.ini"; $config = Core::root_dir()."/sample-config/config.sample.ini";
$services = array();
if (file_exists($services_file)) {
// if a custom config file exists then parse that file too
$services = parse_ini_file($services_file, true);
} }
// merge the default config with the custom config // define services file location
// using replace recursive as the config file contains arrays itself $services = Core::root_dir()."/config/services.ini";
Core::$Config["Services"] = array_replace_recursive($default_services,$services);
// get the current git commit, if it exists. For testing // if it doesn't exist, use the sample file
// YOU REALLY SHOULD HAVE YOUR OWN SERVICES FILE!!!
if (!file_exists($services)) {
$services = Core::root_dir()."/sample-config/services.sample.ini";
}
// Store the config settings in the Core::Config variable
// the "true" means it's going to parse the headers as well.
Core::$Config = parse_ini_file($config, true);
Core::$Config["Services"] = parse_ini_file($services, true);
Core::$Config["CommitID"] = Core::get_current_git_commit(); Core::$Config["CommitID"] = Core::get_current_git_commit();
} }
} }

View file

@ -1,6 +1,6 @@
<?php class Core { <?php class Core {
public static $Config; public static $Config;
public const VERSION = "0.0.6"; public const VERSION = "0.0.2";
public static $CurrentPage; public static $CurrentPage;
public static function root_dir(){ public static function root_dir(){
return $_SERVER['DOCUMENT_ROOT']; return $_SERVER['DOCUMENT_ROOT'];

View file

@ -29,6 +29,10 @@ class Loader {
Core::$CurrentPage = $p; Core::$CurrentPage = $p;
} }
require_once(Core::root_dir()."/public/respond.php"); require_once(Core::root_dir()."/public/respond.php");
// } else {
// Core::$CurrentPage = "Error";
// require_once(Core::RootDir()."/public/error.php");
// }
break; break;
} }
} }

View file

@ -37,7 +37,7 @@ class Responder {
private function get_response(){ private function get_response(){
$resp = false; $resp = false;
// Handle the requested URL, using as many known autoconfiguration urls as possible // Handle the requested URL, using as many known autoconfiguration urls as possible
switch (strtolower(Core::$CurrentPage)){ switch (Core::$CurrentPage){
case "get/test": case "get/test":
$resp = $this->dummy_response(); $resp = $this->dummy_response();
break; break;
@ -49,14 +49,13 @@ class Responder {
$resp = $this->moz_auto_config(); $resp = $this->moz_auto_config();
break; break;
case "autodiscover/autodiscover.xml": case "autodiscover/autodiscover.xml":
case "Autodiscover/Autodiscover.xml":
$resp = $this->ms_autodiscover(); $resp = $this->ms_autodiscover();
break; break;
case "autodiscover/autodiscover.json": case "autodiscover/autodiscover.json":
case "Autodiscover/Autodiscover.json":
$resp = $this->ms_autodiscover_json(); $resp = $this->ms_autodiscover_json();
break; break;
case "get/config":
$resp = $this->get_config();
break;
case "none": case "none":
case "test": case "test":
case "home": case "home":
@ -68,26 +67,6 @@ class Responder {
} }
return $resp; return $resp;
} }
private function get_config(){
$response = new Response();
$response->message = "Here's your config...";
foreach (Core::$Config as $k => $v){
$response->content[$k] = $v;
}
return $response;
}
private function get_username($service,$email_address) {
$username = "%EMAILADDRESS%";
if(!$service["UsernameIsFQDN"]) {
preg_match("/^[^@]+/",$email_address,$matches);
if (count($matches) > 0){
$username = $matches[0];
}
} else if ($service["RequireLogonDomain"]) {
$username = preg_replace("/[^@]+$/",Core::$Config["LogonDomain"],$email_address,1);
}
return $username;
}
private function all_urls(){ private function all_urls(){
$response = new Response(); $response = new Response();
// Not really useful, unless some lovely app developers want to parse it for their app :) // Not really useful, unless some lovely app developers want to parse it for their app :)
@ -96,9 +75,6 @@ class Responder {
// Cycle through each service and add to payload // Cycle through each service and add to payload
foreach (Core::$Config["Services"] as $key => $service){ foreach (Core::$Config["Services"] as $key => $service){
if (!$service["Enabled"]) {
continue;
}
$response->content[$key] = $service; $response->content[$key] = $service;
} }
@ -156,7 +132,7 @@ class Response {
public $url; public $url;
public $content_type = "json"; public $content_type = "json";
public $message; public $message;
// public $headers_set = false; public $headers_set = false;
public $content = array(); public $content = array();
public function __construct(){ public function __construct(){
// add requested page to response. I don't know why, but it could helpful for diagnostics at some point // add requested page to response. I don't know why, but it could helpful for diagnostics at some point

View file

@ -1,116 +0,0 @@
; The Incoming mail Server Config
[InMail]
; Enable this service
Enabled = true
; Mail Type, i.e. IMAP, POP3
Type = "IMAP"
; Your IMAP server
Server = "imap.example.com"
; Your IMAP port
Port = 993
; The socket type : SSL, STARTTLS, or NONE
SocketType = SSL
; Use Secure Password Authentication
SPA = false
; Change to true if you need the domain/logondomain to form part of the username
UsernameIsFQDN = false
; Do you need to authenticate to your mail server? You should! so this should be false!
NoAuthRequired = false
; Authentication type,
;"password-cleartext" : Send password in the clear
; (dangerous, if SSL isn't used either).
; AUTH PLAIN, LOGIN or protocol-native login.
;"password-encrypted" : A secure encrypted password mechanism.
; Can be CRAM-MD5 or DIGEST-MD5. Not NTLM.
;"NTLM": Use NTLM (or NTLMv2 or successors),
; the Windows login mechanism.
Authentication = password-cleartext
; The Outgoing mail server config
[OutMail]
; Enable this service
Enabled = true
; Mail type, likely to only be SMTP
Type = "SMTP"
; Your SMTP server
Server = "smtp.example.com"
; Your SMTP port
Port = 465
; The socket type : SSL, STARTTLS or NONE
SocketType = SSL
; See InMail > Authentication
Authentication = password-cleartext
; Use Secure Password Authentication
SPA = false
; Change to true if you need the domain/logondomain to form part of the username
UsernameIsFQDN = false
; Do you need to authenticate to your mail server? You should! so this should be false!
NoAuthRequired = false
; Use POP Authentication? You probably shouldn't be.
POPAuth = false
; This setting is here to limit errors, I'm not sure what it does yet.
SMTPLast = false
; Currently not implemented, see https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
[Calendar]
; Disable this service
Enabled = false
Server = "https://example.com/remote.php/dav/"
Port = 443
Type = CalDAV
Authentication = http-basic
UsernameIsFQDN = false
; Currently not implemented, see https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
[AddressBook]
; Disable this service
Enabled = false
Server = "https://example.com/remote.php/dav/"
Port = 443
Type = CardDAV
Authentication = http-basic
UsernameIsFQDN = false
; Currently not implemented, see https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
[WebMail]
; Disable this service
Enabled = false
Server = https://mail.example.com
UsernameDivID = "username"
UsernameDivName = "username"
PasswordDivName = "password"
SubmitButtonID = "submit"
SubmitButtonName = "submit"
UsernameIsFQDN = false
; In theory, additional custom services can be configured and will be displayed with
; their options on the /get/all URL of this service. The third-party clients would need to
; check this service as part of their development for this to work
; Will not be shown in autodiscover.xml/json or config-v1.1.xml/autoconfig.xml
; i.e Nextcloud - ideally a nextcloud client could check autoconfig for this URL for ease of set up
;[Nextcloud]
;Server = https://nextcloud.example.com

View file

@ -1,64 +1,91 @@
<?php <?php
// Get some core information to help with generation.
$services = Core::$Config["Services"]; // Errrrrrrrrgh, this is sooooo messy, I'm going to tidy this up
// It's basically configuring the format of the email address dependent on
// variables set in the config file.
// i.e. if the domain isn't required for authentication then it strips the
// username back to just the pre-@ part. Or, if the username requires a different
// logon domain, then it replaces the email domain with the localdomain
//
// TODO: TIDY THIS UP!!
$conf = Core::$Config["Services"];
$data = Core::get_get_data(); $data = Core::get_get_data();
if (isset($data["emailaddress"])) { $email_provided = false;
$display_name = false;
$emailaddress = false;
if ($data["emailaddress"]) {
$email_address = $data["emailaddress"]; $email_address = $data["emailaddress"];
$display_name = $email_address;
$email_provided = true;
} else if ($data["path"]) {
$query = parse_url($data["path"]);
$email_address = explode("=",$query["query"]);
if ($email_address[0] == "emailaddress") {
$email_address = $email[1];
$email_provided = true;
$display_name = $email_address;
} }
}
if ($email_provided) {
if(!Core::$Config["RequireAuthDomain"]) {
$email_address = str_ireplace("@".Core::$Config["Domain"],"",$email_address);
} else if (Core::$Config["LogonDomain"]) {
$email_address = str_ireplace(Core::$Config["Domain"],Core::$Config["LogonDomain"],$email_address);
}
}
// The below link has config-v1.1.xml information // The below link has config-v1.1.xml information
// https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat // https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
?> ?>
<clientConfig version="1.1"> <clientConfig version="1.1">
<emailProvider id="<?php echo Core::$Config["PrimaryDomain"]?>"> <emailProvider id="<?php echo Core::$Config["Domain"]?>">
<?php foreach (Core::$Config["Domain"] as $domain){ ?> <domain><?php echo Core::$Config["Domain"]?></domain>
<domain><?php echo $domain; ?></domain> <displayName><?php echo $email_provided ? $display_name : "%EMAILADDRESS%" ;?></displayName>
<?php } ?> <?php if($conf["InMail"]){
<displayName>%EMAILADDRESS%</displayName> $in = $conf["InMail"]; ?>
<?php if($services["InMail"]&& $services["InMail"]["Enabled"]){ <incomingServer type="<?php echo strtolower($in["Type"]);?>">
$service = $services["InMail"]; ?> <hostname><?php echo $in["Server"];?></hostname>
<incomingServer type="<?php echo strtolower($service["Type"]);?>"> <port><?php echo $in["Port"];?></port>
<hostname><?php echo $service["Server"];?></hostname> <socketType><?php echo $in["SocketType"];?></socketType>
<port><?php echo $service["Port"];?></port> <username><?php echo $email_provided ? $email_address : "%EMAILADDRESS%";?></username>
<socketType><?php echo $service["SocketType"];?></socketType> <authentication><?php echo $in["Authentication"];?></authentication>
<username><?php echo $this->get_username($service,$email_address); ?></username>
<authentication><?php echo $service["Authentication"];?></authentication>
</incomingServer> </incomingServer>
<?php } <?php }
if($services["OutMail"]&& $services["OutMail"]["Enabled"]){ if($conf["OutMail"]){
$service = $services["OutMail"]; ?> $out = $conf["OutMail"]; ?>
<outgoingServer type="<?php echo strtolower($service["Type"]);?>"> <outgoingServer type="<?php echo strtolower($out["Type"]);?>">
<hostname><?php echo $service["Server"];?></hostname> <hostname><?php echo $out["Server"];?></hostname>
<port><?php echo $service["Port"];?></port> <port><?php echo $out["Port"];?></port>
<socketType><?php echo $service["SocketType"];?></socketType> <socketType><?php echo $out["SocketType"];?></socketType>
<username><?php echo $this->get_username($service,$email_address);?></username> <username><?php echo $email_provided ? $email_address : "%EMAILADDRESS%";?></username>
<authentication><?php echo $service["Authentication"];?></authentication> <authentication><?php echo $out["Authentication"];?></authentication>
</outgoingServer> </outgoingServer>
<?php } <?php }
if ($services["AddressBook"] && $services["AddressBook"]["Enabled"]) { if ($conf["AddressBook"]) {
$service = $services["AddressBook"]; ?> $card = $conf["AddressBook"]; ?>
<addressBook type="<?php echo strtolower($service["Type"]); ?>"> <addressBook type="<?php echo strtolower($card["Type"]); ?>">
<username><?php echo $this->get_username($service,$email_address);?></username> <username><?php echo $email_provided ? $email_address : "%EMAILADDRESS%";?></username>
<authentication><?php echo $service["Authentication"];?></authentication> <authentication><?php echo $card["Authentication"] ? $card["Authentication"] : "http-basic" ;?></authentication>
<serverURL><?php echo $service["Server"];?></serverURL> <serverURL><?php echo $card["Server"];?></serverURL>
</addressBook> </addressBook>
<?php } <?php }
if ($services["Calendar"] && $services["Calendar"]["Enabled"]){ if ($conf["Calendar"]){
$service = $services["Calendar"] ;?> $cal = $conf["Calendar"] ;?>
<calendar type="<?php echo strtolower($service["Type"]);?>"> <calendar type="<?php echo strtolower($cal["Type"]);?>">
<username><?php echo $this->get_username($service,$email_address);?></username> <username><?php echo $email_provided ? $email_address : "%EMAILADDRESS%";?></username>
<authentication><?php echo $service["Authentication"];?></authentication> <authentication><?php echo $card["Authentication"] ? $card["Authentication"] : "http-basic" ;?></authentication>
<serverURL><?php echo $service["Server"];?></serverURL> <serverURL><?php echo $card["Server"];?></serverURL>
</calendar> </calendar>
<?php } <?php }
if ($services["WebMail"] && $services["WebMail"]["Enabled"]) { if ($conf["WebMail"]) {
$service = $services["WebMail"]; ?> $wm = $conf["WebMail"]; ?>
<webMail> <webMail>
<loginPage url="<?php echo $service["Server"];?>" /> <loginPage url="<?php echo $wm["Server"];?>" />
<loginPageInfo url="<?php echo $service["Server"];?>"> <loginPageInfo url="<?php echo $wm["Server"];?>">
<username><?php echo $this->get_username($service,$email_address);?></username> <username><?php echo $email_provided ? $email_address : "%EMAILADDRESS%";?></username>
<usernameField id="<?php echo $service["UsernameDivID"];?>" name="<?php echo $service["UsernameDivName"];?>" /> <usernameField id="<?php echo $wm["UsernameDivID"];?>" name="<?php echo $wm["UsernameDivName"];?>" />
<passwordField name="<?php echo $service["PasswordDivName"];?>" /> <passwordField name="<?php echo $wm["PasswordDivName"];?>" />
<loginButton id="<?php echo $service["SubmitButtonID"];?>" name="<?php echo $service["SubmitButtonName"];?>"/> <loginButton id="<?php echo $wm["SubmitButtonID"];?>" name="<?php echo $wm["SubmitButtonName"];?>"/>
</loginPageInfo> </loginPageInfo>
</webMail> </webMail>
<?php } ?> <?php } ?>

View file

@ -8,38 +8,38 @@ preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);
// <?xml version="1.0" \?\> // <?xml version="1.0" \?\>
// <Autodiscover xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"> // <Autodiscover xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
// <Request> // <Request>
// <EMailAddress>your@email.address</EMailAddress> // <EMailAddress>psw@wilde.cloud</EMailAddress>
// <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema> // <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
// </Request> // </Request>
// </Autodiscover> // </Autodiscover>
echo '<?xml version="1.0" encoding="utf-8" ?>';?> echo '<?xml version="1.0" encoding="utf-8" ?>';?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006"> <Autodiscover xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"> <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<Account> <Account>
<AccountType>email</AccountType> <AccountType>email</AccountType>
<Action>settings</Action> <Action>settings</Action>
<?php if ($conf["InMail"] && $conf["InMail"]["Enabled"]){ <?php if ($conf["InMail"]){
$in = $conf["InMail"];?> $in = $conf["InMail"];?>
<Protocol> <Protocol>
<Type><?php echo $in["Type"];?></Type> <Type><?php echo $in["Type"];?></Type>
<Server><?php echo $in["Server"];?></Server> <Server><?php echo $in["Server"];?></Server>
<Port><?php echo $in["Port"];?></Port> <Port><?php echo $in["Port"];?></Port>
<DomainRequired><?php echo Core::$Config["RequireAuthDomain"] ? "on" : "off";?></DomainRequired> <DomainRequired><?php echo Core::$Config["RequireAuthDomain"] ? "on" : "off";?></DomainRequired>
<LoginName><?php echo isset($matches[1]) ? $matches[1] : false ; ?></LoginName> <LoginName><?php echo $matches[1]; ?></LoginName>
<SPA><?php echo $in["SPA"] ? "on" : "off";?></SPA> <SPA><?php echo $in["SPA"] ? "on" : "off";?></SPA>
<SSL><?php echo $in["SocketType"] == "SSL" ? "on" : "off";?></SSL> <SSL><?php echo $in["SocketType"] == "SSL" ? "on" : "off";?></SSL>
<AuthRequired><?php echo $in["NoAuthRequired"] ? "off" : "on";?></AuthRequired> <AuthRequired><?php echo $in["NoAuthRequired"] ? "off" : "on";?></AuthRequired>
</Protocol> </Protocol>
<?php } <?php }
if ($conf["OutMail"]&& $conf["OutMail"]["Enabled"]) { if ($conf["OutMail"]) {
$out = $conf["OutMail"];?> $out = $conf["OutMail"];?>
<Protocol> <Protocol>
<Type><?php echo $out["Type"];?></Type> <Type><?php echo $out["Type"];?></Type>
<Server><?php echo $out["Server"];?></Server> <Server><?php echo $out["Server"];?></Server>
<Port><?php echo $out["Port"];?></Port> <Port><?php echo $out["Port"];?></Port>
<DomainRequired><?php echo Core::$Config["RequireAuthDomain"] ? "on" : "off";?></DomainRequired> <DomainRequired><?php echo Core::$Config["RequireAuthDomain"] ? "on" : "off";?></DomainRequired>
<LoginName><?php echo isset($matches[1]) ? $matches[1] : false ; ?></LoginName> <LoginName><?php echo $matches[1]; ?></LoginName>
<SPA><?php echo $in["SPA"] ? "on" : "off";?></SPA> <SPA><?php echo $in["SPA"] ? "on" : "off";?></SPA>
<Encryption><?php echo $in["SocketType"];?></Encryption> <Encryption><?php echo $in["SocketType"];?></Encryption>
<AuthRequired><?php echo $in["NoAuthRequired"] ? "off" : "on";?></AuthRequired> <AuthRequired><?php echo $in["NoAuthRequired"] ? "off" : "on";?></AuthRequired>

View file

@ -4,10 +4,11 @@
; The URL of this application ; The URL of this application
BaseURL = "https://autoconfig.example.com" BaseURL = "https://autoconfig.example.com"
; Set the email domains for use with this service. The first one is primary. ; Set the base email domain for use with this service
; each will need their own DNS A record for autoconfig.domain.name Domain = example.com
Domain[] = example.com
Domain[] = example2.com
; If you use a different domain to authenticate with, enter it here ; If you use a different domain to authenticate with, enter it here
LogonDomain = example.local LogonDomain = example.local
; Change to true if you need the domain/logondomain to form part of the username
RequireAuthDomain = false

View file

@ -0,0 +1,25 @@
[InMail]
Type = "IMAP"
Server = "imap.example.com"
Port = 993
SocketType = SSL
Authentication = password-cleartext
[OutMail]
Type = "SMTP"
Server = "smtp.example.com"
Port = 465
SocketType = SSL
Authentication = password-cleartext
; Currently not implemented
;[Calendar]
;Server = "https://example.com/remote.php/dav/"
;Port = 443
;Type = CalDAV
; Currently not implemented
;[AddressBook]
;Server = "https://example.com/remote.php/dav/"
;Port = 443
;Type = CardDAV

1
src/xmltest Executable file
View file

@ -0,0 +1 @@
<EMailAddress>psw@wilde.cloud</EMailAddress>

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
a2enmod rewrite a2enmod rewrite
service apache2 stop service apache2 stop
exec bash /entrypoint.sh exec apache2-foreground

View file

@ -5,7 +5,6 @@ podman run --name mailautoconf-test \
-v ./src:/var/www/html/ \ -v ./src:/var/www/html/ \
-v ./config:/var/www/html/config \ -v ./config:/var/www/html/config \
-v ./test-entry.sh:/test-entry.sh \ -v ./test-entry.sh:/test-entry.sh \
-v ./entrypoint.sh:/entrypoint.sh \
--entrypoint "/bin/bash" \ --entrypoint "/bin/bash" \
php:7.4-apache \ php:7.4-apache \
/test-entry.sh /test-entry.sh