aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/src/vmime/platforms/posix/posixHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vmime-master/src/vmime/platforms/posix/posixHandler.cpp')
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixHandler.cpp292
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