summaryrefslogtreecommitdiffstats
path: root/src/uscxml/util
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-01-08 21:59:18 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-01-08 21:59:18 (GMT)
commit030f3b483f54dbef6e164194a1771ef5b346312b (patch)
tree3f5b949b5ffed83d0b41a95d9fd3cfafd17cab2d /src/uscxml/util
parent1ab8b9a0dcaa131b8cccc735a1794ce39b351715 (diff)
downloaduscxml-030f3b483f54dbef6e164194a1771ef5b346312b.zip
uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.tar.gz
uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.tar.bz2
Support for caching values on filesystem
Use USCXML_NOCACHE_FILES=YES to prevent, I will make this a build flag
Diffstat (limited to 'src/uscxml/util')
-rw-r--r--src/uscxml/util/Base64.hpp4
-rw-r--r--src/uscxml/util/Convenience.cpp32
-rw-r--r--src/uscxml/util/Convenience.h2
-rw-r--r--src/uscxml/util/URL.cpp168
-rw-r--r--src/uscxml/util/URL.h16
-rw-r--r--src/uscxml/util/URL.mm62
6 files changed, 263 insertions, 21 deletions
diff --git a/src/uscxml/util/Base64.hpp b/src/uscxml/util/Base64.hpp
index e3cbe03..d9f9ac1 100644
--- a/src/uscxml/util/Base64.hpp
+++ b/src/uscxml/util/Base64.hpp
@@ -40,9 +40,9 @@ USCXML_API inline std::string base64Decode(const std::string& data) {
base64_init_decodestate(ctx);
char* out = (char*)malloc(data.size());
- base64_decode_block(data.data(), data.size(), out, ctx);
+ size_t size = base64_decode_block(data.data(), data.size(), out, ctx);
free(ctx);
- std::string result(out);
+ std::string result(out, size);
free(out);
return result;
}
diff --git a/src/uscxml/util/Convenience.cpp b/src/uscxml/util/Convenience.cpp
index a0263d2..4f47449 100644
--- a/src/uscxml/util/Convenience.cpp
+++ b/src/uscxml/util/Convenience.cpp
@@ -24,22 +24,22 @@
namespace uscxml {
NumAttr::NumAttr(const std::string& str) {
- size_t valueStart = str.find_first_of("0123456789.");
- if (valueStart != std::string::npos) {
- size_t valueEnd = str.find_last_of("0123456789.");
- if (valueEnd != std::string::npos) {
- value = str.substr(valueStart, (valueEnd - valueStart) + 1);
- size_t unitStart = str.find_first_not_of(" \t", valueEnd + 1);
- if (unitStart != std::string::npos) {
- size_t unitEnd = str.find_last_of(" \t");
- if (unitEnd != std::string::npos && unitEnd > unitStart) {
- unit = str.substr(unitStart, unitEnd - unitStart);
- } else {
- unit = str.substr(unitStart, str.length() - unitStart);
- }
- }
- }
- }
+ size_t valueStart = str.find_first_of("0123456789.");
+ if (valueStart != std::string::npos) {
+ size_t valueEnd = str.find_last_of("0123456789.");
+ if (valueEnd != std::string::npos) {
+ value = str.substr(valueStart, (valueEnd - valueStart) + 1);
+ size_t unitStart = str.find_first_not_of(" \t", valueEnd + 1);
+ if (unitStart != std::string::npos) {
+ size_t unitEnd = str.find_last_of(" \t");
+ if (unitEnd != std::string::npos && unitEnd > unitStart) {
+ unit = str.substr(unitStart, unitEnd - unitStart);
+ } else {
+ unit = str.substr(unitStart, str.length() - unitStart);
+ }
+ }
+ }
+ }
}
diff --git a/src/uscxml/util/Convenience.h b/src/uscxml/util/Convenience.h
index cb4416d..c12e0e4 100644
--- a/src/uscxml/util/Convenience.h
+++ b/src/uscxml/util/Convenience.h
@@ -45,7 +45,7 @@ template <typename T> T strTo(std::string tmp) {
class USCXML_API NumAttr {
public:
- NumAttr(const std::string& str);
+ NumAttr(const std::string& str);
std::string value;
std::string unit;
};
diff --git a/src/uscxml/util/URL.cpp b/src/uscxml/util/URL.cpp
index 0885b47..845a972 100644
--- a/src/uscxml/util/URL.cpp
+++ b/src/uscxml/util/URL.cpp
@@ -29,14 +29,17 @@
#include <curl/curl.h>
#include <uriparser/Uri.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#ifdef _WIN32
#include <direct.h>
+#include <Shlobj.h>
#define getcwd _getcwd
#else
#include <unistd.h> // getcwd
-//#include <pwd.h>
+#include <pwd.h> // getpwuid
#endif
#define DOWNLOAD_IF_NECESSARY if (!_isDownloaded) { download(true); }
@@ -44,6 +47,157 @@
namespace uscxml {
+std::string URL::currTmpDir;
+
+std::string URL::getTempDir(bool shared) {
+
+#ifdef _WIN32
+ struct stat st = { 0 };
+ TCHAR tmpPrefix [MAX_PATH];
+
+ // retrieve and optionally create temporary directory
+ if (!GetTempPath(MAX_PATH, tmpPrefix)) {
+ ERROR_EXECUTION_THROW(std::string("Cannot retrieve temporary directory"));
+ }
+ if (stat(tmpPrefix, &st) == -1) {
+ CreateDirectory(tmpPrefix, NULL);
+ if (GetLastError() == ERROR_PATH_NOT_FOUND) {
+ ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + tmpPrefix + "'");
+ }
+ }
+
+ if (shared) {
+ // create uscxml folder in temporary directory
+ std::string sharedTmpDir = std::string(tmpPrefix) + PATH_SEPERATOR + "uscxml";
+
+ if (stat(sharedTmpDir.c_str(), &st) == -1) {
+ CreateDirectory (sharedTmpDir.c_str(), NULL);
+ if (GetLastError() == ERROR_PATH_NOT_FOUND) {
+ ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + sharedTmpDir + "'");
+ }
+ }
+ return sharedTmpDir;
+
+ } else {
+ if (currTmpDir.size() == 0) {
+ // create random folder in temporary directory
+ // http://stackoverflow.com/questions/6287475/creating-a-unique-temporary-directory-from-pure-c-in-windows
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363875(v=vs.85).aspx
+ TCHAR tempFileName[MAX_PATH];
+ if (GetTempFileName(tmpPrefix, // directory for tmp files
+ TEXT("uscxml."), // temp file name prefix
+ 0, // create unique name
+ tempFileName)) {
+ DeleteFile(tempFileName);
+
+ if (stat(tempFileName, &st) == -1) {
+ CreateDirectory(tempFileName, NULL);
+ if (GetLastError() == ERROR_PATH_NOT_FOUND) {
+ ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + tempFileName + "'");
+ }
+ }
+
+ currTmpDir = tempFileName;
+ } else {
+ ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + tmpPrefix + "'");
+ }
+ }
+ return currTmpDir;
+ }
+
+#else
+ std::string tmpPrefix = "/tmp";
+ const char* tmpEnv = getenv("TMPDIR");
+ if (tmpEnv != NULL)
+ tmpPrefix = tmpEnv;
+
+ if (tmpPrefix[tmpPrefix.size() - 1] != PATH_SEPERATOR)
+ tmpPrefix += PATH_SEPERATOR;
+
+ if (shared) {
+ struct stat st = {0};
+
+ std::string sharedTmpDir = tmpPrefix + "uscxml";
+ if (stat(sharedTmpDir.c_str(), &st) == -1) {
+ int err = mkdir(sharedTmpDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); // 777
+ if (err)
+ ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + sharedTmpDir + "':" + strerror(errno));
+
+ }
+ return sharedTmpDir;
+
+ } else {
+ if (currTmpDir.size() == 0) {
+ std::string tmpPrefix = "/tmp";
+ const char* tmpEnv = getenv("TMPDIR");
+ if (tmpEnv != NULL)
+ tmpPrefix = tmpEnv;
+ const char* tmpName = mkdtemp((char*)std::string(tmpPrefix + "uscxml.XXXXXX").c_str()); // can we merely drop the constness?
+ if (tmpName != NULL) {
+ currTmpDir = tmpName;
+ } else {
+ ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory:") + strerror(errno));
+ }
+ }
+ return currTmpDir;
+ }
+#endif
+}
+
+// Version for MacOSX in URL.mm
+#if (!defined APPLE && !defined IOS)
+std::string URL::getResourceDir() {
+#ifdef _WIN32
+ TCHAR szPath[MAX_PATH];
+ std::string resourceDir;
+ if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath) == S_OK) {
+ resourceDir = std::string(szPath) + PATH_SEPERATOR + "uscxml";
+ } else {
+ char* envData = getenv("APPDATA");
+ if (envData) {
+ resourceDir = std::string(envData) + PATH_SEPERATOR + "uscxml";
+ } else {
+ ERROR_EXECUTION_THROW("Could not get resource directory");
+ }
+ }
+
+ struct stat st = { 0 };
+
+ if (stat(resourceDir.c_str(), &st) == -1) {
+ CreateDirectory(resourceDir.c_str(), NULL);
+ if (GetLastError() == ERROR_PATH_NOT_FOUND) {
+ ERROR_EXECUTION_THROW(std::string("Cannot create a resource directory at '") + resourceDir + "'");
+ }
+ }
+ return resourceDir;
+
+#else
+ struct passwd* pw = getpwuid(getuid());
+ std::string homedir(pw->pw_dir);
+ struct stat dirStat;
+ int err = 0;
+
+ err = stat(std::string(homedir + PATH_SEPERATOR + ".config").c_str(), &dirStat);
+ if (err == ENOENT) {
+ err = mkdir(std::string(homedir + PATH_SEPERATOR + ".config").c_str(), S_IWUSR | S_IRUSR | S_IROTH);
+ }
+
+ err = stat(std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml").c_str(), &dirStat);
+ if (err != 0) {
+ // std::cout << std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml") << std::endl;
+ err = mkdir(std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml").c_str(),
+ S_IWUSR | S_IRUSR | S_IROTH | S_IRGRP | S_IXUSR | S_IXOTH | S_IXGRP);
+ }
+
+ err = stat(std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml").c_str(), &dirStat);
+ if (err == 0) {
+ return homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml";
+ }
+ return "";
+#endif
+}
+#endif
+
void URLImpl::prepareException(ErrorEvent& exception, int errorCode, const std::string& origUri, void* parser) {
exception.data.compound["uri"].atom = origUri;
@@ -808,9 +962,19 @@ void URLFetcher::perform() {
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
- case -1:
+ case -1: {
/* select error */
+#ifdef _WIN32
+ char *s = NULL;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, WSAGetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&s, 0, NULL);
+ LOGD(USCXML_WARN) << "select: " << s;
+ LocalFree(s);
+#endif
break;
+ }
case 0: /* timeout */
default: { /* action */
std::lock_guard<std::recursive_mutex> lock(_mutex);
diff --git a/src/uscxml/util/URL.h b/src/uscxml/util/URL.h
index c83e3b1..9ad2f8e 100644
--- a/src/uscxml/util/URL.h
+++ b/src/uscxml/util/URL.h
@@ -136,6 +136,19 @@ public:
URL(const std::string url) : _impl(new URLImpl(url)) {}
+ /**
+ * Get a persistant, shared directory for resources
+ * @return A path to an existing directory for resources.
+ */
+ static std::string getResourceDir();
+
+ /**
+ * Get a temporary, shared or private directory for resources
+ * @param shared Whether the temporary directory is shared among instances.
+ * @return A path to an existing directory for temporary files.
+ */
+ static std::string getTempDir(bool shared = true);
+
bool isAbsolute() {
return _impl->isAbsolute();
}
@@ -241,6 +254,8 @@ public:
protected:
std::shared_ptr<URLImpl> _impl;
friend class URLFetcher;
+ static std::string currTmpDir;
+
};
class USCXML_API URLFetcher {
@@ -270,6 +285,7 @@ protected:
std::map<void*, void*> _handlesToHeaders;
void* _multiHandle = NULL;
char* _envProxy = NULL;
+
};
}
diff --git a/src/uscxml/util/URL.mm b/src/uscxml/util/URL.mm
new file mode 100644
index 0000000..881b3e2
--- /dev/null
+++ b/src/uscxml/util/URL.mm
@@ -0,0 +1,62 @@
+/**
+ * @file
+ * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "URL.h"
+#include "Foundation/Foundation.h"
+
+#ifdef __has_feature
+# if __has_feature(objc_arc)
+# define(HAS_AUTORELEASE_POOL)
+# endif
+#endif
+
+namespace uscxml {
+
+std::string URL::getResourceDir() {
+ std::string path;
+#if HAS_AUTORELEASE_POOL
+ @autoreleasepool {
+#else
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+#endif
+ NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
+ if (bundleId != nil) {
+ NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
+ path = [resourcePath cStringUsingEncoding:NSUTF8StringEncoding];
+ } else {
+ // we are not actually in a bundle, fall back to /tmp
+ NSFileManager *fm = [NSFileManager defaultManager];
+ NSURL* resURL = [[fm homeDirectoryForCurrentUser] URLByAppendingPathComponent:@".uscxml"];
+ NSString* resPath = [NSString stringWithUTF8String:[resURL fileSystemRepresentation]];
+
+ if (![fm fileExistsAtPath:resPath]) {
+ [fm createDirectoryAtPath:resPath withIntermediateDirectories:YES attributes:nil error:nil];
+ }
+ path = [resPath cStringUsingEncoding:NSUTF8StringEncoding];
+ }
+
+#if HAS_AUTORELEASE_POOL
+ }
+#else
+ [pool drain];
+#endif
+ return path;
+}
+
+}