Platinum UPnP SDK  1.0.5.13
PltUtilities.h
1 /*****************************************************************
2 |
3 | Platinum - Utilities
4 |
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
8 |
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.
13 |
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
21 |
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.
26 |
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
32 |
33 ****************************************************************/
34 
35 #ifndef _PLT_UTILITIES_H_
36 #define _PLT_UTILITIES_H_
37 
38 /*----------------------------------------------------------------------
39 | includes
40 +---------------------------------------------------------------------*/
41 #include "Neptune.h"
42 
43 /*----------------------------------------------------------------------
44 | PLT_XmlAttributeFinder
45 +---------------------------------------------------------------------*/
51 {
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) {}
60 
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;
73  }
74  } else {
75  // ANY namespace will match
76  return true;
77  }
78  } else {
79  return false;
80  }
81  }
82 
83 private:
84  const NPT_XmlElementNode& m_Element;
85  const char* m_Name;
86  const char* m_Namespace;
87 };
88 
89 /*----------------------------------------------------------------------
90 | PLT_XmlHelper
91 +---------------------------------------------------------------------*/
97 {
98 public:
99 
100  // static methods
101 
102  static NPT_Result Parse(const NPT_String& xml, NPT_XmlElementNode*& tree) {
103  // reset tree
104  tree = NULL;
105 
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);
113  }
114 
115  tree = node->AsElementNode();
116  if (!tree) {
117  delete node;
118  return NPT_FAILURE;
119  }
120 
121  return NPT_SUCCESS;
122  }
123 
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 = "";
130 
131  if (!node) return NPT_FAILURE;
132 
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;
136  }
137 
138  NPT_XmlElementNode* child = node->GetChild(tag, namespc);
139  if (!child) return NPT_FAILURE;
140 
141  const NPT_String* text = child->GetText();
142  // DLNA 7.3.17
143  value = text?text->SubString(0, max_size):"";
144  return NPT_SUCCESS;
145  }
146 
147  static NPT_Result RemoveAttribute(NPT_XmlElementNode* node,
148  const char* name,
149  const char* namespc = "") {
150  if (!node) return NPT_FAILURE;
151 
152  // special case "" means we look for the same namespace as the parent
153  if (namespc && namespc[0] == '\0') {
154  namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
155  }
156 
157  NPT_List<NPT_XmlAttribute*>::Iterator attribute;
158  attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
159  if (!attribute) return NPT_FAILURE;
160 
161  delete *attribute;
162  NPT_CHECK(node->GetAttributes().Erase(attribute));
163 
164  return NPT_SUCCESS;
165  }
166 
167  static NPT_Result GetAttribute(NPT_XmlElementNode* node,
168  const char* name,
169  NPT_XmlAttribute*& attr,
170  const char* namespc = "") {
171  attr = NULL;
172 
173  if (!node) return NPT_FAILURE;
174 
175  // special case "" means we look for the same namespace as the parent
176  if (namespc && namespc[0] == '\0') {
177  namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
178  }
179 
180  NPT_List<NPT_XmlAttribute*>::Iterator attribute;
181  attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
182  if (!attribute) {
183  //NPT_Debug("Failed to find attribute [%s]:%s", namespc, name);
184  return NPT_FAILURE;
185  }
186 
187  attr = (*attribute);
188  return NPT_SUCCESS;
189  }
190 
191  static NPT_Result GetAttribute(NPT_XmlElementNode* node,
192  const char* name,
193  NPT_String& value,
194  const char* namespc = "",
195  NPT_Cardinal max_size = 1024) {
196  value = "";
197 
198  NPT_XmlAttribute* attribute = NULL;
199  NPT_Result result = GetAttribute(node, name, attribute, namespc);
200  if (NPT_FAILED(result)) return result;
201 
202  if (!attribute) return NPT_FAILURE;
203  // DLNA 7.3.17 truncate to 1024 bytes
204  value = attribute->GetValue().SubString(0, max_size);
205  return NPT_SUCCESS;
206  }
207 
208  static NPT_Result SetAttribute(NPT_XmlElementNode* node,
209  const char* name,
210  const char* value,
211  const char* namespc = "") {
212  NPT_XmlAttribute* attribute = NULL;
213  NPT_CHECK(GetAttribute(node, name, attribute, namespc));
214  if (!attribute) return NPT_FAILURE;
215 
216  attribute->SetValue(value);
217  return NPT_SUCCESS;
218  }
219 
220  static NPT_Result AddChildText(NPT_XmlElementNode* node,
221  const char* tag,
222  const char* text,
223  const char* prefix = NULL) {
224  if (!node) return NPT_FAILURE;
225  NPT_XmlElementNode* child = new NPT_XmlElementNode(prefix, tag);
226  child->AddText(text);
227  return node->AddChild(child);
228  }
229 
230  static bool IsMatch(const NPT_XmlNode* const & node, const char* tag, const char* namespc_mapped) {
231  // if m_Namespace is NULL, we're looking for ANY namespace
232  // if m_Namespace is '\0', we're looking for NO namespace
233  // if m_Namespace is non-empty, look for that SPECIFIC namespace
234 
235  const NPT_XmlElementNode* element = node->AsElementNode();
236  // is tag the same (case sensitive)?
237  if (element && element->GetTag() == tag) {
238  if (namespc_mapped) {
239  // look for a SPECIFIC namespace or NO namespace
240  const NPT_String* namespc = element->GetNamespace();
241  if (namespc) {
242  // the element has a namespace, match if it is equal to
243  // what we're looking for
244  return *namespc == namespc_mapped;
245  } else {
246  // the element does not have a namespace, match if we're
247  // looking for NO namespace
248  return namespc_mapped[0] == '\0';
249  }
250  } else {
251  // ANY namespace will match
252  return true;
253  }
254  }
255  return false;
256  }
257 
258  static NPT_Result GetChildren(NPT_XmlElementNode* node,
259  NPT_Array<NPT_XmlElementNode*>& children,
260  const char* tag,
261  const char* namespc = "") {
262  if (!node) return NPT_FAILURE;
263 
264  // special case "" means we look for the same namespace as the parent
265  if (namespc && namespc[0] == '\0') {
266  namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
267  }
268 
269  const char* namespc_mapped = (namespc==NULL)?"":(namespc[0]=='*' && namespc[1]=='\0')?NULL:namespc;
270 
271  // get all children first
272  NPT_List<NPT_XmlNode*>& allchildren = node->GetChildren();
273 
274  // iterate through children and add only elements with matching tag
275  NPT_List<NPT_XmlNode*>::Iterator child = allchildren.GetFirstItem();
276  while (child) {
277  if (IsMatch(*child, tag, namespc_mapped)) {
278  children.Add((*child)->AsElementNode());
279  }
280  ++child;
281  }
282  return NPT_SUCCESS;
283  }
284 
285  static NPT_XmlElementNode* GetChild(NPT_XmlElementNode* node,
286  const char* tag,
287  const char* namespc = "") {
288  if (!node) return NULL;
289 
290  // special case "" means we look for the same namespace as the parent
291  if (namespc && namespc[0] == '\0') {
292  namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
293  }
294 
295  return node->GetChild(tag, namespc);
296  }
297 
298  static NPT_Result GetChild(NPT_XmlElementNode* parent,
299  NPT_XmlElementNode*& child,
300  NPT_Ordinal n = 0) {
301  if (!parent) return NPT_FAILURE;
302 
303  // reset child
304  child = NULL;
305 
306  // get all children first
307  NPT_List<NPT_XmlNode*>::Iterator children = parent->GetChildren().GetFirstItem();
308  while (children) {
309  if ((*children)->AsElementNode() && n-- == 0) {
310  child = (*children)->AsElementNode();
311  return NPT_SUCCESS;
312  }
313  children++;
314  }
315 
316  return NPT_FAILURE;
317  }
318 
319  static NPT_Result Serialize(NPT_XmlNode& node, NPT_String& xml, bool add_header = true, NPT_Int8 indentation = 0) {
320  NPT_XmlWriter writer(indentation);
321  NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
322  NPT_CHECK(writer.Serialize(node, *stream, add_header));
323  return NPT_SUCCESS;
324  }
325 
326  static NPT_String Serialize(NPT_XmlNode& node, bool add_header = true, NPT_Int8 indentation = 0) {
327  NPT_XmlWriter writer(indentation);
328  NPT_String xml;
329  NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
330  if (NPT_FAILED(writer.Serialize(node, *stream, add_header))) {
331  NPT_Debug("Failed to serialize xml node");
332  return "";
333  }
334 
335  return xml;
336  }
337 private:
338  // members
339 };
340 
341 /*----------------------------------------------------------------------
342 | NPT_StringFinder
343 +---------------------------------------------------------------------*/
349 {
350 public:
351  // methods
352  explicit NPT_StringFinder(NPT_String& value, bool ignore_case = false) :
353  m_Value(value.GetChars()), m_IgnoreCase(ignore_case) {}
354 
355  explicit NPT_StringFinder(const char* value, bool ignore_case = false) :
356  m_Value(value), m_IgnoreCase(ignore_case) {}
357 
358  virtual ~NPT_StringFinder() {}
359 
360  bool operator()(const NPT_String* const & value) const {
361  return value->Compare(m_Value, m_IgnoreCase) ? false : true;
362  }
363  bool operator()(const NPT_String& value) const {
364  return value.Compare(m_Value, m_IgnoreCase) ? false : true;
365  }
366 
367 private:
368  // members
369  const char* m_Value;
370  bool m_IgnoreCase;
371 };
372 
373 /*----------------------------------------------------------------------
374 | NPT_IpAddressFinder
375 +---------------------------------------------------------------------*/
381 {
382 public:
383  // methods
384  NPT_IpAddressFinder(NPT_IpAddress ip) : m_Value(ip) {}
385  virtual ~NPT_IpAddressFinder() {}
386 
387  bool operator()(const NPT_IpAddress* const & value) const {
388  return *value == m_Value;
389  }
390  bool operator()(const NPT_IpAddress& value) const {
391  return value == m_Value;
392  }
393 
394 private:
395  // members
396  NPT_IpAddress m_Value;
397 };
398 
399 
400 /*----------------------------------------------------------------------
401 | PLT_UPnPMessageHelper class
402 +---------------------------------------------------------------------*/
408 {
409 public:
410  // methods
411  static const NPT_String* GetST(const NPT_HttpMessage& message) {
412  return message.GetHeaders().GetHeaderValue("ST");
413  }
414  static NPT_Result SetST(NPT_HttpMessage& message,
415  const char* st) {
416  return message.GetHeaders().SetHeader("ST", st);
417  }
418 
419  static const NPT_String* GetNT(const NPT_HttpMessage& message) {
420  return message.GetHeaders().GetHeaderValue("NT");
421  }
422  static NPT_Result SetNT(NPT_HttpMessage& message,
423  const char* nt) {
424  return message.GetHeaders().SetHeader("NT", nt);
425  }
426 
427  static const NPT_String* GetNTS(const NPT_HttpMessage& message) {
428  return message.GetHeaders().GetHeaderValue("NTS");
429  }
430  static NPT_Result SetNTS(NPT_HttpMessage& message,
431  const char* nts) {
432  return message.GetHeaders().SetHeader("NTS", nts);
433  }
434 
435  static const NPT_String* GetMAN(const NPT_HttpMessage& message) {
436  return message.GetHeaders().GetHeaderValue("MAN");
437  }
438  static NPT_Result SetMAN(NPT_HttpMessage& message,
439  const char* man) {
440  return message.GetHeaders().SetHeader("MAN", man);
441  }
442 
443  static const NPT_String* GetLocation(const NPT_HttpMessage& message) {
444  return message.GetHeaders().GetHeaderValue("Location");
445  }
446  static NPT_Result SetLocation(NPT_HttpMessage& message,
447  const char* location) {
448  return message.GetHeaders().SetHeader("Location", location);
449  }
450 
451  static const NPT_String* GetServer(const NPT_HttpMessage& message) {
452  return message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER);
453  }
454  static NPT_Result SetServer(NPT_HttpMessage& message,
455  const char* server,
456  bool replace = true) {
457  return message.GetHeaders().SetHeader(
458  NPT_HTTP_HEADER_SERVER,
459  server,
460  replace);
461  }
462 
463  static const NPT_String* GetUSN(const NPT_HttpMessage& message) {
464  return message.GetHeaders().GetHeaderValue("USN");
465  }
466  static NPT_Result SetUSN(NPT_HttpMessage& message,
467  const char* usn) {
468  return message.GetHeaders().SetHeader("USN", usn);
469  }
470 
471  static const NPT_String* GetCallbacks(const NPT_HttpMessage& message) {
472  return message.GetHeaders().GetHeaderValue("CALLBACK");
473  }
474  static NPT_Result SetCallbacks(NPT_HttpMessage& message, const char* callbacks) {
475  return message.GetHeaders().SetHeader("CALLBACK", callbacks);
476  }
477 
478  static const NPT_String* GetSID(const NPT_HttpMessage& message) {
479  return message.GetHeaders().GetHeaderValue("SID");
480  }
481  static NPT_Result SetSID(NPT_HttpMessage& message,
482  const char* sid) {
483  return message.GetHeaders().SetHeader("SID", sid);
484  }
485 
486  static NPT_Result GetLeaseTime(const NPT_HttpMessage& message, NPT_TimeInterval& lease) {
487  const NPT_String* cc =
488  message.GetHeaders().GetHeaderValue("Cache-Control");
489  NPT_CHECK_POINTER(cc);
490  return ExtractLeaseTime(*cc, lease);
491  }
492  static NPT_Result SetLeaseTime(NPT_HttpMessage& message, const NPT_TimeInterval& lease) {
493  return message.GetHeaders().SetHeader("Cache-Control",
494  "max-age="+NPT_String::FromInteger(lease.ToSeconds()));
495  }
496 
497  static NPT_Result GetBootId(const NPT_HttpMessage& message, NPT_UInt32& bootId) {
498  bootId = 0;
499  const NPT_String* bid = message.GetHeaders().GetHeaderValue("BOOTID.UPNP.ORG");
500  NPT_CHECK_POINTER(bid);
501  return NPT_ParseInteger32(*bid, bootId, false);
502  }
503  static NPT_Result SetBootId(NPT_HttpMessage& message, const NPT_UInt32& bootId) {
504  return message.GetHeaders().SetHeader("BOOTID.UPNP.ORG",
505  NPT_String::FromInteger(bootId));
506  }
507 
508  static NPT_Result GetNextBootId(const NPT_HttpMessage& message, NPT_UInt32& nextBootId) {
509  nextBootId = 0;
510  const NPT_String* nbid = message.GetHeaders().GetHeaderValue("NEXTBOOTID.UPNP.ORG");
511  NPT_CHECK_POINTER(nbid);
512  return NPT_ParseInteger32(*nbid, nextBootId, false);
513  }
514  static NPT_Result SetNextBootId(NPT_HttpMessage& message, const NPT_UInt32& nextBootId) {
515  return message.GetHeaders().SetHeader("NEXTBOOTID.UPNP.ORG",
516  NPT_String::FromInteger(nextBootId));
517  }
518 
519  static NPT_Result GetConfigId(const NPT_HttpMessage& message, NPT_UInt32& configId) {
520  configId = 0;
521  const NPT_String* cid = message.GetHeaders().GetHeaderValue("CONFIGID.UPNP.ORG");
522  NPT_CHECK_POINTER(cid);
523  return NPT_ParseInteger32(*cid, configId, false);
524  }
525  static NPT_Result SetConfigId(NPT_HttpMessage& message, const NPT_UInt32& configId) {
526  return message.GetHeaders().SetHeader("CONFIGID.UPNP.ORG", NPT_String::FromInteger(configId));
527  }
528 
529  static NPT_Result GetTimeOut(const NPT_HttpMessage& message, NPT_Int32& seconds) {
530  seconds = 0;
531  const NPT_String* timeout =
532  message.GetHeaders().GetHeaderValue("TIMEOUT");
533  NPT_CHECK_POINTER(timeout);
534  return ExtractTimeOut(*timeout, seconds);
535  }
536  static NPT_Result SetTimeOut(NPT_HttpMessage& message, const NPT_Int32 seconds) {
537  if (seconds >= 0) {
538  return message.GetHeaders().SetHeader("TIMEOUT", "Second-"+NPT_String::FromInteger(seconds));
539  } else {
540  return message.GetHeaders().SetHeader("TIMEOUT", "Second-infinite");
541  }
542  }
543 
544  static NPT_Result SetDate(NPT_HttpMessage& message) {
545  NPT_TimeStamp now;
546  NPT_System::GetCurrentTimeStamp(now);
547  NPT_DateTime date(now);
548 
549  return message.GetHeaders().SetHeader("Date", date.ToString(NPT_DateTime::FORMAT_RFC_1123));
550  }
551 
552  static NPT_Result GetIfModifiedSince(const NPT_HttpMessage& message, NPT_DateTime& date) {
553  const NPT_String* value = message.GetHeaders().GetHeaderValue("If-Modified-Since");
554  if (!value) return NPT_FAILURE;
555 
556  // Try RFC 1123, RFC 1036, then ANSI
557  if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1123)))
558  return NPT_SUCCESS;
559 
560  if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1036)))
561  return NPT_SUCCESS;
562 
563  return date.FromString(*value, NPT_DateTime::FORMAT_ANSI);
564  }
565  static NPT_Result SetIfModifiedSince(NPT_HttpMessage& message, const NPT_DateTime& date) {
566  return message.GetHeaders().SetHeader("If-Modified-Since",
567  date.ToString(NPT_DateTime::FORMAT_RFC_1123));
568  }
569 
570  static NPT_Result GetMX(const NPT_HttpMessage& message, NPT_UInt32& value) {
571  value = 0;
572  const NPT_String* mx =
573  message.GetHeaders().GetHeaderValue("MX");
574  NPT_CHECK_POINTER(mx);
575  return NPT_ParseInteger32(*mx, value, false); // no relax to be UPnP compliant
576  }
577  static NPT_Result SetMX(NPT_HttpMessage& message, const NPT_UInt32 mx) {
578  return message.GetHeaders().SetHeader("MX",
579  NPT_String::FromInteger(mx));
580  }
581 
582  static NPT_Result GetSeq(const NPT_HttpMessage& message, NPT_UInt32& value) {
583  value = 0;
584  const NPT_String* seq =
585  message.GetHeaders().GetHeaderValue("SEQ");
586  NPT_CHECK_POINTER(seq);
587  return NPT_ParseInteger32(*seq, value);
588  }
589  static NPT_Result SetSeq(NPT_HttpMessage& message, const NPT_UInt32 seq) {
590  return message.GetHeaders().SetHeader("SEQ",
591  NPT_String::FromInteger(seq));
592  }
593 
594  static const char* GenerateUUID(int count, NPT_String& uuid) {
595  uuid = "";
596  for (int i=0;i<(count<100?count:100);i++) {
597  int random = NPT_System::GetRandomInteger();
598  uuid += (char)((random % 25) + 66);
599  }
600  return uuid;
601  }
602 
603  static const char* GenerateSerialNumber(NPT_String& sn, int count = 40) {
604  sn = "{";
605  for (int i=0;i<count;i++) {
606  char nibble = (char)(NPT_System::GetRandomInteger() % 16);
607  sn += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
608  }
609  sn += "}";
610  return sn;
611  }
612 
613  static const char* GenerateGUID(NPT_String& guid) {
614  guid = "";
615  for (int i=0;i<32;i++) {
616  char nibble = (char)(NPT_System::GetRandomInteger() % 16);
617  guid += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
618  if (i == 7 || i == 11 || i == 15 || i == 19) {
619  guid += '-';
620  }
621  }
622  return guid;
623  }
624 
625  static NPT_Result ExtractLeaseTime(const NPT_String& cache_control, NPT_TimeInterval& lease) {
626  NPT_Int32 value;
627  if (cache_control.StartsWith("max-age=", true) &&
628  NPT_SUCCEEDED(NPT_ParseInteger32(cache_control.GetChars()+8, value))) {
629  lease.SetSeconds(value);
630  return NPT_SUCCESS;
631  }
632  return NPT_FAILURE;
633  }
634 
635  static NPT_Result ExtractTimeOut(const char* timeout, NPT_Int32& len) {
636  NPT_String temp = timeout;
637  if (temp.CompareN("Second-", 7, true)) {
638  return NPT_ERROR_INVALID_FORMAT;
639  }
640 
641  if (temp.Compare("Second-infinite", true) == 0) {
642  len = NPT_TIMEOUT_INFINITE;
643  return NPT_SUCCESS;
644  }
645  return temp.SubString(7).ToInteger(len);
646  }
647 
648  static NPT_Result GetIPAddresses(NPT_List<NPT_IpAddress>& ips, bool with_localhost = false) {
649  NPT_List<NPT_NetworkInterface*> if_list;
650  NPT_CHECK(GetNetworkInterfaces(if_list, with_localhost));
651 
652  NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
653  while (iface) {
654  NPT_IpAddress ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress();
655  if (ip.ToString().Compare("0.0.0.0") &&
656  (with_localhost || ip.ToString().Compare("127.0.0.1"))) {
657  ips.Add(ip);
658  }
659  ++iface;
660  }
661 
662  if (with_localhost && !ips.Find(NPT_IpAddressFinder(NPT_IpAddress(127, 0, 0, 1)))) {
663  NPT_IpAddress localhost;
664  localhost.Parse("127.0.0.1");
665  ips.Add(localhost);
666  }
667 
668  if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
669  return NPT_SUCCESS;
670  }
671 
672  static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
673  bool with_localhost = false) {
674  NPT_CHECK(_GetNetworkInterfaces(if_list, with_localhost, false));
675 
676  // if no valid interfaces or if requested, add localhost interface
677  if (if_list.GetItemCount() == 0) {
678  NPT_CHECK(_GetNetworkInterfaces(if_list, true, true));
679  }
680  return NPT_SUCCESS;
681  }
682 
683  static NPT_Result GetMACAddresses(NPT_List<NPT_String>& addresses) {
684  NPT_List<NPT_NetworkInterface*> if_list;
685  NPT_CHECK(GetNetworkInterfaces(if_list));
686 
687  NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
688  while (iface) {
689  NPT_String ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress().ToString();
690  if (ip.Compare("0.0.0.0") && ip.Compare("127.0.0.1")) {
691  addresses.Add((*iface)->GetMacAddress().ToString());
692  }
693  ++iface;
694  }
695 
696  if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
697  return NPT_SUCCESS;
698  }
699 
700 
701  static bool IsLocalNetworkAddress(const NPT_IpAddress& address) {
702  if (address.ToString() == "127.0.0.1") return true;
703 
704  NPT_List<NPT_NetworkInterface*> if_list;
705  NPT_NetworkInterface::GetNetworkInterfaces(if_list);
706 
707  NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
708  while (iface) {
709  if((*iface)->IsAddressInNetwork(address)) return true;
710  ++iface;
711  }
712 
713  if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
714  return false;
715  }
716 
717 private:
718 
719  static NPT_Result _GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
720  bool include_localhost = false,
721  bool only_localhost = false) {
722  NPT_List<NPT_NetworkInterface*> _if_list;
723  NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(_if_list));
724 
725  NPT_NetworkInterface* iface;
726  while (NPT_SUCCEEDED(_if_list.PopHead(iface))) {
727  // only interested in non PTP & multicast capable interfaces
728  if ((iface->GetAddresses().GetItemCount() == 0) ||
729  !(iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) ||
730  (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT)) {
731  delete iface;
732  continue;
733  }
734 
735  NPT_String ip = iface->GetAddresses().GetFirstItem()->GetPrimaryAddress().ToString();
736 
737  if (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
738  if (include_localhost || only_localhost) {
739  if_list.Add(iface);
740  continue;
741  }
742  } else if (ip.Compare("0.0.0.0") && !only_localhost) {
743  if_list.Add(iface);
744  continue;
745  }
746 
747  delete iface;
748  }
749 
750  // cleanup any remaining items in list if we breaked early
751  _if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
752  return NPT_SUCCESS;
753  }
754 };
755 
756 #endif // _PLT_UTILITIES_H_
757 
758 
759 
760 
761 
762 
763 
764 
765 
The PLT_XmlAttributeFinder class is used to determine if an attribute exists given an xml element nod...
Definition: PltUtilities.h:50
The NPT_IpAddressFinder class is used to determine if a IP Address is found as part of a list of IP A...
Definition: PltUtilities.h:380
The PLT_XmlHelper class is a set of utility functions for manipulating xml documents and DOM trees...
Definition: PltUtilities.h:96
The NPT_StringFinder class is used to determine if a string is found as part of a list of strings...
Definition: PltUtilities.h:348
The PLT_UPnPMessageHelper class is a set of utility functions for manipulating specific UPnP HTTP hea...
Definition: PltUtilities.h:407