#ifndef _PLT_UTILITIES_H_
#define _PLT_UTILITIES_H_
#include "Neptune.h"
class PLT_XmlAttributeFinder
{
public:
PLT_XmlAttributeFinder(const NPT_XmlElementNode& element,
const char* name,
const char* namespc) :
m_Element(element), m_Name(name), m_Namespace(namespc) {}
bool operator()(const NPT_XmlAttribute* const & attribute) const {
if (attribute->GetName() == m_Name) {
if (m_Namespace) {
const NPT_String& prefix = attribute->GetPrefix();
if (m_Namespace[0] == '\0') {
return prefix.IsEmpty();
} else {
const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
return namespc && *namespc == m_Namespace;
}
} else {
return true;
}
} else {
return false;
}
}
private:
const NPT_XmlElementNode& m_Element;
const char* m_Name;
const char* m_Namespace;
};
class PLT_XmlHelper
{
public:
static NPT_Result Parse(const NPT_String& xml,
NPT_XmlElementNode*& tree) {
tree = NULL;
NPT_XmlParser parser;
NPT_XmlNode* node;
NPT_Result result = parser.Parse(xml, node);
if (NPT_FAILED(result)) {
NPT_CHECK(result);
}
tree = node->AsElementNode();
if (!tree) {
delete node;
return NPT_FAILURE;
}
return NPT_SUCCESS;
}
static NPT_Result GetChildText(NPT_XmlElementNode* node,
const char* tag,
NPT_String& value,
const char* namespc = "",
NPT_Cardinal max_size = 1024) {
value = "";
if (!node) return NPT_FAILURE;
if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
NPT_XmlElementNode* child = node->GetChild(tag, namespc);
if (!child) return NPT_FAILURE;
const NPT_String* text = child->GetText();
value = text?text->SubString(0, max_size):"";
return NPT_SUCCESS;
}
static NPT_Result RemoveAttribute(NPT_XmlElementNode* node,
const char* name,
const char* namespc = "") {
if (!node) return NPT_FAILURE;
if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
NPT_List<NPT_XmlAttribute*>::Iterator attribute;
attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
if (!attribute) return NPT_FAILURE;
delete *attribute;
NPT_CHECK(node->GetAttributes().Erase(attribute));
return NPT_SUCCESS;
}
static NPT_Result GetAttribute(NPT_XmlElementNode* node,
const char* name,
NPT_XmlAttribute*& attr,
const char* namespc = "") {
attr = NULL;
if (!node) return NPT_FAILURE;
if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
NPT_List<NPT_XmlAttribute*>::Iterator attribute;
attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
if (!attribute) {
return NPT_FAILURE;
}
attr = (*attribute);
return NPT_SUCCESS;
}
static NPT_Result GetAttribute(NPT_XmlElementNode* node,
const char* name,
NPT_String& value,
const char* namespc = "",
NPT_Cardinal max_size = 1024) {
value = "";
NPT_XmlAttribute* attribute = NULL;
NPT_Result result = GetAttribute(node, name, attribute, namespc);
if (NPT_FAILED(result)) return result;
if (!attribute) return NPT_FAILURE;
value = attribute->GetValue().SubString(0, max_size);
return NPT_SUCCESS;
}
static NPT_Result SetAttribute(NPT_XmlElementNode* node,
const char* name,
NPT_String& value,
const char* namespc = "") {
NPT_XmlAttribute* attribute = NULL;
NPT_CHECK(GetAttribute(node, name, attribute, namespc));
if (!attribute) return NPT_FAILURE;
attribute->SetValue(value);
return NPT_SUCCESS;
}
static NPT_Result AddChildText(NPT_XmlElementNode* node,
const char* tag,
const char* text,
const char* prefix = NULL) {
if (!node) return NPT_FAILURE;
NPT_XmlElementNode* child = new NPT_XmlElementNode(prefix, tag);
child->AddText(text);
return node->AddChild(child);
}
static bool IsMatch(const NPT_XmlNode* const & node, const char* tag, const char* namespc_mapped) {
const NPT_XmlElementNode* element = node->AsElementNode();
if (element && element->GetTag() == tag) {
if (namespc_mapped) {
const NPT_String* namespc = element->GetNamespace();
if (namespc) {
return *namespc == namespc_mapped;
} else {
return namespc_mapped[0] == '\0';
}
} else {
return true;
}
}
return false;
}
static NPT_Result GetChildren(NPT_XmlElementNode* node,
NPT_Array<NPT_XmlElementNode*>& children,
const char* tag,
const char* namespc = "") {
if (!node) return NPT_FAILURE;
if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
const char* namespc_mapped = (namespc==NULL)?"":(namespc[0]=='*' && namespc[1]=='\0')?NULL:namespc;
NPT_List<NPT_XmlNode*>& allchildren = node->GetChildren();
NPT_List<NPT_XmlNode*>::Iterator child = allchildren.GetFirstItem();
while (child) {
if (IsMatch(*child, tag, namespc_mapped)) {
children.Add((*child)->AsElementNode());
}
++child;
}
return NPT_SUCCESS;
}
static NPT_XmlElementNode* GetChild(NPT_XmlElementNode* node,
const char* tag,
const char* namespc = "") {
if (!node) return NULL;
if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
return node->GetChild(tag, namespc);
}
static NPT_Result GetChild(NPT_XmlElementNode* parent,
NPT_XmlElementNode*& child,
NPT_Ordinal n = 0) {
if (!parent) return NPT_FAILURE;
child = NULL;
NPT_List<NPT_XmlNode*>::Iterator children = parent->GetChildren().GetFirstItem();
while (children) {
if ((*children)->AsElementNode() && n-- == 0) {
child = (*children)->AsElementNode();
return NPT_SUCCESS;
}
children++;
}
return NPT_FAILURE;
}
static NPT_Result Serialize(NPT_XmlNode& node, NPT_String& xml, bool add_header = true, NPT_Int8 indentation = 0) {
NPT_XmlWriter writer(indentation);
NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
NPT_CHECK(writer.Serialize(node, *stream, add_header));
return NPT_SUCCESS;
}
static NPT_String Serialize(NPT_XmlNode& node, bool add_header = true, NPT_Int8 indentation = 0) {
NPT_XmlWriter writer(indentation);
NPT_String xml;
NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
if (NPT_FAILED(writer.Serialize(node, *stream, add_header))) {
NPT_Debug("Failed to serialize xml node");
return "";
}
return xml;
}
private:
};
class NPT_StringFinder
{
public:
NPT_StringFinder(const char* value, bool ignore_case = false) :
m_Value(value), m_IgnoreCase(ignore_case) {}
virtual ~NPT_StringFinder() {}
bool operator()(const NPT_String* const & value) const {
return value->Compare(m_Value, m_IgnoreCase) ? false : true;
}
bool operator()(const NPT_String& value) const {
return value.Compare(m_Value, m_IgnoreCase) ? false : true;
}
private:
NPT_String m_Value;
bool m_IgnoreCase;
};
class NPT_IpAddressFinder
{
public:
NPT_IpAddressFinder(NPT_IpAddress ip) : m_Value(ip) {}
virtual ~NPT_IpAddressFinder() {}
bool operator()(const NPT_IpAddress* const & value) const {
return *value == m_Value;
}
bool operator()(const NPT_IpAddress& value) const {
return value == m_Value;
}
private:
NPT_IpAddress m_Value;
};
class PLT_UPnPMessageHelper
{
public:
static const NPT_String* GetST(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("ST");
}
static NPT_Result SetST(NPT_HttpMessage& message,
const char* st) {
return message.GetHeaders().SetHeader("ST", st);
}
static const NPT_String* GetNT(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("NT");
}
static NPT_Result SetNT(NPT_HttpMessage& message,
const char* nt) {
return message.GetHeaders().SetHeader("NT", nt);
}
static const NPT_String* GetNTS(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("NTS");
}
static NPT_Result SetNTS(NPT_HttpMessage& message,
const char* nts) {
return message.GetHeaders().SetHeader("NTS", nts);
}
static const NPT_String* GetMAN(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("MAN");
}
static NPT_Result SetMAN(NPT_HttpMessage& message,
const char* man) {
return message.GetHeaders().SetHeader("MAN", man);
}
static const NPT_String* GetLocation(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("Location");
}
static NPT_Result SetLocation(NPT_HttpMessage& message,
const char* location) {
return message.GetHeaders().SetHeader("Location", location);
}
static const NPT_String* GetServer(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER);
}
static NPT_Result SetServer(NPT_HttpMessage& message,
const char* server,
bool replace = true) {
return message.GetHeaders().SetHeader(
NPT_HTTP_HEADER_SERVER,
server,
replace);
}
static const NPT_String* GetUSN(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("USN");
}
static NPT_Result SetUSN(NPT_HttpMessage& message,
const char* usn) {
return message.GetHeaders().SetHeader("USN", usn);
}
static const NPT_String* GetCallbacks(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("CALLBACK");
}
static NPT_Result SetCallbacks(NPT_HttpMessage& message,
const char* callbacks) {
return message.GetHeaders().SetHeader("CALLBACK", callbacks);
}
static const NPT_String* GetSID(const NPT_HttpMessage& message) {
return message.GetHeaders().GetHeaderValue("SID");
}
static NPT_Result SetSID(NPT_HttpMessage& message,
const char* sid) {
return message.GetHeaders().SetHeader("SID", sid);
}
static NPT_Result GetLeaseTime(const NPT_HttpMessage& message,
NPT_TimeInterval& lease) {
const NPT_String* cc =
message.GetHeaders().GetHeaderValue("Cache-Control");
NPT_CHECK_POINTER(cc);
return ExtractLeaseTime(*cc, lease);
}
static NPT_Result SetLeaseTime(NPT_HttpMessage& message,
const NPT_TimeInterval& lease) {
return message.GetHeaders().SetHeader(
"Cache-Control",
"max-age="+NPT_String::FromInteger(lease.ToSeconds()));
}
static NPT_Result GetTimeOut(const NPT_HttpMessage& message,
NPT_Int32& seconds) {
seconds = 0;
const NPT_String* timeout =
message.GetHeaders().GetHeaderValue("TIMEOUT");
NPT_CHECK_POINTER(timeout);
return ExtractTimeOut(*timeout, seconds);
}
static NPT_Result SetTimeOut(NPT_HttpMessage& message,
const NPT_Int32 seconds) {
if (seconds >= 0) {
return message.GetHeaders().SetHeader(
"TIMEOUT",
"Second-"+NPT_String::FromInteger(seconds));
} else {
return message.GetHeaders().SetHeader(
"TIMEOUT",
"Second-infinite");
}
}
static NPT_Result SetDate(NPT_HttpMessage& message) {
NPT_TimeStamp now;
NPT_System::GetCurrentTimeStamp(now);
NPT_DateTime date(now);
return message.GetHeaders().SetHeader("Date", date.ToString(NPT_DateTime::FORMAT_RFC_1123));
}
static NPT_Result GetIfModifiedSince(const NPT_HttpMessage& message,
NPT_DateTime& date) {
const NPT_String* value =
message.GetHeaders().GetHeaderValue("If-Modified-Since");
if (!value) return NPT_FAILURE;
if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1123)))
return NPT_SUCCESS;
if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1036)))
return NPT_SUCCESS;
return date.FromString(*value, NPT_DateTime::FORMAT_ANSI);
}
static NPT_Result SetIfModifiedSince(NPT_HttpMessage& message,
const NPT_DateTime& date) {
return message.GetHeaders().SetHeader(
"If-Modified-Since",
date.ToString(NPT_DateTime::FORMAT_RFC_1123));
}
static NPT_Result GetMX(const NPT_HttpMessage& message,
NPT_UInt32& value) {
value = 0;
const NPT_String* mx =
message.GetHeaders().GetHeaderValue("MX");
NPT_CHECK_POINTER(mx);
return NPT_ParseInteger32(*mx, value, false);
}
static NPT_Result SetMX(NPT_HttpMessage& message,
const NPT_UInt32 mx) {
return message.GetHeaders().SetHeader(
"MX",
NPT_String::FromInteger(mx));
}
static NPT_Result GetSeq(const NPT_HttpMessage& message,
NPT_UInt32& value) {
value = 0;
const NPT_String* seq =
message.GetHeaders().GetHeaderValue("SEQ");
NPT_CHECK_POINTER(seq);
return NPT_ParseInteger32(*seq, value);
}
static NPT_Result SetSeq(NPT_HttpMessage& message,
const NPT_UInt32 seq) {
return message.GetHeaders().SetHeader(
"SEQ",
NPT_String::FromInteger(seq));
}
static const char* GenerateUUID(int count,
NPT_String& uuid) {
uuid = "";
for (int i=0;i<(count<100?count:100);i++) {
int random = NPT_System::GetRandomInteger();
uuid += (char)((random % 25) + 66);
}
return uuid;
}
static const char* GenerateSerialNumber(NPT_String& sn, int count = 40) {
sn = "{";
for (int i=0;i<count;i++) {
char nibble = (char)(NPT_System::GetRandomInteger() % 16);
sn += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
}
sn += "}";
return sn;
}
static const char* GenerateGUID(NPT_String& guid) {
guid = "";
for (int i=0;i<32;i++) {
char nibble = (char)(NPT_System::GetRandomInteger() % 16);
guid += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
if (i == 7 || i == 11 || i == 15 || i == 19) {
guid += '-';
}
}
return guid;
}
static NPT_Result ExtractLeaseTime(const NPT_String& cache_control,
NPT_TimeInterval& lease) {
NPT_Int32 value;
if (cache_control.StartsWith("max-age=", true) &&
NPT_SUCCEEDED(NPT_ParseInteger32(cache_control.GetChars()+8,
value))) {
lease.SetSeconds(value);
return NPT_SUCCESS;
}
return NPT_FAILURE;
}
static NPT_Result ExtractTimeOut(const char* timeout,
NPT_Int32& len) {
NPT_String temp = timeout;
if (temp.CompareN("Second-", 7, true)) {
return NPT_ERROR_INVALID_FORMAT;
}
if (temp.Compare("Second-infinite", true) == 0) {
len = NPT_TIMEOUT_INFINITE;
return NPT_SUCCESS;
}
return temp.SubString(7).ToInteger(len);
}
static NPT_Result GetIPAddresses(NPT_List<NPT_IpAddress>& ips,
bool with_localhost = false) {
NPT_List<NPT_NetworkInterface*> if_list;
NPT_CHECK(GetNetworkInterfaces(if_list, with_localhost));
NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
while (iface) {
NPT_IpAddress ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress();
if (ip.ToString().Compare("0.0.0.0") &&
(with_localhost || ip.ToString().Compare("127.0.0.1"))) {
ips.Add(ip);
}
++iface;
}
if (with_localhost && !ips.Find(NPT_IpAddressFinder(NPT_IpAddress(127, 0, 0, 1)))) {
NPT_IpAddress localhost;
localhost.Parse("127.0.0.1");
ips.Add(localhost);
}
if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
return NPT_SUCCESS;
}
static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
bool with_localhost = false) {
NPT_CHECK(_GetNetworkInterfaces(if_list, with_localhost, false));
if (if_list.GetItemCount() == 0) {
NPT_CHECK(_GetNetworkInterfaces(if_list, true, true));
}
return NPT_SUCCESS;
}
static NPT_Result GetMACAddresses(NPT_List<NPT_String>& addresses) {
NPT_List<NPT_NetworkInterface*> if_list;
NPT_CHECK(GetNetworkInterfaces(if_list));
NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
while (iface) {
NPT_String ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress().ToString();
if (ip.Compare("0.0.0.0") && ip.Compare("127.0.0.1")) {
addresses.Add((*iface)->GetMacAddress().ToString());
}
++iface;
}
if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
return NPT_SUCCESS;
}
static bool IsLocalNetworkAddress(const NPT_IpAddress& address) {
if (address.ToString() == "127.0.0.1") return true;
NPT_List<NPT_NetworkInterface*> if_list;
NPT_NetworkInterface::GetNetworkInterfaces(if_list);
NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
while (iface) {
if((*iface)->IsAddressInNetwork(address)) return true;
++iface;
}
if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
return false;
}
private:
static NPT_Result _GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
bool include_localhost = false,
bool only_localhost = false) {
NPT_List<NPT_NetworkInterface*> _if_list;
NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(_if_list));
NPT_NetworkInterface* iface;
while (NPT_SUCCEEDED(_if_list.PopHead(iface))) {
if ((iface->GetAddresses().GetItemCount() == 0) ||
!(iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) ||
(iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT)) {
delete iface;
continue;
}
NPT_String ip = iface->GetAddresses().GetFirstItem()->GetPrimaryAddress().ToString();
if (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
if (include_localhost || only_localhost) {
if_list.Add(iface);
continue;
}
} else if (ip.Compare("0.0.0.0") && !only_localhost) {
if_list.Add(iface);
continue;
}
delete iface;
}
_if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
return NPT_SUCCESS;
}
};
#endif