#include "base/utility.hpp"
#include "base/json.hpp"
#include "base/objectlock.hpp"
+#include "base/scriptfunction.hpp"
#include <mmatch.h>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
boost::thread_specific_ptr<String> Utility::m_ThreadName;
boost::thread_specific_ptr<unsigned int> Utility::m_RandSeed;
+REGISTER_SCRIPTFUNCTION(escape, &Utility::EscapeString);
+REGISTER_SCRIPTFUNCTION(unescape, &Utility::UnescapeString);
+
/**
* Demangles a symbol name.
*
<< boost::errinfo_file_name(tempPath));
}
}
+
+static void HexEncode(char ch, std::ostream& os)
+{
+ const char *hex_chars = "0123456789ABCDEF";
+
+ os << hex_chars[ch >> 4 & 0x0f];
+ os << hex_chars[ch & 0x0f];
+}
+
+static int HexDecode(char hc)
+{
+ if (hc >= '0' && hc <= '9')
+ return hc - '0';
+ else if (hc >= 'a' && hc <= 'f')
+ return hc - 'a' + 10;
+ else if (hc >= 'A' && hc <= 'F')
+ return hc - 'A' + 10;
+ else
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid hex character."));
+}
+
+String Utility::EscapeString(const String& s, const String& chars)
+{
+ std::ostringstream result;
+
+ BOOST_FOREACH(char ch, s) {
+ if (chars.FindFirstOf(ch) != String::NPos || ch == '%') {
+ result << '%';
+ HexEncode(ch, result);
+ } else
+ result << ch;
+ }
+
+ return result.str();
+}
+
+String Utility::UnescapeString(const String& s)
+{
+ std::ostringstream result;
+
+ for (String::SizeType i = 0; i < s.GetLength(); i++) {
+ if (s[i] == '%') {
+ if (i + 2 > s.GetLength() - 1)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid escape sequence."));
+
+ char ch = HexDecode(s[i + 1]) * 16 + HexDecode(s[i + 2]);
+ result << ch;
+
+ i += 2;
+ } else
+ result << s[i];
+ }
+
+ return result.str();
+}
if (type == "Host")
path += "hosts";
else if (type == "Service")
- path += "hosts/" + object->Get("host_name");
+ path += "hosts/" + EscapeName(object->Get("host_name"));
else if (type == "Zone")
path += "zones";
else if (type == "Endpoint")
{
String path = GetRepositoryObjectConfigPath(type, object);
- path += "/" + object->Get("name") + ".conf";
+ path += "/" + EscapeName(object->Get("name")) + ".conf";
return path;
}
String file = Utility::BaseName(object);
boost::algorithm::replace_all(file, ".conf", "");
+ file = UnescapeName(file);
fp << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << type << ConsoleColorTag(Console_Normal)
<< " '" << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << file << ConsoleColorTag(Console_Normal) << "'";
std::vector<String> tokens;
boost::algorithm::split(tokens, prefix, boost::is_any_of("/"));
- String host_name = tokens[tokens.size()-1];
+ String host_name = UnescapeName(tokens[tokens.size()-1]);
fp << " (on " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << "Host" << ConsoleColorTag(Console_Normal)
<< " '" << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << host_name << ConsoleColorTag(Console_Normal) << "')";
String pattern;
if (type == "Service")
- pattern = attrs->Get("host_name") + "/" + name + ".conf";
+ pattern = EscapeName(attrs->Get("host_name")) + "/" + EscapeName(name) + ".conf";
else
- pattern = name + ".conf";
+ pattern = EscapeName(name) + ".conf";
BOOST_FOREACH(const String& object_path, object_paths) {
if (object_path.Contains(pattern)) {
/* internal implementation when changes are committed */
bool RepositoryUtility::AddObjectInternal(const String& name, const String& type, const Dictionary::Ptr& attrs)
{
- String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + name + ".conf";
+ String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + EscapeName(name) + ".conf";
return WriteObjectToRepository(path, name, type, attrs);
}
bool RepositoryUtility::RemoveObjectInternal(const String& name, const String& type, const Dictionary::Ptr& attrs)
{
- String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + name + ".conf";
+ String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + EscapeName(name) + ".conf";
if (!Utility::PathExists(path)) {
Log(LogWarning, "cli")
bool RepositoryUtility::SetObjectAttributeInternal(const String& name, const String& type, const String& key, const Value& val, const Dictionary::Ptr& attrs)
{
//TODO
- String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + name + ".conf";
+ String path = GetRepositoryObjectConfigPath(type, attrs) + "/" + EscapeName(name) + ".conf";
Dictionary::Ptr obj = GetObjectFromRepository(path); //TODO
return Dictionary::Ptr();
}
+String RepositoryUtility::EscapeName(const String& name)
+{
+ return Utility::EscapeString(name, "<>:\"/\\|?*");
+}
+
+String RepositoryUtility::UnescapeName(const String& name)
+{
+ return Utility::UnescapeString(name);
+}
/*
* collect functions