Merge pull request #25959 from neo1973/TagLib_deprecation_warnings
[xbmc.git] / lib / libUPnP / Platinum / Source / Core / PltUtilities.h
blob4677f5be0ec7ed4b0fd549b5765509d31486510d
1 /*****************************************************************
3 | Platinum - Utilities
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 | licensing@plutinosoft.com
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
33 ****************************************************************/
35 #ifndef _PLT_UTILITIES_H_
36 #define _PLT_UTILITIES_H_
38 /*----------------------------------------------------------------------
39 | includes
40 +---------------------------------------------------------------------*/
41 #include "Neptune.h"
43 /*----------------------------------------------------------------------
44 | PLT_XmlAttributeFinder
45 +---------------------------------------------------------------------*/
46 /**
47 The PLT_XmlAttributeFinder class is used to determine if an attribute
48 exists given an xml element node, an attribute name and namespace.
50 class PLT_XmlAttributeFinder
52 public:
53 // if 'namespc' is NULL, we're looking for ANY namespace
54 // if 'namespc' is '\0', we're looking for NO namespace
55 // if 'namespc' is non-empty, look for that SPECIFIC namespace
56 PLT_XmlAttributeFinder(const NPT_XmlElementNode& element,
57 const char* name,
58 const char* namespc) :
59 m_Element(element), m_Name(name), m_Namespace(namespc) {}
61 bool operator()(const NPT_XmlAttribute* const & attribute) const {
62 if (attribute->GetName() == m_Name) {
63 if (m_Namespace) {
64 const NPT_String& prefix = attribute->GetPrefix();
65 if (m_Namespace[0] == '\0') {
66 // match if the attribute has NO namespace
67 return prefix.IsEmpty();
68 } else {
69 // match if the attribute has the SPECIFIC namespace
70 // we're looking for
71 const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
72 return namespc && *namespc == m_Namespace;
74 } else {
75 // ANY namespace will match
76 return true;
78 } else {
79 return false;
83 private:
84 const NPT_XmlElementNode& m_Element;
85 const char* m_Name;
86 const char* m_Namespace;
89 /*----------------------------------------------------------------------
90 | PLT_XmlHelper
91 +---------------------------------------------------------------------*/
92 /**
93 The PLT_XmlHelper class is a set of utility functions for manipulating
94 xml documents and DOM trees.
96 class PLT_XmlHelper
98 public:
100 // static methods
102 static NPT_Result Parse(const NPT_String& xml, NPT_XmlElementNode*& tree) {
103 // reset tree
104 tree = NULL;
106 // parse body
107 NPT_XmlParser parser;
108 NPT_XmlNode* node;
109 NPT_Result result = parser.Parse(xml, node);
110 if (NPT_FAILED(result)) {
111 //NPT_LOG_FINEST_1("Failed to parse %s", xml.IsEmpty()?"(empty string)":xml.GetChars());
112 NPT_CHECK(result);
115 tree = node->AsElementNode();
116 if (!tree) {
117 delete node;
118 return NPT_FAILURE;
121 return NPT_SUCCESS;
124 static NPT_Result GetChildText(NPT_XmlElementNode* node,
125 const char* tag,
126 NPT_String& value,
127 const char* namespc = "",
128 NPT_Cardinal max_size = 1024) {
129 value = "";
131 if (!node) return NPT_FAILURE;
133 // special case "" means we look for the same namespace as the parent
134 if (namespc && namespc[0] == '\0') {
135 namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
138 NPT_XmlElementNode* child = node->GetChild(tag, namespc);
139 if (!child) return NPT_FAILURE;
141 const NPT_String* text = child->GetText();
142 // DLNA 7.3.17
143 if (text)
144 value = text->SubString(0, max_size);
145 return NPT_SUCCESS;
148 static NPT_Result RemoveAttribute(NPT_XmlElementNode* node,
149 const char* name,
150 const char* namespc = "") {
151 if (!node) return NPT_FAILURE;
153 // special case "" means we look for the same namespace as the parent
154 if (namespc && namespc[0] == '\0') {
155 namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
158 NPT_List<NPT_XmlAttribute*>::Iterator attribute;
159 attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
160 if (!attribute) return NPT_FAILURE;
162 delete *attribute;
163 NPT_CHECK(node->GetAttributes().Erase(attribute));
165 return NPT_SUCCESS;
168 static NPT_Result GetAttribute(NPT_XmlElementNode* node,
169 const char* name,
170 NPT_XmlAttribute*& attr,
171 const char* namespc = "") {
172 attr = NULL;
174 if (!node) return NPT_FAILURE;
176 // special case "" means we look for the same namespace as the parent
177 if (namespc && namespc[0] == '\0') {
178 namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
181 NPT_List<NPT_XmlAttribute*>::Iterator attribute;
182 attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
183 if (!attribute) {
184 //NPT_Debug("Failed to find attribute [%s]:%s", namespc, name);
185 return NPT_FAILURE;
188 attr = (*attribute);
189 return NPT_SUCCESS;
192 static NPT_Result GetAttribute(NPT_XmlElementNode* node,
193 const char* name,
194 NPT_String& value,
195 const char* namespc = "",
196 NPT_Cardinal max_size = 1024) {
197 value = "";
199 NPT_XmlAttribute* attribute = NULL;
200 NPT_Result result = GetAttribute(node, name, attribute, namespc);
201 if (NPT_FAILED(result)) return result;
203 if (!attribute) return NPT_FAILURE;
204 // DLNA 7.3.17 truncate to 1024 bytes
205 value = attribute->GetValue().SubString(0, max_size);
206 return NPT_SUCCESS;
209 static NPT_Result SetAttribute(NPT_XmlElementNode* node,
210 const char* name,
211 const char* value,
212 const char* namespc = "") {
213 NPT_XmlAttribute* attribute = NULL;
214 NPT_CHECK(GetAttribute(node, name, attribute, namespc));
215 if (!attribute) return NPT_FAILURE;
217 attribute->SetValue(value);
218 return NPT_SUCCESS;
221 static NPT_Result AddChildText(NPT_XmlElementNode* node,
222 const char* tag,
223 const char* text,
224 const char* prefix = NULL) {
225 if (!node) return NPT_FAILURE;
226 NPT_XmlElementNode* child = new NPT_XmlElementNode(prefix, tag);
227 child->AddText(text);
228 return node->AddChild(child);
231 static bool IsMatch(const NPT_XmlNode* const & node, const char* tag, const char* namespc_mapped) {
232 // if m_Namespace is NULL, we're looking for ANY namespace
233 // if m_Namespace is '\0', we're looking for NO namespace
234 // if m_Namespace is non-empty, look for that SPECIFIC namespace
236 const NPT_XmlElementNode* element = node->AsElementNode();
237 // is tag the same (case sensitive)?
238 if (element && element->GetTag() == tag) {
239 if (namespc_mapped) {
240 // look for a SPECIFIC namespace or NO namespace
241 const NPT_String* namespc = element->GetNamespace();
242 if (namespc) {
243 // the element has a namespace, match if it is equal to
244 // what we're looking for
245 return *namespc == namespc_mapped;
246 } else {
247 // the element does not have a namespace, match if we're
248 // looking for NO namespace
249 return namespc_mapped[0] == '\0';
251 } else {
252 // ANY namespace will match
253 return true;
256 return false;
259 static NPT_Result GetChildren(NPT_XmlElementNode* node,
260 NPT_Array<NPT_XmlElementNode*>& children,
261 const char* tag,
262 const char* namespc = "") {
263 if (!node) return NPT_FAILURE;
265 // special case "" means we look for the same namespace as the parent
266 if (namespc && namespc[0] == '\0') {
267 namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
270 const char* namespc_mapped = (namespc==NULL)?"":(namespc[0]=='*' && namespc[1]=='\0')?NULL:namespc;
272 // get all children first
273 NPT_List<NPT_XmlNode*>& allchildren = node->GetChildren();
275 // iterate through children and add only elements with matching tag
276 NPT_List<NPT_XmlNode*>::Iterator child = allchildren.GetFirstItem();
277 while (child) {
278 if (IsMatch(*child, tag, namespc_mapped)) {
279 children.Add((*child)->AsElementNode());
281 ++child;
283 return NPT_SUCCESS;
286 static NPT_XmlElementNode* GetChild(NPT_XmlElementNode* node,
287 const char* tag,
288 const char* namespc = "") {
289 if (!node) return NULL;
291 // special case "" means we look for the same namespace as the parent
292 if (namespc && namespc[0] == '\0') {
293 namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
296 return node->GetChild(tag, namespc);
299 static NPT_Result GetChild(NPT_XmlElementNode* parent,
300 NPT_XmlElementNode*& child,
301 NPT_Ordinal n = 0) {
302 if (!parent) return NPT_FAILURE;
304 // reset child
305 child = NULL;
307 // get all children first
308 NPT_List<NPT_XmlNode*>::Iterator children = parent->GetChildren().GetFirstItem();
309 while (children) {
310 if ((*children)->AsElementNode() && n-- == 0) {
311 child = (*children)->AsElementNode();
312 return NPT_SUCCESS;
314 children++;
317 return NPT_FAILURE;
320 static NPT_Result Serialize(NPT_XmlNode& node, NPT_String& xml, bool add_header = true, NPT_Int8 indentation = 0) {
321 NPT_XmlWriter writer(indentation);
322 NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
323 NPT_CHECK(writer.Serialize(node, *stream, add_header));
324 return NPT_SUCCESS;
327 static NPT_String Serialize(NPT_XmlNode& node, bool add_header = true, NPT_Int8 indentation = 0) {
328 NPT_XmlWriter writer(indentation);
329 NPT_String xml;
330 NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
331 if (NPT_FAILED(writer.Serialize(node, *stream, add_header))) {
332 NPT_Debug("Failed to serialize xml node");
333 return "";
336 return xml;
338 private:
339 // members
342 /*----------------------------------------------------------------------
343 | NPT_StringFinder
344 +---------------------------------------------------------------------*/
346 The NPT_StringFinder class is used to determine if a string is found
347 as part of a list of strings.
349 class NPT_StringFinder
351 public:
352 // methods
353 explicit NPT_StringFinder(NPT_String& value, bool ignore_case = false) :
354 m_Value(value.GetChars()), m_IgnoreCase(ignore_case) {}
356 explicit NPT_StringFinder(const char* value, bool ignore_case = false) :
357 m_Value(value), m_IgnoreCase(ignore_case) {}
359 virtual ~NPT_StringFinder() {}
361 bool operator()(const NPT_String* const & value) const {
362 return value->Compare(m_Value, m_IgnoreCase) ? false : true;
364 bool operator()(const NPT_String& value) const {
365 return value.Compare(m_Value, m_IgnoreCase) ? false : true;
368 private:
369 // members
370 const char* m_Value;
371 bool m_IgnoreCase;
374 /*----------------------------------------------------------------------
375 | NPT_IpAddressFinder
376 +---------------------------------------------------------------------*/
378 The NPT_IpAddressFinder class is used to determine if a IP Address is found
379 as part of a list of IP Addresses.
381 class NPT_IpAddressFinder
383 public:
384 // methods
385 NPT_IpAddressFinder(NPT_IpAddress ip) : m_Value(ip) {}
386 virtual ~NPT_IpAddressFinder() {}
388 bool operator()(const NPT_IpAddress* const & value) const {
389 return *value == m_Value;
391 bool operator()(const NPT_IpAddress& value) const {
392 return value == m_Value;
395 private:
396 // members
397 NPT_IpAddress m_Value;
401 /*----------------------------------------------------------------------
402 | PLT_UPnPMessageHelper class
403 +---------------------------------------------------------------------*/
405 The PLT_UPnPMessageHelper class is a set of utility functions for manipulating
406 specific UPnP HTTP headers.
408 class PLT_UPnPMessageHelper
410 public:
411 // methods
412 static const NPT_String* GetST(const NPT_HttpMessage& message) {
413 return message.GetHeaders().GetHeaderValue("ST");
415 static NPT_Result SetST(NPT_HttpMessage& message,
416 const char* st) {
417 return message.GetHeaders().SetHeader("ST", st);
420 static const NPT_String* GetNT(const NPT_HttpMessage& message) {
421 return message.GetHeaders().GetHeaderValue("NT");
423 static NPT_Result SetNT(NPT_HttpMessage& message,
424 const char* nt) {
425 return message.GetHeaders().SetHeader("NT", nt);
428 static const NPT_String* GetNTS(const NPT_HttpMessage& message) {
429 return message.GetHeaders().GetHeaderValue("NTS");
431 static NPT_Result SetNTS(NPT_HttpMessage& message,
432 const char* nts) {
433 return message.GetHeaders().SetHeader("NTS", nts);
436 static const NPT_String* GetMAN(const NPT_HttpMessage& message) {
437 return message.GetHeaders().GetHeaderValue("MAN");
439 static NPT_Result SetMAN(NPT_HttpMessage& message,
440 const char* man) {
441 return message.GetHeaders().SetHeader("MAN", man);
444 static const NPT_String* GetLocation(const NPT_HttpMessage& message) {
445 return message.GetHeaders().GetHeaderValue("Location");
447 static NPT_Result SetLocation(NPT_HttpMessage& message,
448 const char* location) {
449 return message.GetHeaders().SetHeader("Location", location);
452 static const NPT_String* GetServer(const NPT_HttpMessage& message) {
453 return message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER);
455 static NPT_Result SetServer(NPT_HttpMessage& message,
456 const char* server,
457 bool replace = true) {
458 return message.GetHeaders().SetHeader(
459 NPT_HTTP_HEADER_SERVER,
460 server,
461 replace);
464 static const NPT_String* GetUSN(const NPT_HttpMessage& message) {
465 return message.GetHeaders().GetHeaderValue("USN");
467 static NPT_Result SetUSN(NPT_HttpMessage& message,
468 const char* usn) {
469 return message.GetHeaders().SetHeader("USN", usn);
472 static const NPT_String* GetCallbacks(const NPT_HttpMessage& message) {
473 return message.GetHeaders().GetHeaderValue("CALLBACK");
475 static NPT_Result SetCallbacks(NPT_HttpMessage& message, const char* callbacks) {
476 return message.GetHeaders().SetHeader("CALLBACK", callbacks);
479 static const NPT_String* GetSID(const NPT_HttpMessage& message) {
480 return message.GetHeaders().GetHeaderValue("SID");
482 static NPT_Result SetSID(NPT_HttpMessage& message,
483 const char* sid) {
484 return message.GetHeaders().SetHeader("SID", sid);
487 static NPT_Result GetLeaseTime(const NPT_HttpMessage& message, NPT_TimeInterval& lease) {
488 const NPT_String* cc =
489 message.GetHeaders().GetHeaderValue("Cache-Control");
490 NPT_CHECK_POINTER(cc);
491 return ExtractLeaseTime(*cc, lease);
493 static NPT_Result SetLeaseTime(NPT_HttpMessage& message, const NPT_TimeInterval& lease) {
494 return message.GetHeaders().SetHeader("Cache-Control",
495 "max-age="+NPT_String::FromInteger(lease.ToSeconds()));
498 static NPT_Result GetBootId(const NPT_HttpMessage& message, NPT_UInt32& bootId) {
499 bootId = 0;
500 const NPT_String* bid = message.GetHeaders().GetHeaderValue("BOOTID.UPNP.ORG");
501 NPT_CHECK_POINTER(bid);
502 return NPT_ParseInteger32(*bid, bootId, false);
504 static NPT_Result SetBootId(NPT_HttpMessage& message, const NPT_UInt32& bootId) {
505 return message.GetHeaders().SetHeader("BOOTID.UPNP.ORG",
506 NPT_String::FromInteger(bootId));
509 static NPT_Result GetNextBootId(const NPT_HttpMessage& message, NPT_UInt32& nextBootId) {
510 nextBootId = 0;
511 const NPT_String* nbid = message.GetHeaders().GetHeaderValue("NEXTBOOTID.UPNP.ORG");
512 NPT_CHECK_POINTER(nbid);
513 return NPT_ParseInteger32(*nbid, nextBootId, false);
515 static NPT_Result SetNextBootId(NPT_HttpMessage& message, const NPT_UInt32& nextBootId) {
516 return message.GetHeaders().SetHeader("NEXTBOOTID.UPNP.ORG",
517 NPT_String::FromInteger(nextBootId));
520 static NPT_Result GetConfigId(const NPT_HttpMessage& message, NPT_UInt32& configId) {
521 configId = 0;
522 const NPT_String* cid = message.GetHeaders().GetHeaderValue("CONFIGID.UPNP.ORG");
523 NPT_CHECK_POINTER(cid);
524 return NPT_ParseInteger32(*cid, configId, false);
526 static NPT_Result SetConfigId(NPT_HttpMessage& message, const NPT_UInt32& configId) {
527 return message.GetHeaders().SetHeader("CONFIGID.UPNP.ORG", NPT_String::FromInteger(configId));
530 static NPT_Result GetTimeOut(const NPT_HttpMessage& message, NPT_Int32& seconds) {
531 seconds = 0;
532 const NPT_String* timeout =
533 message.GetHeaders().GetHeaderValue("TIMEOUT");
534 NPT_CHECK_POINTER(timeout);
535 return ExtractTimeOut(*timeout, seconds);
537 static NPT_Result SetTimeOut(NPT_HttpMessage& message, const NPT_Int32 seconds) {
538 if (seconds >= 0) {
539 return message.GetHeaders().SetHeader("TIMEOUT", "Second-"+NPT_String::FromInteger(seconds));
540 } else {
541 return message.GetHeaders().SetHeader("TIMEOUT", "Second-infinite");
545 static NPT_Result SetDate(NPT_HttpMessage& message) {
546 NPT_TimeStamp now;
547 NPT_System::GetCurrentTimeStamp(now);
548 NPT_DateTime date(now);
550 return message.GetHeaders().SetHeader("Date", date.ToString(NPT_DateTime::FORMAT_RFC_1123));
553 static NPT_Result GetIfModifiedSince(const NPT_HttpMessage& message, NPT_DateTime& date) {
554 const NPT_String* value = message.GetHeaders().GetHeaderValue("If-Modified-Since");
555 if (!value) return NPT_FAILURE;
557 // Try RFC 1123, RFC 1036, then ANSI
558 if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1123)))
559 return NPT_SUCCESS;
561 if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1036)))
562 return NPT_SUCCESS;
564 return date.FromString(*value, NPT_DateTime::FORMAT_ANSI);
566 static NPT_Result SetIfModifiedSince(NPT_HttpMessage& message, const NPT_DateTime& date) {
567 return message.GetHeaders().SetHeader("If-Modified-Since",
568 date.ToString(NPT_DateTime::FORMAT_RFC_1123));
571 static NPT_Result GetMX(const NPT_HttpMessage& message, NPT_UInt32& value) {
572 value = 0;
573 const NPT_String* mx =
574 message.GetHeaders().GetHeaderValue("MX");
575 NPT_CHECK_POINTER(mx);
576 return NPT_ParseInteger32(*mx, value, false); // no relax to be UPnP compliant
578 static NPT_Result SetMX(NPT_HttpMessage& message, const NPT_UInt32 mx) {
579 return message.GetHeaders().SetHeader("MX",
580 NPT_String::FromInteger(mx));
583 static NPT_Result GetSeq(const NPT_HttpMessage& message, NPT_UInt32& value) {
584 value = 0;
585 const NPT_String* seq =
586 message.GetHeaders().GetHeaderValue("SEQ");
587 NPT_CHECK_POINTER(seq);
588 return NPT_ParseInteger32(*seq, value);
590 static NPT_Result SetSeq(NPT_HttpMessage& message, const NPT_UInt32 seq) {
591 return message.GetHeaders().SetHeader("SEQ",
592 NPT_String::FromInteger(seq));
595 static const char* GenerateUUID(int count, NPT_String& uuid) {
596 uuid = "";
597 for (int i=0;i<(count<100?count:100);i++) {
598 int random = NPT_System::GetRandomInteger();
599 uuid += (char)((random % 25) + 66);
601 return uuid;
604 static const char* GenerateSerialNumber(NPT_String& sn, int count = 40) {
605 sn = "{";
606 for (int i=0;i<count;i++) {
607 char nibble = (char)(NPT_System::GetRandomInteger() % 16);
608 sn += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
610 sn += "}";
611 return sn;
614 static const char* GenerateGUID(NPT_String& guid) {
615 guid = "";
616 for (int i=0;i<32;i++) {
617 char nibble = (char)(NPT_System::GetRandomInteger() % 16);
618 guid += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
619 if (i == 7 || i == 11 || i == 15 || i == 19) {
620 guid += '-';
623 return guid;
626 static NPT_Result ExtractLeaseTime(const NPT_String& cache_control, NPT_TimeInterval& lease) {
627 NPT_Int32 value;
628 if (cache_control.StartsWith("max-age=", true) &&
629 NPT_SUCCEEDED(NPT_ParseInteger32(cache_control.GetChars()+8, value))) {
630 lease.SetSeconds(value);
631 return NPT_SUCCESS;
633 return NPT_FAILURE;
636 static NPT_Result ExtractTimeOut(const char* timeout, NPT_Int32& len) {
637 NPT_String temp = timeout;
638 if (temp.CompareN("Second-", 7, true)) {
639 return NPT_ERROR_INVALID_FORMAT;
642 if (temp.Compare("Second-infinite", true) == 0) {
643 len = NPT_TIMEOUT_INFINITE;
644 return NPT_SUCCESS;
646 return temp.SubString(7).ToInteger(len);
649 static NPT_Result GetIPAddresses(NPT_List<NPT_IpAddress>& ips, bool with_localhost = false) {
650 NPT_List<NPT_NetworkInterface*> if_list;
651 NPT_CHECK(GetNetworkInterfaces(if_list, with_localhost));
653 NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
654 while (iface) {
655 NPT_IpAddress ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress();
656 if (ip.ToString().Compare("0.0.0.0") &&
657 (with_localhost || ip.ToString().Compare("127.0.0.1"))) {
658 ips.Add(ip);
660 ++iface;
663 if (with_localhost && !ips.Find(NPT_IpAddressFinder(NPT_IpAddress(127, 0, 0, 1)))) {
664 NPT_IpAddress localhost;
665 localhost.Parse("127.0.0.1");
666 ips.Add(localhost);
669 if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
670 return NPT_SUCCESS;
673 static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
674 bool with_localhost = false) {
675 NPT_CHECK(_GetNetworkInterfaces(if_list, with_localhost, false));
677 // if no valid interfaces or if requested, add localhost interface
678 if (if_list.GetItemCount() == 0) {
679 NPT_CHECK(_GetNetworkInterfaces(if_list, true, true));
681 return NPT_SUCCESS;
684 static NPT_Result GetMACAddresses(NPT_List<NPT_String>& addresses) {
685 NPT_List<NPT_NetworkInterface*> if_list;
686 NPT_CHECK(GetNetworkInterfaces(if_list));
688 NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
689 while (iface) {
690 NPT_String ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress().ToString();
691 if (ip.Compare("0.0.0.0") && ip.Compare("127.0.0.1")) {
692 addresses.Add((*iface)->GetMacAddress().ToString());
694 ++iface;
697 if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
698 return NPT_SUCCESS;
702 static bool IsLocalNetworkAddress(const NPT_IpAddress& address) {
703 if (address.ToString() == "127.0.0.1") return true;
705 NPT_List<NPT_NetworkInterface*> if_list;
706 NPT_NetworkInterface::GetNetworkInterfaces(if_list);
708 NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
709 while (iface) {
710 if((*iface)->IsAddressInNetwork(address)) return true;
711 ++iface;
714 if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
715 return false;
718 private:
720 static NPT_Result _GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
721 bool include_localhost = false,
722 bool only_localhost = false) {
723 NPT_List<NPT_NetworkInterface*> _if_list;
724 NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(_if_list));
726 NPT_NetworkInterface* iface;
727 while (NPT_SUCCEEDED(_if_list.PopHead(iface))) {
728 // only interested in non PTP & multicast capable interfaces
729 if ((iface->GetAddresses().GetItemCount() == 0) ||
730 !(iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) ||
731 (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT)) {
732 delete iface;
733 continue;
736 NPT_String ip = iface->GetAddresses().GetFirstItem()->GetPrimaryAddress().ToString();
738 if (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
739 if (include_localhost || only_localhost) {
740 if_list.Add(iface);
741 continue;
743 } else if (ip.Compare("0.0.0.0") && !only_localhost) {
744 if_list.Add(iface);
745 continue;
748 delete iface;
751 // cleanup any remaining items in list if we breaked early
752 _if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
753 return NPT_SUCCESS;
757 #endif // _PLT_UTILITIES_H_