use super::connect_params::ServerCerts;
use super::connect_params_builder::ConnectParamsBuilder;
use super::cp_url::UrlOpt;
use crate::{HdbError, HdbResult};
use url::Url;
pub trait IntoConnectParamsBuilder {
fn into_connect_params_builder(self) -> HdbResult<ConnectParamsBuilder>;
}
impl IntoConnectParamsBuilder for ConnectParamsBuilder {
fn into_connect_params_builder(self) -> HdbResult<ConnectParamsBuilder> {
Ok(self)
}
}
impl<'a> IntoConnectParamsBuilder for &'a str {
fn into_connect_params_builder(self) -> HdbResult<ConnectParamsBuilder> {
Url::parse(self)
.map_err(|e| HdbError::conn_params(Box::new(e)))?
.into_connect_params_builder()
}
}
impl IntoConnectParamsBuilder for String {
fn into_connect_params_builder(self) -> HdbResult<ConnectParamsBuilder> {
self.as_str().into_connect_params_builder()
}
}
impl IntoConnectParamsBuilder for Url {
fn into_connect_params_builder(self) -> HdbResult<ConnectParamsBuilder> {
let mut builder = ConnectParamsBuilder::new();
self.host_str().as_ref().map(|host| builder.hostname(host));
self.port().as_ref().map(|port| builder.port(*port));
let dbuser = self.username();
if !dbuser.is_empty() {
builder.dbuser(dbuser);
}
self.password().as_ref().map(|pw| builder.password(pw));
let use_tls = match self.scheme() {
"hdbsql" => false,
"hdbsqls" => true,
_ => {
return Err(HdbError::Usage(
"Unknown protocol, only 'hdbsql' and 'hdbsqls' are supported",
));
}
};
let mut insecure_option = false;
let mut server_certs = Vec::<ServerCerts>::new();
for (name, value) in self.query_pairs() {
match UrlOpt::from(name.as_ref()) {
Some(UrlOpt::ClientLocale) => {
builder.clientlocale(&value);
}
Some(UrlOpt::ClientLocaleFromEnv) => {
std::env::var(value.to_string())
.ok()
.map(|s| builder.clientlocale(s));
}
Some(UrlOpt::TlsCertificateDir) => {
server_certs.push(ServerCerts::Directory(value.to_string()));
}
Some(UrlOpt::TlsCertificateEnv) => {
server_certs.push(ServerCerts::Environment(value.to_string()));
}
Some(UrlOpt::TlsCertificateMozilla) => {
server_certs.push(ServerCerts::RootCertificates);
}
Some(UrlOpt::InsecureOmitServerCheck) => {
insecure_option = true;
}
#[cfg(feature = "alpha_nonblocking")]
Some(UrlOpt::NonBlocking) => {
builder.use_nonblocking();
return Err(HdbError::UsageDetailed(format!(
"url option {} requires feature alpha_nonblocking",
UrlOpt::NonBlocking.name()
)));
}
Some(UrlOpt::Database) => {
builder.dbname(&value);
}
Some(UrlOpt::NetworkGroup) => {
builder.network_group(&value);
}
None => {
return Err(HdbError::UsageDetailed(format!(
"option '{}' not supported",
name
)));
}
}
}
if use_tls {
if insecure_option {
if !server_certs.is_empty() {
return Err(HdbError::Usage(
"Use the url-options 'tls_certificate_dir', 'tls_certificate_env', \
'tls_certificate_direct' and 'use_mozillas_root_certificates' \
to specify the access to the server certificate,\
or use 'insecure_omit_server_certificate_check' to not verify the server's \
identity, which is not recommended in most situations",
));
}
builder.tls_without_server_verification();
} else {
if server_certs.is_empty() {
return Err(HdbError::Usage(
"Using 'hdbsqls' requires at least one of the url-options \
'tls_certificate_dir', 'tls_certificate_env', 'tls_certificate_direct', \
'use_mozillas_root_certificates', or 'insecure_omit_server_certificate_check'",
));
}
for cert in server_certs {
builder.tls_with(cert);
}
}
} else if insecure_option || !server_certs.is_empty() {
return Err(HdbError::Usage(
"Using 'hdbsql' is not possible with any of the url-options \
'tls_certificate_dir', 'tls_certificate_env', 'tls_certificate_direct', \
'use_mozillas_root_certificates', or 'insecure_omit_server_certificate_check'; \
consider using 'hdbsqls' instead",
));
}
Ok(builder)
}
}