diff options
author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
---|---|---|
committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
commit | aa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch) | |
tree | 4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /vmime-master/src/vmime/platforms/posix/posixHandler.cpp | |
download | smtps-and-pop3s-console-program-master.tar.gz smtps-and-pop3s-console-program-master.zip |
Diffstat (limited to 'vmime-master/src/vmime/platforms/posix/posixHandler.cpp')
-rw-r--r-- | vmime-master/src/vmime/platforms/posix/posixHandler.cpp | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/platforms/posix/posixHandler.cpp b/vmime-master/src/vmime/platforms/posix/posixHandler.cpp new file mode 100644 index 0000000..eecdbea --- /dev/null +++ b/vmime-master/src/vmime/platforms/posix/posixHandler.cpp @@ -0,0 +1,292 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_PLATFORM_IS_POSIX + + +#include "vmime/platforms/posix/posixHandler.hpp" + +#include "vmime/platforms/posix/posixCriticalSection.hpp" + +#include "vmime/utility/stringUtils.hpp" + +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <locale.h> +#include <langinfo.h> +#include <errno.h> +#include <limits.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#if VMIME_HAVE_SYSCALL +# include <sys/syscall.h> +#endif + +#include <netdb.h> + +#include <string.h> +#include <cassert> +#include <cstdlib> + + +/* +#ifdef _POSIX_PRIORITY_SCHEDULING + #include <sched.h> +#endif // _POSIX_PRIORITY_SCHEDULING +*/ + + +namespace vmime { +namespace platforms { +namespace posix { + + +posixHandler::posixHandler() { + +#if VMIME_HAVE_MESSAGING_FEATURES + m_socketFactory = make_shared <posixSocketFactory>(); +#endif +#if VMIME_HAVE_FILESYSTEM_FEATURES + m_fileSysFactory = make_shared <posixFileSystemFactory>(); + m_childProcFactory = make_shared <posixChildProcessFactory>(); +#endif + +} + + +posixHandler::~posixHandler() { + +} + + +unsigned long posixHandler::getUnixTime() const { + + return static_cast <unsigned long>(::time(NULL)); +} + + +const vmime::datetime posixHandler::getCurrentLocalTime() const { + + const time_t t(::time(NULL)); + + // Get the local time +#if VMIME_HAVE_LOCALTIME_R + tm local; + ::localtime_r(&t, &local); +#else + tm local = *::localtime(&t); // WARNING: this is not thread-safe! +#endif + + // Get the UTC time +#if VMIME_HAVE_GMTIME_R + tm gmt; + ::gmtime_r(&t, &gmt); +#else + tm gmt = *::gmtime(&t); // WARNING: this is not thread-safe! +#endif + + // "A negative value for tm_isdst causes mktime() to attempt + // to determine whether Daylight Saving Time is in effect + // for the specified time." + local.tm_isdst = -1; + gmt.tm_isdst = -1; + + // Calculate the difference (in seconds) + const time_t diff = ::mktime(&local) - ::mktime(&gmt); + + // Return the date + return vmime::datetime( + local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, + local.tm_hour, local.tm_min, local.tm_sec, static_cast <int>(diff / 60) + ); +} + + +const vmime::charset posixHandler::getLocalCharset() const { + + // Note: nl_langinfo() might be affected by calls to setlocale() + // in a multithread environment. There is not MT-safe alternative + // to nl_langinfo(). + auto codeset = ::nl_langinfo(CODESET); + + if (codeset) { + return vmime::charset(codeset); + } + + return vmime::charset(); +} + + +static inline bool isAcceptableHostname(const vmime::string& str) { + + // At least, try to find something better than "localhost" + if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9) || + utility::stringUtils::isStringEqualNoCase(str, "localhost.localdomain", 21)) { + + return false; + } + + // Anything else will be OK, as long as it is a valid hostname + return utility::stringUtils::isValidHostname(str); +} + + +const vmime::string posixHandler::getHostName() const { + char hostname[256]; + + ::gethostname(hostname, sizeof(hostname)); + hostname[sizeof(hostname)-1] = '\0'; + + // Try to get official canonical name of this host + struct addrinfo hints; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // either IPV4 or IPV6 + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + + struct addrinfo* info; + + if (getaddrinfo(hostname, "http", &hints, &info) == 0) { + // First, try to get a Fully-Qualified Domain Name (FQDN) + for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) { + + if (p->ai_canonname) { + + const string hn(p->ai_canonname); + + if (utility::stringUtils::isValidFQDN(hn)) { + freeaddrinfo(info); + return hn; + } + } + } + + // Then, try to find an acceptable host name + for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) { + + if (p->ai_canonname) { + + const string hn(p->ai_canonname); + + if (isAcceptableHostname(hn)) { + freeaddrinfo(info); + return hn; + } + } + } + + freeaddrinfo(info); + } + + if (::strlen(hostname) == 0 || !isAcceptableHostname(hostname)) { + ::strcpy(hostname, "localhost.localdomain"); + } + + return hostname; +} + + +unsigned int posixHandler::getProcessId() const { + + return ::getpid(); +} + + +unsigned int posixHandler::getThreadId() const { + +#if VMIME_HAVE_GETTID + return static_cast <unsigned int>(::gettid()); +#elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID + return static_cast <unsigned int>(::syscall(SYS_gettid)); +#elif VMIME_HAVE_GETTHRID // OpenBSD + return static_cast <unsigned int>(::getthrid()); +#else + #error We have no implementation of getThreadId() for this platform! +#endif + +} + + +#if VMIME_HAVE_MESSAGING_FEATURES + +shared_ptr <vmime::net::socketFactory> posixHandler::getSocketFactory() { + + return m_socketFactory; +} + +#endif + + +#if VMIME_HAVE_FILESYSTEM_FEATURES + +shared_ptr <vmime::utility::fileSystemFactory> posixHandler::getFileSystemFactory() { + + return m_fileSysFactory; +} + + +shared_ptr <vmime::utility::childProcessFactory> posixHandler::getChildProcessFactory() { + + return m_childProcFactory; +} + +#endif + + +void posixHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) { + + int fd = open("/dev/urandom", O_RDONLY); + + if (fd != -1) { + + read(fd, buffer, count); + close(fd); + + } else { // fallback + + for (unsigned int i = 0 ; i < count ; ++i) { + buffer[i] = static_cast <unsigned char>(rand() % 255); + } + } +} + + +shared_ptr <utility::sync::criticalSection> posixHandler::createCriticalSection() { + + return make_shared <posixCriticalSection>(); +} + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_POSIX |