summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Neptune/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Neptune/Source/Core')
-rw-r--r--lib/libUPnP/Neptune/Source/Core/Neptune.cpp0
-rw-r--r--lib/libUPnP/Neptune/Source/Core/Neptune.h86
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptArray.h522
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.cpp101
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.h74
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptAutoreleasePool.h57
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptBase64.cpp194
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptBase64.h68
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.cpp471
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.h102
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptCommon.cpp38
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptCommon.h169
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptConfig.h381
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptConsole.cpp67
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptConsole.h55
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptConstants.h44
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptCrypto.cpp833
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptCrypto.h78
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDataBuffer.cpp256
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDataBuffer.h83
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDebug.cpp83
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDebug.h56
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDefs.h0
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDigest.cpp685
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDigest.h78
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDynamicCast.h89
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.cpp36
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.h84
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptFile.cpp409
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptFile.h229
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptHash.cpp137
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptHash.h83
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptHttp.cpp3483
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptHttp.h866
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptInterfaces.h115
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptJson.cpp37
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptJson.h42
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptList.cpp34
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptList.h704
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptLogging.cpp1555
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptLogging.h524
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptMap.h807
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptMessaging.cpp127
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptMessaging.h230
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptNetwork.cpp438
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptNetwork.h277
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptQueue.cpp36
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptQueue.h94
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptReferences.h173
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptResults.cpp153
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptResults.h163
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptRingBuffer.cpp269
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptRingBuffer.h83
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSelectableMessageQueue.h68
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSerialPort.h119
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.cpp128
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.h68
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSockets.cpp59
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSockets.h340
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptStack.h74
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptStreams.cpp724
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptStreams.h321
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptStrings.cpp1205
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptStrings.h358
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSystem.cpp37
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptSystem.h63
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptThreads.cpp161
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptThreads.h322
-rwxr-xr-xlib/libUPnP/Neptune/Source/Core/NptTime.cpp714
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptTime.h156
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptTls.cpp1227
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptTls.h304
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsBase.h583
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsExtended.h91
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptTypes.h149
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptUri.cpp912
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptUri.h322
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptUtils.cpp957
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptUtils.h235
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptVersion.h41
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptXml.cpp2611
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptXml.h391
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptZip.cpp886
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptZip.h220
84 files changed, 29704 insertions, 0 deletions
diff --git a/lib/libUPnP/Neptune/Source/Core/Neptune.cpp b/lib/libUPnP/Neptune/Source/Core/Neptune.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/Neptune.cpp
diff --git a/lib/libUPnP/Neptune/Source/Core/Neptune.h b/lib/libUPnP/Neptune/Source/Core/Neptune.h
new file mode 100644
index 0000000..8ea4fa1
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/Neptune.h
@@ -0,0 +1,86 @@
+/*****************************************************************
+|
+| Neptune - Toplevel Include
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NEPTUNE_H_
+#define _NEPTUNE_H_
+
+/*----------------------------------------------------------------------
+| flags
++---------------------------------------------------------------------*/
+#define NPT_EXTERNAL_USE /* do not expose internal definitions */
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptCommon.h"
+#include "NptResults.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptReferences.h"
+#include "NptStreams.h"
+#include "NptBufferedStreams.h"
+#include "NptFile.h"
+#include "NptNetwork.h"
+#include "NptSockets.h"
+#include "NptTime.h"
+#include "NptThreads.h"
+#include "NptSystem.h"
+#include "NptMessaging.h"
+#include "NptQueue.h"
+#include "NptSimpleMessageQueue.h"
+#include "NptSelectableMessageQueue.h"
+#include "NptXml.h"
+#include "NptStrings.h"
+#include "NptArray.h"
+#include "NptList.h"
+#include "NptMap.h"
+#include "NptStack.h"
+#include "NptUri.h"
+#include "NptHttp.h"
+#include "NptDataBuffer.h"
+#include "NptUtils.h"
+#include "NptRingBuffer.h"
+#include "NptBase64.h"
+#include "NptConsole.h"
+#include "NptLogging.h"
+#include "NptSerialPort.h"
+#include "NptVersion.h"
+#include "NptDynamicLibraries.h"
+#include "NptDynamicCast.h"
+#include "NptDigest.h"
+#include "NptCrypto.h"
+
+// optional modules
+#include "NptZip.h"
+#include "NptTls.h"
+
+#endif // _NEPTUNE_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptArray.h b/lib/libUPnP/Neptune/Source/Core/NptArray.h
new file mode 100644
index 0000000..721bac8
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptArray.h
@@ -0,0 +1,522 @@
+/*****************************************************************
+|
+| Neptune - Arrays
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_ARRAY_H_
+#define _NPT_ARRAY_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#if defined(NPT_CONFIG_HAVE_NEW_H)
+#include <new>
+#endif
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ARRAY_INITIAL_MAX_SIZE = 128; // bytes
+
+/*----------------------------------------------------------------------
+| NPT_Array
++---------------------------------------------------------------------*/
+template <typename T>
+class NPT_Array
+{
+public:
+ // types
+ typedef T Element;
+ typedef T* Iterator;
+
+ // methods
+ NPT_Array<T>(): m_Capacity(0), m_ItemCount(0), m_Items(0) {}
+ explicit NPT_Array<T>(NPT_Cardinal count);
+ NPT_Array<T>(NPT_Cardinal count, const T& item);
+ NPT_Array<T>(const T* items, NPT_Cardinal item_count);
+ ~NPT_Array<T>();
+ NPT_Array<T>(const NPT_Array<T>& copy);
+ NPT_Array<T>& operator=(const NPT_Array<T>& copy);
+ bool operator==(const NPT_Array<T>& other) const;
+ bool operator!=(const NPT_Array<T>& other) const;
+ NPT_Cardinal GetItemCount() const { return m_ItemCount; }
+ NPT_Result Add(const T& item);
+ T& operator[](NPT_Ordinal pos) { return m_Items[pos]; }
+ const T& operator[](NPT_Ordinal pos) const { return m_Items[pos]; }
+ NPT_Result Erase(Iterator which);
+ NPT_Result Erase(NPT_Ordinal which) { return Erase(&m_Items[which]); }
+ NPT_Result Erase(Iterator first, Iterator last);
+ NPT_Result Erase(NPT_Ordinal first, NPT_Ordinal last) { return Erase(&m_Items[first], &m_Items[last]); }
+ NPT_Result Insert(Iterator where, const T& item, NPT_Cardinal count = 1);
+ NPT_Result Reserve(NPT_Cardinal count);
+ NPT_Cardinal GetCapacity() const { return m_Capacity; }
+ NPT_Result Resize(NPT_Cardinal count);
+ NPT_Result Resize(NPT_Cardinal count, const T& fill);
+ NPT_Result Clear();
+ bool Contains(const T& data) const;
+ Iterator GetFirstItem() const { return m_ItemCount?&m_Items[0]:NULL; }
+ Iterator GetLastItem() const { return m_ItemCount?&m_Items[m_ItemCount-1]:NULL; }
+ Iterator GetItem(NPT_Ordinal n) { return n<m_ItemCount?&m_Items[n]:NULL; }
+
+ // template list operations
+ // keep these template members defined here because MSV6 does not let
+ // us define them later
+ template <typename X>
+ NPT_Result Apply(const X& function) const
+ {
+ for (unsigned int i=0; i<m_ItemCount; i++) function(m_Items[i]);
+ return NPT_SUCCESS;
+ }
+
+ template <typename X, typename P>
+ NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
+ {
+ for (unsigned int i=0; i<m_ItemCount; i++) {
+ NPT_Result return_value;
+ if (predicate(function(m_Items[i]), return_value)) {
+ if (match) *match = true;
+ return return_value;
+ }
+ }
+ if (match) *match = false;
+ return NPT_SUCCESS;
+ }
+
+ template <typename X>
+ T* Find(const X& predicate, NPT_Ordinal n=0, NPT_Ordinal* pos = NULL) const
+ {
+ if (pos) *pos = -1;
+
+ for (unsigned int i=0; i<m_ItemCount; i++) {
+ if (predicate(m_Items[i])) {
+ if (pos) *pos = i;
+ if (n == 0) return &m_Items[i];
+ --n;
+ }
+ }
+ return NULL;
+ }
+
+protected:
+ // methods
+ T* Allocate(NPT_Cardinal count, NPT_Cardinal& allocated);
+
+ // members
+ NPT_Cardinal m_Capacity;
+ NPT_Cardinal m_ItemCount;
+ T* m_Items;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(NPT_Cardinal count) :
+ m_Capacity(0),
+ m_ItemCount(0),
+ m_Items(0)
+{
+ Reserve(count);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(const NPT_Array<T>& copy) :
+ m_Capacity(0),
+ m_ItemCount(0),
+ m_Items(0)
+{
+ Reserve(copy.GetItemCount());
+ for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
+ new ((void*)&m_Items[i]) T(copy.m_Items[i]);
+ }
+ m_ItemCount = copy.m_ItemCount;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(NPT_Cardinal count, const T& item) :
+ m_Capacity(0),
+ m_ItemCount(count),
+ m_Items(0)
+{
+ Reserve(count);
+ for (NPT_Ordinal i=0; i<count; i++) {
+ new ((void*)&m_Items[i]) T(item);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(const T* items, NPT_Cardinal item_count) :
+ m_Capacity(0),
+ m_ItemCount(item_count),
+ m_Items(0)
+{
+ Reserve(item_count);
+ for (NPT_Ordinal i=0; i<item_count; i++) {
+ new ((void*)&m_Items[i]) T(items[i]);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::~NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::~NPT_Array()
+{
+ // remove all items
+ Clear();
+
+ // free the memory
+ ::operator delete((void*)m_Items);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::operator=
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Array<T>&
+NPT_Array<T>::operator=(const NPT_Array<T>& copy)
+{
+ // do nothing if we're assigning to ourselves
+ if (this == &copy) return *this;
+
+ // destroy all elements
+ Clear();
+
+ // copy all elements from the other object
+ Reserve(copy.GetItemCount());
+ m_ItemCount = copy.m_ItemCount;
+ for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
+ new ((void*)&m_Items[i]) T(copy.m_Items[i]);
+ }
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Clear
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Clear()
+{
+ // destroy all items
+ for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
+ m_Items[i].~T();
+ }
+
+ m_ItemCount = 0;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Allocate
++---------------------------------------------------------------------*/
+template <typename T>
+T*
+NPT_Array<T>::Allocate(NPT_Cardinal count, NPT_Cardinal& allocated)
+{
+ if (m_Capacity) {
+ allocated = 2*m_Capacity;
+ } else {
+ // start with just enough elements to fill
+ // NPT_ARRAY_INITIAL_MAX_SIZE worth of memory
+ allocated = NPT_ARRAY_INITIAL_MAX_SIZE/sizeof(T);
+ if (allocated == 0) allocated = 1;
+ }
+ if (allocated < count) allocated = count;
+
+ // allocate the items
+ return (T*)::operator new(allocated*sizeof(T));
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Reserve
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Reserve(NPT_Cardinal count)
+{
+ if (count <= m_Capacity) return NPT_SUCCESS;
+
+ // (re)allocate the items
+ NPT_Cardinal new_capacity;
+ T* new_items = Allocate(count, new_capacity);
+ if (new_items == NULL) {
+ return NPT_ERROR_OUT_OF_MEMORY;
+ }
+ if (m_ItemCount && m_Items) {
+ for (unsigned int i=0; i<m_ItemCount; i++) {
+ // construct the copy
+ new ((void*)&new_items[i])T(m_Items[i]);
+
+ // destroy the item
+ m_Items[i].~T();
+ }
+ }
+ ::operator delete((void*)m_Items);
+ m_Items = new_items;
+ m_Capacity = new_capacity;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_Array<T>::Add(const T& item)
+{
+ // ensure capacity
+ NPT_Result result = Reserve(m_ItemCount+1);
+ if (result != NPT_SUCCESS) return result;
+
+ // store the item
+ new ((void*)&m_Items[m_ItemCount++]) T(item);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Erase
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_Array<T>::Erase(Iterator which)
+{
+ return Erase(which, which);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Erase
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Erase(Iterator first, Iterator last)
+{
+ // check parameters
+ if (first == NULL || last == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // check the bounds
+ NPT_Ordinal first_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(first-m_Items));
+ NPT_Ordinal last_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(last-m_Items));
+ if (first_index >= m_ItemCount ||
+ last_index >= m_ItemCount ||
+ first_index > last_index) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // shift items to the left
+ NPT_Cardinal interval = last_index-first_index+1;
+ NPT_Cardinal shifted = m_ItemCount-last_index-1;
+ for (NPT_Ordinal i=first_index; i<first_index+shifted; i++) {
+ m_Items[i] = m_Items[i+interval];
+ }
+
+ // destruct the remaining items
+ for (NPT_Ordinal i=first_index+shifted; i<m_ItemCount; i++) {
+ m_Items[i].~T();
+ }
+
+ // update the item count
+ m_ItemCount -= interval;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Insert(Iterator where, const T& item, NPT_Cardinal repeat)
+{
+ // check bounds
+ NPT_Ordinal where_index = where?((NPT_Ordinal)NPT_POINTER_TO_LONG(where-m_Items)):m_ItemCount;
+ if (where > &m_Items[m_ItemCount] || repeat == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_Cardinal needed = m_ItemCount+repeat;
+ if (needed > m_Capacity) {
+ // allocate more memory
+ NPT_Cardinal new_capacity;
+ T* new_items = Allocate(needed, new_capacity);
+ if (new_items == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+ m_Capacity = new_capacity;
+
+ // move the items before the insertion point
+ for (NPT_Ordinal i=0; i<where_index; i++) {
+ new((void*)&new_items[i])T(m_Items[i]);
+ m_Items[i].~T();
+ }
+
+ // move the items after the insertion point
+ for (NPT_Ordinal i=where_index; i<m_ItemCount; i++) {
+ new((void*)&new_items[i+repeat])T(m_Items[i]);
+ m_Items[i].~T();
+ }
+
+ // use the new items instead of the current ones
+ ::operator delete((void*)m_Items);
+ m_Items = new_items;
+ } else {
+ // shift items after the insertion point to the right
+ for (NPT_Ordinal i=m_ItemCount; i>where_index; i--) {
+ new((void*)&m_Items[i+repeat-1])T(m_Items[i-1]);
+ m_Items[i-1].~T();
+ }
+ }
+
+ // insert the new items
+ for (NPT_Cardinal i=where_index; i<where_index+repeat; i++) {
+ new((void*)&m_Items[i])T(item);
+ }
+
+ // update the item count
+ m_ItemCount += repeat;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Resize
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Resize(NPT_Cardinal size)
+{
+ if (size < m_ItemCount) {
+ // shrink
+ for (NPT_Ordinal i=size; i<m_ItemCount; i++) {
+ m_Items[i].~T();
+ }
+ m_ItemCount = size;
+ } else if (size > m_ItemCount) {
+ return Resize(size, T());
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Resize
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Resize(NPT_Cardinal size, const T& fill)
+{
+ if (size < m_ItemCount) {
+ return Resize(size);
+ } else if (size > m_ItemCount) {
+ Reserve(size);
+ for (NPT_Ordinal i=m_ItemCount; i<size; i++) {
+ new ((void*)&m_Items[i]) T(fill);
+ }
+ m_ItemCount = size;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Contains
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_Array<T>::Contains(const T& data) const
+{
+ for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
+ if (m_Items[i] == data) return true;
+ }
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::operator==
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_Array<T>::operator==(const NPT_Array<T>& other) const
+{
+ // we need the same number of items
+ if (other.m_ItemCount != m_ItemCount) return false;
+
+ // compare all items
+ for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
+ if (!(m_Items[i] == other.m_Items[i])) return false;
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::operator!=
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+bool
+NPT_Array<T>::operator!=(const NPT_Array<T>& other) const
+{
+ return !(*this == other);
+}
+
+#endif // _NPT_ARRAY_H_
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.cpp b/lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.cpp
new file mode 100644
index 0000000..9f677e4
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.cpp
@@ -0,0 +1,101 @@
+/*****************************************************************
+|
+| Neptune - Automatic Cleaner
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptAutomaticCleaner.h"
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner::NPT_AutomaticCleaner
++---------------------------------------------------------------------*/
+NPT_AutomaticCleaner::NPT_AutomaticCleaner() :
+ m_TlsContext(NULL),
+ m_HttpConnectionManager(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner::~NPT_AutomaticCleaner
++---------------------------------------------------------------------*/
+NPT_AutomaticCleaner::~NPT_AutomaticCleaner()
+{
+ // When using TLS, the order to destroy singletons is important as
+ // connections may still need the TLS context up until they're
+ // cleaned up
+ delete m_HttpConnectionManager;
+ delete m_TlsContext;
+
+ // Finally we can destroy the rest such as the NPT_HttpClient::ConnectionCanceller
+ m_Singletons.Apply(NPT_ObjectDeleter<Singleton>());
+}
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner::GetInstance
++---------------------------------------------------------------------*/
+NPT_AutomaticCleaner*
+NPT_AutomaticCleaner::GetInstance()
+{
+ return &Instance;
+}
+NPT_AutomaticCleaner NPT_AutomaticCleaner::Instance;
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner::RegisterTlsContext
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_AutomaticCleaner::RegisterTlsContext(Singleton* singleton)
+{
+ m_TlsContext = singleton;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner::RegisterHttpConnectionManager
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_AutomaticCleaner::RegisterHttpConnectionManager(Singleton* singleton)
+{
+ m_HttpConnectionManager = singleton;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner::Register
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_AutomaticCleaner::Register(Singleton *singleton)
+{
+ // Prevent double insertion
+ m_Singletons.Remove(singleton);
+ return m_Singletons.Insert(m_Singletons.GetFirstItem(), singleton);
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.h b/lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.h
new file mode 100644
index 0000000..21ff7c0
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptAutomaticCleaner.h
@@ -0,0 +1,74 @@
+/*****************************************************************
+|
+| Neptune - Automatic Cleaner
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_AUTOMATIC_CLEANER_H_
+#define _NPT_AUTOMATIC_CLEANER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+| NPT_AutomaticCleaner
++---------------------------------------------------------------------*/
+class NPT_AutomaticCleaner
+{
+public:
+ class Singleton {
+ public:
+ virtual ~Singleton() {}
+ };
+
+ static NPT_AutomaticCleaner* GetInstance();
+
+ // destructor
+ ~NPT_AutomaticCleaner();
+
+ // methods
+ NPT_Result Register(Singleton* singleton);
+ NPT_Result RegisterTlsContext(Singleton* singleton);
+ NPT_Result RegisterHttpConnectionManager(Singleton* singleton);
+
+private:
+ // class members
+ static NPT_AutomaticCleaner Instance;
+
+ // constructor
+ NPT_AutomaticCleaner();
+
+ // members
+ NPT_List<Singleton*> m_Singletons;
+ Singleton* m_TlsContext;
+ Singleton* m_HttpConnectionManager;
+};
+
+#endif // _NPT_AUTOMATIC_CLEANER_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptAutoreleasePool.h b/lib/libUPnP/Neptune/Source/Core/NptAutoreleasePool.h
new file mode 100644
index 0000000..6f704f7
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptAutoreleasePool.h
@@ -0,0 +1,57 @@
+/*****************************************************************
+|
+| Neptune - AutoreleasePool
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_AUTORELEASE_POOL_H_
+#define _NPT_AUTORELEASE_POOL_H_
+
+/*----------------------------------------------------------------------
+| NPT_AutoreleasePoolInterface
++---------------------------------------------------------------------*/
+class NPT_AutoreleasePoolInterface
+{
+public:
+ virtual ~NPT_AutoreleasePoolInterface() {}
+};
+
+/*----------------------------------------------------------------------
+| NPT_AutoreleasePool
++---------------------------------------------------------------------*/
+class NPT_AutoreleasePool : public NPT_AutoreleasePoolInterface
+{
+public:
+ NPT_AutoreleasePool();
+ ~NPT_AutoreleasePool() override;
+
+private:
+ NPT_AutoreleasePoolInterface* m_Delegate;
+};
+
+#endif // _NPT_AUTORELEASE_POOL_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptBase64.cpp b/lib/libUPnP/Neptune/Source/Core/NptBase64.cpp
new file mode 100644
index 0000000..b5ecc25
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptBase64.cpp
@@ -0,0 +1,194 @@
+/*****************************************************************
+|
+| Neptune - Base64
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptBase64.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+static const signed char NPT_Base64_Bytes[128] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x3E, -1, -1, -1, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1, -1, -1, 0x7F, -1, -1,
+ -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1, -1, -1, -1, -1,
+ -1, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, -1, -1, -1, -1, -1
+};
+
+static const char NPT_Base64_Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+const char NPT_BASE64_PAD_CHAR = '=';
+const char NPT_BASE64_PAD_BYTE = 0x7F;
+
+/*----------------------------------------------------------------------
+| NPT_Base64::Decode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Base64::Decode(const char* base64,
+ NPT_Size size,
+ NPT_DataBuffer& data,
+ bool url_safe /* = false */)
+{
+ // estimate the data size
+ data.SetBufferSize(size);
+
+ // reset the buffer
+ data.SetDataSize(0);
+
+ // keep a pointer to the buffer
+ unsigned char* buffer = data.UseData();
+ NPT_Size data_size = 0;
+
+ // iterate over all characters
+ unsigned char codes[4];
+ unsigned int code_count = 0;
+ while (size--) {
+ unsigned char c = *base64++;
+ if (c >= NPT_ARRAY_SIZE(NPT_Base64_Bytes)) continue;
+ if (url_safe) {
+ // remap some characters and forbid the mapped variants
+ if (c == '-') {
+ c = '+';
+ } else if (c == '_') {
+ c = '/';
+ } else if (c == '+' || c == '/') {
+ c = 0; // will be ignored later
+ }
+ }
+ signed char code = NPT_Base64_Bytes[c];
+ if (code >= 0) {
+ // valid code
+ codes[code_count++] = code;
+ if (code_count == 4) {
+ // group complete
+ if (codes[0] == NPT_BASE64_PAD_BYTE || codes[1] == NPT_BASE64_PAD_BYTE) {
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ if (codes[2] == NPT_BASE64_PAD_BYTE) {
+ // pad at char 3
+ if (codes[3] == NPT_BASE64_PAD_BYTE) {
+ // double padding
+ unsigned int packed = (codes[0]<<2)|(codes[1]>>4);
+ buffer[data_size++] = (unsigned char)packed;
+ } else {
+ // invalid padding
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ } else if (codes[3] == NPT_BASE64_PAD_BYTE) {
+ // single padding
+ unsigned int packed = (codes[0]<<10)|(codes[1]<<4)|(codes[2]>>2);
+ buffer[data_size++] = (unsigned char)(packed >> 8);
+ buffer[data_size++] = (unsigned char)(packed );
+ } else {
+ // no padding
+ unsigned int packed = (codes[0]<<18)|(codes[1]<<12)|(codes[2]<<6)|codes[3];
+ buffer[data_size++] = (unsigned char)(packed >> 16);
+ buffer[data_size++] = (unsigned char)(packed >> 8);
+ buffer[data_size++] = (unsigned char)(packed );
+ }
+ code_count = 0;
+ }
+ }
+ }
+
+ if (code_count) return NPT_ERROR_INVALID_FORMAT;
+
+ // update the data size
+ data.SetDataSize(data_size);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Base64::Encode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Base64::Encode(const NPT_Byte* data,
+ NPT_Size size,
+ NPT_String& base64,
+ NPT_Cardinal max_blocks_per_line /* = 0 */,
+ bool url_safe /* = false */)
+{
+ unsigned int block_count = 0;
+ unsigned int i = 0;
+
+ // reserve space for the string
+ base64.Reserve(4*((size+3)/3) + 2*(max_blocks_per_line?(size/(3*max_blocks_per_line)):0));
+ char* buffer = base64.UseChars();
+
+ // encode each byte
+ while (size >= 3) {
+ // output a block
+ *buffer++ = NPT_Base64_Chars[ (data[i ] >> 2) & 0x3F];
+ *buffer++ = NPT_Base64_Chars[((data[i ] & 0x03) << 4) | ((data[i+1] >> 4) & 0x0F)];
+ *buffer++ = NPT_Base64_Chars[((data[i+1] & 0x0F) << 2) | ((data[i+2] >> 6) & 0x03)];
+ *buffer++ = NPT_Base64_Chars[ data[i+2] & 0x3F];
+
+ size -= 3;
+ i += 3;
+ if (++block_count == max_blocks_per_line) {
+ *buffer++ = '\r';
+ *buffer++ = '\n';
+ block_count = 0;
+ }
+ }
+
+ // deal with the tail
+ if (size == 2) {
+ *buffer++ = NPT_Base64_Chars[ (data[i ] >> 2) & 0x3F];
+ *buffer++ = NPT_Base64_Chars[((data[i ] & 0x03) << 4) | ((data[i+1] >> 4) & 0x0F)];
+ *buffer++ = NPT_Base64_Chars[ (data[i+1] & 0x0F) << 2];
+ *buffer++ = NPT_BASE64_PAD_CHAR;
+ } else if (size == 1) {
+ *buffer++ = NPT_Base64_Chars[(data[i] >> 2) & 0x3F];
+ *buffer++ = NPT_Base64_Chars[(data[i] & 0x03) << 4];
+ *buffer++ = NPT_BASE64_PAD_CHAR;
+ *buffer++ = NPT_BASE64_PAD_CHAR;
+ }
+
+ // update the string size
+ NPT_ASSERT((NPT_Size)(buffer-base64.GetChars()) <= base64.GetCapacity());
+ base64.SetLength((NPT_Size)(buffer-base64.GetChars()));
+
+ // deal with url safe remapping
+ if (url_safe) {
+ base64.Replace('+','-');
+ base64.Replace('/','_');
+ }
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptBase64.h b/lib/libUPnP/Neptune/Source/Core/NptBase64.h
new file mode 100644
index 0000000..89950de
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptBase64.h
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+| Neptune - Base64
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_BASE64_H_
+#define _NPT_BASE64_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptDataBuffer.h"
+#include "NptStrings.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const NPT_Cardinal NPT_BASE64_MIME_BLOCKS_PER_LINE = 19;
+const NPT_Cardinal NPT_BASE64_PEM_BLOCKS_PER_LINE = 16;
+
+/*----------------------------------------------------------------------
+| NPT_Base64
++---------------------------------------------------------------------*/
+class NPT_Base64 {
+public:
+ // class methods
+ static NPT_Result Decode(const char* base64,
+ NPT_Size size,
+ NPT_DataBuffer& data,
+ bool url_safe = false);
+ static NPT_Result Encode(const NPT_Byte* data,
+ NPT_Size size,
+ NPT_String& base64,
+ NPT_Cardinal max_blocks_per_line = 0,
+ bool url_safe = false);
+
+private:
+ // this class is purely static
+ NPT_Base64();
+};
+
+#endif // _NPT_BASE64_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.cpp b/lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.cpp
new file mode 100644
index 0000000..157a5bc
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.cpp
@@ -0,0 +1,471 @@
+/*****************************************************************
+|
+| Neptune - Buffered Streams
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptInterfaces.h"
+#include "NptConstants.h"
+#include "NptBufferedStreams.h"
+#include "NptUtils.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.bufferedstreams")
+
+#define NPT_CHECK_NOLOGTIMEOUT(_x) \
+do { \
+ NPT_Result __result = (_x); \
+ if (__result != NPT_SUCCESS) { \
+ if (__result != NPT_ERROR_TIMEOUT && __result != NPT_ERROR_EOS) { \
+ NPT_CHECK_WARNING(__result); \
+ } \
+ return __result; \
+ } \
+} while(0)
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::NPT_BufferedInputStream
++---------------------------------------------------------------------*/
+NPT_BufferedInputStream::NPT_BufferedInputStream(NPT_InputStreamReference& source, NPT_Size buffer_size) :
+ m_Source(source),
+ m_Position(0),
+ m_SkipNewline(false),
+ m_Eos(false)
+{
+ // setup the read buffer
+ m_Buffer.data = NULL;
+ m_Buffer.offset = 0;
+ m_Buffer.valid = 0;
+ m_Buffer.size = buffer_size;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::~NPT_BufferedInputStream
++---------------------------------------------------------------------*/
+NPT_BufferedInputStream::~NPT_BufferedInputStream()
+{
+ // release the buffer
+ delete[] m_Buffer.data;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::SetBufferSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::SetBufferSize(NPT_Size size, bool force /* = false */)
+{
+ if (m_Buffer.data != NULL) {
+ // we already have a buffer
+ if (m_Buffer.size < size || force) {
+ // the current buffer is too small or we want to move
+ // existing data to the beginning of the buffer, reallocate
+ NPT_Byte* buffer = new NPT_Byte[size];
+ if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+
+ // copy existing data
+ NPT_Size need_to_copy = m_Buffer.valid - m_Buffer.offset;
+ if (need_to_copy) {
+ NPT_CopyMemory((void*)buffer,
+ m_Buffer.data+m_Buffer.offset,
+ need_to_copy);
+ }
+
+ // use the new buffer
+ delete[] m_Buffer.data;
+ m_Buffer.data = buffer;
+ m_Buffer.valid -= m_Buffer.offset;
+ m_Buffer.offset = 0;
+ }
+ }
+ m_Buffer.size = size;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::FillBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::FillBuffer()
+{
+ // shortcut
+ if (m_Eos) return NPT_ERROR_EOS;
+
+ // check that there is nothing left in the buffer and the buffer
+ // size is not 0
+ NPT_ASSERT(m_Buffer.valid == m_Buffer.offset);
+ NPT_ASSERT(m_Buffer.size != 0);
+
+ // allocate the read buffer if it has not been done yet
+ if (m_Buffer.data == NULL) {
+ m_Buffer.data = new NPT_Byte[m_Buffer.size];
+ if (m_Buffer.data == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+ }
+
+ // refill the buffer
+ m_Buffer.offset = 0;
+ NPT_Result result = m_Source->Read(m_Buffer.data, m_Buffer.size, &m_Buffer.valid);
+ if (NPT_FAILED(result)) m_Buffer.valid = 0;
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::ReleaseBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::ReleaseBuffer()
+{
+ NPT_ASSERT(m_Buffer.size == 0);
+ NPT_ASSERT(m_Buffer.offset == m_Buffer.valid);
+
+ delete[] m_Buffer.data;
+ m_Buffer.data = NULL;
+ m_Buffer.offset = 0;
+ m_Buffer.valid = 0;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::ReadLine
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::ReadLine(char* buffer,
+ NPT_Size size,
+ NPT_Size* chars_read,
+ bool break_on_cr)
+{
+ NPT_Result result = NPT_SUCCESS;
+ char* buffer_start = buffer;
+ char* buffer_end = buffer_start+size-1;
+ bool skip_newline = false;
+
+ // check parameters
+ if (buffer == NULL || size < 1) {
+ if (chars_read) *chars_read = 0;
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // read until EOF or newline
+ for (;;) {
+ while (m_Buffer.offset != m_Buffer.valid) {
+ // there is some data left in the buffer
+ NPT_Byte c = m_Buffer.data[m_Buffer.offset++];
+ if (c == '\r') {
+ if (break_on_cr) {
+ skip_newline = true;
+ goto done;
+ }
+ } else if (c == '\n') {
+ if (m_SkipNewline && (buffer == buffer_start)) {
+ continue;
+ }
+ goto done;
+ } else {
+ if (buffer == buffer_end) {
+ result = NPT_ERROR_NOT_ENOUGH_SPACE;
+ goto done;
+ }
+ *buffer++ = c;
+ }
+ }
+
+ if (m_Buffer.size == 0 && !m_Eos) {
+ // unbuffered mode
+ if (m_Buffer.data != NULL) ReleaseBuffer();
+ while (NPT_SUCCEEDED(result = m_Source->Read(buffer, 1, NULL))) {
+ if (*buffer == '\r') {
+ if (break_on_cr) {
+ skip_newline = true;
+ goto done;
+ }
+ } else if (*buffer == '\n') {
+ goto done;
+ } else {
+ if (buffer == buffer_end) {
+ result = NPT_ERROR_NOT_ENOUGH_SPACE;
+ goto done;
+ }
+ ++buffer;
+ }
+ }
+ } else {
+ // refill the buffer
+ result = FillBuffer();
+ }
+ if (NPT_FAILED(result)) goto done;
+ }
+
+done:
+ // update the newline skipping state
+ m_SkipNewline = skip_newline;
+
+ // NULL-terminate the line
+ *buffer = '\0';
+
+ // return what we have
+ m_Position += (NPT_Size)(buffer-buffer_start);
+ if (chars_read) *chars_read = (NPT_Size)(buffer-buffer_start);
+ if (result == NPT_ERROR_EOS) {
+ m_Eos = true;
+ if (buffer != buffer_start) {
+ // we have reached the end of the stream, but we have read
+ // some chars, so do not return EOS now
+ return NPT_SUCCESS;
+ }
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::ReadLine
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::ReadLine(NPT_String& line,
+ NPT_Size max_chars,
+ bool break_on_cr)
+{
+ // clear the line
+ line.SetLength(0);
+
+ // reserve space for the chars
+ line.Reserve(max_chars);
+
+ // read the line
+ NPT_Size chars_read = 0;
+ NPT_Result result = ReadLine(line.UseChars(), max_chars, &chars_read, break_on_cr);
+ NPT_CHECK_NOLOGTIMEOUT(result);
+
+ // adjust the length of the string object
+ line.SetLength(chars_read);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ NPT_Result result = NPT_SUCCESS;
+ NPT_Size total_read = 0;
+ NPT_Size buffered;
+
+ // check for a possible shortcut
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // skip a newline char if needed
+ if (m_SkipNewline) {
+ m_SkipNewline = false;
+ result = Read(buffer, 1, NULL);
+ if (NPT_FAILED(result)) goto done;
+ NPT_Byte c = *(NPT_Byte*)buffer;
+ if (c != '\n') {
+ buffer = (void*)((NPT_Byte*)buffer+1);
+ --bytes_to_read;
+ total_read = 1;
+ }
+ }
+
+ // compute how much is buffered
+ buffered = m_Buffer.valid-m_Buffer.offset;
+ if (bytes_to_read > buffered) {
+ // there is not enough in the buffer, take what's there
+ if (buffered) {
+ NPT_CopyMemory(buffer,
+ m_Buffer.data + m_Buffer.offset,
+ buffered);
+ buffer = (void*)((NPT_Byte*)buffer+buffered);
+ m_Buffer.offset += buffered;
+ bytes_to_read -= buffered;
+ total_read += buffered;
+ goto done;
+ }
+
+ // read the rest from the source
+ if (m_Buffer.size == 0) {
+ // unbuffered mode, read directly into the supplied buffer
+ if (m_Buffer.data != NULL) ReleaseBuffer(); // cleanup if necessary
+ NPT_Size local_read = 0;
+ result = m_Source->Read(buffer, bytes_to_read, &local_read);
+ if (NPT_SUCCEEDED(result)) {
+ total_read += local_read;
+ }
+ goto done;
+ } else {
+ // refill the buffer
+ result = FillBuffer();
+ if (NPT_FAILED(result)) goto done;
+ buffered = m_Buffer.valid;
+ if (bytes_to_read > buffered) bytes_to_read = buffered;
+ }
+ }
+
+ // get what we can from the buffer
+ if (bytes_to_read) {
+ NPT_CopyMemory(buffer,
+ m_Buffer.data + m_Buffer.offset,
+ bytes_to_read);
+ m_Buffer.offset += bytes_to_read;
+ total_read += bytes_to_read;
+ }
+
+done:
+ m_Position += total_read;
+ if (bytes_read) *bytes_read = total_read;
+ if (result == NPT_ERROR_EOS) {
+ m_Eos = true;
+ if (total_read != 0) {
+ // we have reached the end of the stream, but we have read
+ // some chars, so do not return EOS now
+ return NPT_SUCCESS;
+ }
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::Peek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::Peek(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ NPT_Result result = NPT_SUCCESS;
+ NPT_Size buffered;
+ NPT_Size new_size = m_Buffer.size?m_Buffer.size:NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE;
+
+ // check for a possible shortcut
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // compute how much is buffered
+ buffered = m_Buffer.valid-m_Buffer.offset;
+ if (bytes_to_read > buffered && buffered < new_size && !m_Eos) {
+ // we need more data than what we have
+ // switch to unbuffered mode and resize to force relocation
+ // of data to the beginning of the buffer
+ SetBufferSize(new_size, true);
+ // fill up the end of the buffer
+ result = FillBuffer();
+ // continue even if it failed
+ buffered = m_Buffer.valid;
+ }
+
+ // make sure we're returning what we can
+ if (bytes_to_read > buffered) bytes_to_read = buffered;
+
+ // get what we can from the buffer
+ NPT_CopyMemory(buffer,
+ m_Buffer.data + m_Buffer.offset,
+ bytes_to_read);
+
+ if (bytes_read) *bytes_read = bytes_to_read;
+ if (result == NPT_ERROR_EOS) {
+ m_Eos = true;
+ if (bytes_to_read != 0) {
+ // we have reached the end of the stream, but we have read
+ // some chars, so do not return EOS now
+ return NPT_SUCCESS;
+ }
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::Seek(NPT_Position offset)
+{
+ NPT_Result result;
+
+ if (offset >= m_Position &&
+ offset - m_Position < m_Buffer.valid - m_Buffer.offset) {
+ NPT_Position diff = offset - m_Position;
+ m_Buffer.offset += ((NPT_Size)diff);
+ m_Position = offset;
+ return NPT_SUCCESS;
+ }
+
+ result = m_Source->Seek(offset);
+ if (NPT_FAILED(result)) return result;
+
+ m_Buffer.offset = 0;
+ m_Buffer.valid = 0;
+ m_Eos = false;
+ m_Position = offset;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::Tell(NPT_Position& offset)
+{
+ offset = m_Position;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::GetSize(NPT_LargeSize& size)
+{
+ return m_Source->GetSize(size);
+}
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ NPT_LargeSize source_available = 0;
+ NPT_Result result = m_Source->GetAvailable(source_available);
+ if (NPT_SUCCEEDED(result)) {
+ available = m_Buffer.valid-m_Buffer.offset + source_available;
+ return NPT_SUCCESS;
+ } else {
+ available = m_Buffer.valid-m_Buffer.offset;
+ return available?NPT_SUCCESS:result;
+ }
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.h b/lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.h
new file mode 100644
index 0000000..6e37051
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptBufferedStreams.h
@@ -0,0 +1,102 @@
+/*****************************************************************
+|
+| Neptune - Buffered Byte Stream
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_BUFFERED_STREAMS_H_
+#define _NPT_BUFFERED_STREAMS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptStreams.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+| NPT_BufferedStream
++---------------------------------------------------------------------*/
+const NPT_Size NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE = 4096;
+
+/*----------------------------------------------------------------------
+| NPT_BufferedInputStream
++---------------------------------------------------------------------*/
+class NPT_BufferedInputStream : public NPT_InputStream
+{
+public:
+ // constructors and destructor
+ NPT_BufferedInputStream(NPT_InputStreamReference& stream,
+ NPT_Size buffer_size = NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE);
+ ~NPT_BufferedInputStream() override;
+
+ // methods
+ virtual NPT_Result ReadLine(NPT_String& line,
+ NPT_Size max_chars = 4096,
+ bool break_on_cr = false);
+ virtual NPT_Result ReadLine(char* buffer,
+ NPT_Size buffer_size,
+ NPT_Size* chars_read = NULL,
+ bool break_on_cr = false);
+ virtual NPT_Result SetBufferSize(NPT_Size size, bool force = false);
+ virtual NPT_Result Peek(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read);
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result Seek(NPT_Position offset) override;
+ NPT_Result Tell(NPT_Position& offset) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override;
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+protected:
+ // members
+ NPT_InputStreamReference m_Source;
+ NPT_Position m_Position;
+ bool m_SkipNewline;
+ bool m_Eos;
+ struct {
+ NPT_Byte* data;
+ NPT_Size offset;
+ NPT_Size valid;
+ NPT_Size size;
+ } m_Buffer;
+
+ // methods
+ virtual NPT_Result FillBuffer();
+ virtual NPT_Result ReleaseBuffer();
+};
+
+typedef NPT_Reference<NPT_BufferedInputStream> NPT_BufferedInputStreamReference;
+
+#endif // _NPT_BUFFERED_STREAMS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptCommon.cpp b/lib/libUPnP/Neptune/Source/Core/NptCommon.cpp
new file mode 100644
index 0000000..3a94380
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptCommon.cpp
@@ -0,0 +1,38 @@
+/*****************************************************************
+|
+| Neptune - Common Classes
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptCommon.h"
+
+
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptCommon.h b/lib/libUPnP/Neptune/Source/Core/NptCommon.h
new file mode 100644
index 0000000..9137d31
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptCommon.h
@@ -0,0 +1,169 @@
+/*****************************************************************
+|
+| Neptune - Common Definitions
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_COMMON_H_
+#define _NPT_COMMON_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| NPT_ObjectDeleter
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_ObjectDeleter {
+public:
+ void operator()(T* object) const {
+ delete object;
+ }
+};
+
+/*----------------------------------------------------------------------
+| NPT_ObjectComparator
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_ObjectComparator {
+public:
+ NPT_ObjectComparator(T& object) : m_Object(object) {}
+ bool operator()(const T& object) const {
+ return object == m_Object;
+ }
+private:
+ T& m_Object;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ContainerFind
++---------------------------------------------------------------------*/
+template <typename T, typename P>
+NPT_Result NPT_ContainerFind(T& container,
+ const P& predicate,
+ typename T::Element& item,
+ NPT_Ordinal n=0)
+{
+ typename T::Iterator found = container.Find(predicate, n);
+ if (found) {
+ item = *found;
+ return NPT_SUCCESS;
+ } else {
+ return NPT_ERROR_NO_SUCH_ITEM;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_ContainerFind
++---------------------------------------------------------------------*/
+template <typename T, typename P>
+NPT_Result NPT_ContainerFind(T& container,
+ const P& predicate,
+ typename T::Iterator& iter,
+ NPT_Ordinal n=0)
+{
+ iter = container.Find(predicate, n);
+ return iter?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| NPT_UntilResultEquals
++---------------------------------------------------------------------*/
+class NPT_UntilResultEquals
+{
+public:
+ // methods
+ NPT_UntilResultEquals(NPT_Result condition_result,
+ NPT_Result return_value = NPT_SUCCESS) :
+ m_ConditionResult(condition_result),
+ m_ReturnValue(return_value) {}
+ bool operator()(NPT_Result result, NPT_Result& return_value) const {
+ if (result == m_ConditionResult) {
+ return_value = m_ReturnValue;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+private:
+ // members
+ NPT_Result m_ConditionResult;
+ NPT_Result m_ReturnValue;
+};
+
+/*----------------------------------------------------------------------
+| NPT_UntilResultNotEquals
++---------------------------------------------------------------------*/
+class NPT_UntilResultNotEquals
+{
+public:
+ // methods
+ NPT_UntilResultNotEquals(NPT_Result condition_result) :
+ m_ConditionResult(condition_result) {}
+ bool operator()(NPT_Result result, NPT_Result& return_value) const {
+ if (result != m_ConditionResult) {
+ return_value = result;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+private:
+ // members
+ NPT_Result m_ConditionResult;
+};
+
+/*----------------------------------------------------------------------
+| NPT_PropertyValue
++---------------------------------------------------------------------*/
+class NPT_PropertyValue
+{
+ public:
+ // typedefs
+ typedef enum {UNKNOWN, INTEGER, STRING} Type;
+
+ // methods
+ NPT_PropertyValue() : m_Type(UNKNOWN), m_Integer(0) {}
+ NPT_PropertyValue(int value) : m_Type(INTEGER), m_Integer(value) {}
+ NPT_PropertyValue(const char* value) : m_Type(STRING), m_String(value) {}
+
+ // members
+ Type m_Type;
+ union {
+ int m_Integer;
+ const char* m_String;
+ };
+};
+
+#endif // _NPT_COMMON_H_
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptConfig.h b/lib/libUPnP/Neptune/Source/Core/NptConfig.h
new file mode 100644
index 0000000..e4be01e
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptConfig.h
@@ -0,0 +1,381 @@
+/*****************************************************************
+|
+| Neptune - Configuration
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_CONFIG_H_
+#define _NPT_CONFIG_H_
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#define NPT_CONFIG_HAVE_ASSERT_H
+#define NPT_CONFIG_HAVE_STD_C
+#define NPT_CONFIG_HAVE_POSIX_TIME
+#define NPT_CONFIG_HAVE_ASSERT_H
+#define NPT_CONFIG_HAVE_STDLIB_H
+#define NPT_CONFIG_HAVE_STDIO_H
+#define NPT_CONFIG_HAVE_STDARG_H
+#define NPT_CONFIG_HAVE_STDINT_H
+#define NPT_CONFIG_HAVE_STRING_H
+#define NPT_CONFIG_HAVE_LIMITS_H
+
+/*----------------------------------------------------------------------
+| standard C runtime
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_HAVE_STD_C)
+#define NPT_CONFIG_HAVE_MALLOC
+#define NPT_CONFIG_HAVE_CALLOC
+#define NPT_CONFIG_HAVE_REALLOC
+#define NPT_CONFIG_HAVE_FREE
+#define NPT_CONFIG_HAVE_MEMCPY
+#define NPT_CONFIG_HAVE_MEMSET
+#define NPT_CONFIG_HAVE_MEMCMP
+#define NPT_CONFIG_HAVE_GETENV
+#define NPT_CONFIG_HAVE_SETENV
+#define NPT_CONFIG_HAVE_UNSETENV
+#if defined(TARGET_WINDOWS_STORE)
+#undef NPT_CONFIG_HAVE_GETENV
+#undef NPT_CONFIG_HAVE_SETENV
+#undef NPT_CONFIG_HAVE_UNSETENV
+#endif
+#define NPT_CONFIG_HAVE_READDIR_R
+#endif /* NPT_CONFIG_HAS_STD_C */
+
+#if defined(NPT_CONFIG_HAVE_POSIX_TIME)
+#define NPT_CONFIG_HAVE_GMTIME
+#define NPT_CONFIG_HAVE_GMTIME_R
+#define NPT_CONFIG_HAVE_LOCALTIME
+#define NPT_CONFIG_HAVE_LOCALTIME_R
+#define NPT_CONFIG_HAVE_TM_GMTOFF
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRING_H)
+#define NPT_CONFIG_HAVE_STRCMP
+#define NPT_CONFIG_HAVE_STRNCMP
+#define NPT_CONFIG_HAVE_STRDUP
+#define NPT_CONFIG_HAVE_STRLEN
+#define NPT_CONFIG_HAVE_STRCPY
+#define NPT_CONFIG_HAVE_STRNCPY
+#endif /* NPT_CONFIG_HAVE_STRING_H */
+
+#if defined(NPT_CONFIG_HAVE_STDIO_H)
+#define NPT_CONFIG_HAVE_SPRINTF
+#define NPT_CONFIG_HAVE_SNPRINTF
+#define NPT_CONFIG_HAVE_VSPRINTF
+#define NPT_CONFIG_HAVE_VSNPRINTF
+#endif /* NPT_CONFIG_HAVE_STDIO_H */
+
+#if defined(NPT_CONFIG_HAVE_LIMITS_H)
+#define NPT_CONFIG_HAVE_INT_MIN
+#define NPT_CONFIG_HAVE_INT_MAX
+#define NPT_CONFIG_HAVE_UINT_MAX
+#define NPT_CONFIG_HAVE_LONG_MIN
+#define NPT_CONFIG_HAVE_LONG_MAX
+#define NPT_CONFIG_HAVE_ULONG_MAX
+#endif
+
+/*----------------------------------------------------------------------
+| standard C++ runtime
++---------------------------------------------------------------------*/
+#define NPT_CONFIG_HAVE_NEW_H
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#define NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+
+/*----------------------------------------------------------------------
+| platform specifics
++---------------------------------------------------------------------*/
+/* Windows 32 */
+#if defined(_WIN32) || defined(_XBOX)
+#if !defined(STRICT)
+#define STRICT
+#endif
+#endif
+
+/* XBox */
+#if defined(_XBOX)
+#define NPT_CONFIG_THREAD_STACK_SIZE 0x10000
+#endif
+
+/* QNX */
+#if defined(__QNX__)
+#define NPT_CONFIG_HAVE_GETADDRINFO
+#endif
+
+/* cygwin */
+#if defined(__CYGWIN__)
+#undef NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+#endif
+
+/* linux */
+#if defined(__linux__)
+#define NPT_CONFIG_HAVE_GETADDRINFO
+//#define NPT_CONFIG_HAVE_GETIFADDRS // Linux has getifaddrs, but it doesn't return the MAC addrs
+ // in a convenient way, so we don't use it
+#undef NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+#define NPT_CONFIG_HAVE_ARPA_INET_H
+#define NPT_CONFIG_HAVE_INET_NTOP
+#define NPT_CONFIG_HAVE_INET_PTON
+#endif
+
+/* symbian */
+#if defined(__SYMBIAN32__)
+/* If defined, specify the stack size of each NPT_Thread. */
+#define NPT_CONFIG_THREAD_STACK_SIZE 0x14000
+#endif
+
+/* android */
+#if defined(ANDROID)
+#define NPT_CONFIG_HAVE_GETADDRINFO
+#undef NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+#define NPT_CONFIG_HAVE_ARPA_INET_H
+#define NPT_CONFIG_HAVE_INET_NTOP
+#define NPT_CONFIG_HAVE_INET_PTON
+#endif
+
+/* OSX and iOS */
+#if defined(__APPLE__)
+#define NPT_CONFIG_HAVE_GETADDRINFO
+#define NPT_CONFIG_HAVE_GETIFADDRS
+#define NPT_CONFIG_HAVE_AUTORELEASE_POOL
+#define NPT_CONFIG_HAVE_SOCKADDR_IN_SIN_LEN
+#define NPT_CONFIG_HAVE_ARPA_INET_H
+#define NPT_CONFIG_HAVE_INET_NTOP
+#define NPT_CONFIG_HAVE_INET_PTON
+#define NPT_CONFIG_HAVE_NET_IF_DL_H
+#define NPT_CONFIG_HAVE_SOCKADDR_DL
+#endif
+
+/*----------------------------------------------------------------------
+| compiler specifics
++---------------------------------------------------------------------*/
+/* GCC */
+#if defined(__GNUC__)
+#define NPT_LocalFunctionName __FUNCTION__
+#define NPT_COMPILER_UNUSED(p) (void)p
+#else
+#define NPT_COMPILER_UNUSED(p)
+#endif
+
+/* TriMedia C/C++ Compiler */
+#if defined(__TCS__)
+#undef NPT_CONFIG_HAVE_ASSERT_H
+#undef NPT_CONFIG_HAVE_SNPRINTF
+#undef NPT_CONFIG_HAVE_VSNPRINTF
+#endif
+
+/* palmos compiler */
+#if defined(__PALMOS__)
+#if __PALMOS__ <= 0x05000000
+#undef NPT_CONFIG_HAVE_ASSERT_H
+#undef NPT_CONFIG_HAVE_SNPRINTF
+#undef NPT_CONFIG_HAVE_VSNPRINTF
+#endif
+#endif
+
+/* Microsoft C/C++ Compiler */
+#if defined(_MSC_VER)
+#undef NPT_CONFIG_HAVE_STDINT_H
+#define NPT_CONFIG_HAVE_GETADDRINFO
+#define NPT_CONFIG_STAT_ST_CTIME_IS_ST_BIRTHTIME
+#define NPT_FORMAT_64 "I64"
+#define NPT_CONFIG_INT64_TYPE __int64
+#define NPT_INT64_MIN _I64_MIN
+#define NPT_INT64_MAX _I64_MAX
+#define NPT_UINT64_MAX _UI64_MAX
+#define NPT_INT64_C(_x) _x##i64
+#define NPT_UINT64_C(_x) _x##ui64
+#define NPT_LocalFunctionName __FUNCTION__
+#if !defined(_WIN32_WCE)
+#define NPT_fseek _fseeki64
+#define NPT_ftell _ftelli64
+#else
+#define NPT_fseek(a,b,c) fseek((a),(long)(b), (c))
+#define NPT_ftell ftell
+#endif
+#define NPT_stat NPT_stat_utf8
+#define NPT_stat_struct struct __stat64
+#if defined(_WIN64)
+typedef __int64 NPT_PointerLong;
+#else
+#if _MSC_VER >= 1400
+typedef __w64 long NPT_PointerLong;
+#else
+typedef long NPT_PointerLong;
+#endif
+#endif
+#define NPT_POINTER_TO_LONG(_p) ((NPT_PointerLong) (_p) )
+#if _MSC_VER >= 1400 && !defined(_WIN32_WCE)
+#define gmtime_r(a,b) gmtime_s(a,b)
+#define localtime_r(a,b) localtime_s(b,a)
+#define NPT_CONFIG_HAVE_FOPEN_S
+#define NPT_CONFIG_HAVE_FSOPEN
+#define NPT_CONFIG_HAVE_SHARE_H
+#define NPT_vsnprintf(s,c,f,a) _vsnprintf_s(s,c,_TRUNCATE,f,a)
+#define NPT_snprintf(s,c,f,...) _snprintf_s(s,c,_TRUNCATE,f,__VA_ARGS__)
+#define NPT_strncpy(d,s,c) strncpy_s(d,c+1,s,c)
+#define NPT_strcpy(d,s) strcpy_s(d,strlen(s)+1,s)
+#undef NPT_CONFIG_HAVE_GETENV
+#ifdef TARGET_WINDOWS_STORE
+#undef NPT_CONFIG_HAVE_GETENV
+#undef NPT_CONFIG_HAVE_DUPENV_S
+#undef NPT_CONFIG_HAVE_SETENV
+#undef NPT_CONFIG_HAVE_UNSETENV
+#undef NPT_CONFIG_HAVE_PUTENV_S
+#else
+#define NPT_CONFIG_HAVE_DUPENV_S
+#define dupenv_s _dupenv_s
+#undef NPT_CONFIG_HAVE_SETENV
+#undef NPT_CONFIG_HAVE_UNSETENV
+#define NPT_CONFIG_HAVE_PUTENV_S
+#define putenv_s _putenv_s
+#endif
+#else
+#undef NPT_CONFIG_HAVE_GMTIME_R
+#undef NPT_CONFIG_HAVE_LOCALTIME_R
+#define NPT_vsnprintf _vsnprintf
+#define NPT_snprintf _snprintf
+#endif
+#if defined(_DEBUG)
+#define _CRTDBG_MAP_ALLOC
+#endif
+#endif
+
+/* Windows CE */
+#if defined(_WIN32_WCE)
+#if defined(NPT_CONFIG_HAVE_FOPEN_S)
+#undef NPT_CONFIG_HAVE_FOPEN_S
+#endif
+#endif
+
+/* Symbian */
+#if defined(__SYMBIAN32__)
+#undef NPT_CONFIG_HAVE_NEW_H
+#include "e32std.h"
+#define explicit
+#define NPT_fseek fseek // no fseeko ?
+#define NPT_ftell ftell // no ftello ?
+#endif
+
+/* Android */
+#if defined(ANDROID)
+#if !defined(NPT_CONFIG_NO_RTTI)
+#define NPT_CONFIG_NO_RTTI
+#endif
+//#define NPT_ftell ftello64
+//#define NPT_fseek fseeko64
+#endif
+
+/* OSX and iOS */
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+#if !defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE
+#define NPT_CONFIG_HAVE_NET_IF_TYPES_H
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)
+#define NPT_CONFIG_HAVE_STAT_ST_BIRTHTIME
+#endif
+#define NPT_CONFIG_HAVE_DEV_URANDOM
+#endif
+#endif
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#if !defined(NPT_FORMAT_64)
+#define NPT_FORMAT_64 "ll"
+#endif
+
+#if !defined(NPT_POINTER_TO_LONG)
+#define NPT_POINTER_TO_LONG(_p) ((long)(_p))
+#endif
+
+#if !defined(NPT_CONFIG_INT64_TYPE)
+#define NPT_CONFIG_INT64_TYPE long long
+#endif
+
+#if !defined(NPT_INT64_C)
+#define NPT_INT64_C(_x) _x##LL
+#endif
+
+#if !defined(NPT_UINT64_C)
+#define NPT_UINT64_C(_x) _x##ULL
+#endif
+
+#if !defined(NPT_snprintf)
+#define NPT_snprintf snprintf
+#endif
+
+#if !defined(NPT_strcpy)
+#define NPT_strcpy strcpy
+#endif
+
+#if !defined(NPT_strncpy)
+#define NPT_strncpy strncpy
+#endif
+
+#if !defined(NPT_vsnprintf)
+#define NPT_vsnprintf vsnprintf
+#endif
+
+#if !defined(NPT_LocalFunctionName)
+#define NPT_LocalFunctionName (NULL)
+#endif
+
+#if !defined(NPT_CONFIG_THREAD_STACK_SIZE)
+#define NPT_CONFIG_THREAD_STACK_SIZE 0
+#endif
+
+#if !defined(NPT_fseek)
+#define NPT_fseek fseeko
+#endif
+
+#if !defined(NPT_ftell)
+#define NPT_ftell ftello
+#endif
+
+#if !defined(NPT_stat)
+#define NPT_stat stat
+#endif
+
+#if !defined(NPT_stat_struct)
+#define NPT_stat_struct struct stat
+#endif
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#if defined(DMALLOC)
+#include <dmalloc.h>
+#endif
+
+#endif // _NPT_CONFIG_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptConsole.cpp b/lib/libUPnP/Neptune/Source/Core/NptConsole.cpp
new file mode 100644
index 0000000..bbd92dd
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptConsole.cpp
@@ -0,0 +1,67 @@
+/*****************************************************************
+|
+| Neptune - Console
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+#if defined(NPT_CONFIG_HAVE_STDARG_H)
+#include <stdarg.h>
+#endif
+
+#include "NptConfig.h"
+#include "NptConsole.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+| NPT_ConsoleOutputFunction
++---------------------------------------------------------------------*/
+static void
+NPT_ConsoleOutputFunction(void*, const char* message)
+{
+ NPT_Console::Output(message);
+}
+
+/*----------------------------------------------------------------------
+| NPT_ConsoleOutputF
++---------------------------------------------------------------------*/
+void
+NPT_Console::OutputF(const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ NPT_FormatOutput(NPT_ConsoleOutputFunction, NULL, format, args);
+
+ va_end(args);
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptConsole.h b/lib/libUPnP/Neptune/Source/Core/NptConsole.h
new file mode 100644
index 0000000..6502a79
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptConsole.h
@@ -0,0 +1,55 @@
+/*****************************************************************
+|
+| Neptune - Console
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+/** @file
+* Header file for console support
+*/
+
+#ifndef _NPT_CONSOLE_H_
+#define _NPT_CONSOLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| prototypes
++---------------------------------------------------------------------*/
+class NPT_Console {
+public:
+ // class methods
+ static void Output(const char* message);
+ static void OutputF(const char* format, ...);
+};
+
+
+#endif /* _NPT_CONSOLE_H_ */
diff --git a/lib/libUPnP/Neptune/Source/Core/NptConstants.h b/lib/libUPnP/Neptune/Source/Core/NptConstants.h
new file mode 100644
index 0000000..6618bf8
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptConstants.h
@@ -0,0 +1,44 @@
+/*****************************************************************
+|
+| Neptune - Constants
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_CONSTANTS_H_
+#define _NPT_CONSTANTS_H_
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#ifndef NULL
+#define NULL 0
+#endif
+
+const int NPT_TIMEOUT_INFINITE = -1;
+
+#endif // _NPT_CONSTANTS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptCrypto.cpp b/lib/libUPnP/Neptune/Source/Core/NptCrypto.cpp
new file mode 100644
index 0000000..20b128b
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptCrypto.cpp
@@ -0,0 +1,833 @@
+/*****************************************************************
+|
+| Neptune - Message Digests
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*
+ Portions of this code are based on the code of LibTomCrypt
+ that was released into public domain by Tom St Denis.
+*/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptCrypto.h"
+#include "NptUtils.h"
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_AES_BLOCK_SIZE 16
+
+static const NPT_UInt32 TE0[256] = {
+ 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+ 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+ 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+ 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+ 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
+ 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
+ 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
+ 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
+ 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
+ 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
+ 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
+ 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
+ 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
+ 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
+ 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
+ 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
+ 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
+ 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
+ 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
+ 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
+ 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
+ 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
+ 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
+ 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
+ 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
+ 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
+ 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
+ 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
+ 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
+ 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
+ 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
+ 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
+ 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
+ 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
+ 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
+ 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
+ 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
+ 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
+ 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
+ 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
+ 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
+ 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
+ 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
+ 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
+ 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
+ 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
+ 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
+ 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
+ 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
+ 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
+ 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
+ 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
+ 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
+ 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
+ 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
+ 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
+ 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
+ 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
+ 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
+ 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
+ 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
+ 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
+ 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
+ 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,
+};
+
+static const NPT_UInt32 Te4[256] = {
+ 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,
+ 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,
+ 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,
+ 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,
+ 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,
+ 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,
+ 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,
+ 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,
+ 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,
+ 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,
+ 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,
+ 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,
+ 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,
+ 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,
+ 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,
+ 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,
+ 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,
+ 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,
+ 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,
+ 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,
+ 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,
+ 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,
+ 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,
+ 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,
+ 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,
+ 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,
+ 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,
+ 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,
+ 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,
+ 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,
+ 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,
+ 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,
+ 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,
+ 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,
+ 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,
+ 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,
+ 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,
+ 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,
+ 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,
+ 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,
+ 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,
+ 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,
+ 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,
+ 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,
+ 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,
+ 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,
+ 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,
+ 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,
+ 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,
+ 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,
+ 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,
+ 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,
+ 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,
+ 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,
+ 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,
+ 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,
+ 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,
+ 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,
+ 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,
+ 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,
+ 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,
+ 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,
+ 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,
+ 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
+};
+
+static const NPT_UInt32 TD0[256] = {
+ 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
+ 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
+ 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
+ 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
+ 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
+ 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
+ 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
+ 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
+ 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
+ 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
+ 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
+ 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
+ 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
+ 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
+ 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
+ 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
+ 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
+ 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
+ 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
+ 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
+ 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
+ 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
+ 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
+ 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
+ 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
+ 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
+ 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
+ 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
+ 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
+ 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
+ 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
+ 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
+ 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
+ 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
+ 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
+ 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
+ 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
+ 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
+ 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
+ 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
+ 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
+ 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
+ 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
+ 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
+ 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
+ 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
+ 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
+ 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
+ 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
+ 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
+ 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
+ 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
+ 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
+ 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
+ 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
+ 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
+ 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
+ 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
+ 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
+ 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
+ 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
+ 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
+ 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
+ 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,
+};
+
+static const NPT_UInt32 Td4[256] = {
+ 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,
+ 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,
+ 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,
+ 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,
+ 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,
+ 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,
+ 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,
+ 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,
+ 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,
+ 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,
+ 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,
+ 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,
+ 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,
+ 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,
+ 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,
+ 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,
+ 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,
+ 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,
+ 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,
+ 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,
+ 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,
+ 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,
+ 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,
+ 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,
+ 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,
+ 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,
+ 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,
+ 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,
+ 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,
+ 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,
+ 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,
+ 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,
+ 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,
+ 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,
+ 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,
+ 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,
+ 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,
+ 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,
+ 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,
+ 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,
+ 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,
+ 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,
+ 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,
+ 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,
+ 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,
+ 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,
+ 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,
+ 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,
+ 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,
+ 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,
+ 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,
+ 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,
+ 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,
+ 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,
+ 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,
+ 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,
+ 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,
+ 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,
+ 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,
+ 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,
+ 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,
+ 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,
+ 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,
+ 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
+};
+
+static const NPT_UInt32 rcon[] = {
+ 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
+ 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
+ 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define RORc(x, y) \
+ ( ((((NPT_UInt32)(x)&0xFFFFFFFFUL)>>(NPT_UInt32)(y)) | \
+ ((NPT_UInt32)(x)<<(NPT_UInt32)(32-(y)))) & 0xFFFFFFFFUL)
+
+#define Te0(x) TE0[x]
+#define Te1(x) RORc(TE0[x], 8)
+#define Te2(x) RORc(TE0[x], 16)
+#define Te3(x) RORc(TE0[x], 24)
+
+#define Td0(x) TD0[x]
+#define Td1(x) RORc(TD0[x], 8)
+#define Td2(x) RORc(TD0[x], 16)
+#define Td3(x) RORc(TD0[x], 24)
+
+#define Te4_0 0x000000FF & Te4
+#define Te4_1 0x0000FF00 & Te4
+#define Te4_2 0x00FF0000 & Te4
+#define Te4_3 0xFF000000 & Te4
+
+#define NPT_BYTE(x,n) (((unsigned char)((x) >> (8 * (n)))))
+
+/*----------------------------------------------------------------------
+| local utility functions
++---------------------------------------------------------------------*/
+static NPT_UInt32 setup_mix(NPT_UInt32 temp)
+{
+ return (Te4_3[NPT_BYTE(temp, 2)]) ^
+ (Te4_2[NPT_BYTE(temp, 1)]) ^
+ (Te4_1[NPT_BYTE(temp, 0)]) ^
+ (Te4_0[NPT_BYTE(temp, 3)]);
+}
+
+static NPT_UInt32 setup_mix2(NPT_UInt32 temp)
+{
+ return Td0(0xFF & Te4[NPT_BYTE(temp, 3)]) ^
+ Td1(0xFF & Te4[NPT_BYTE(temp, 2)]) ^
+ Td2(0xFF & Te4[NPT_BYTE(temp, 1)]) ^
+ Td3(0xFF & Te4[NPT_BYTE(temp, 0)]);
+}
+
+static inline NPT_UInt32 LOAD32H(const NPT_UInt8* p)
+{
+ return ((((NPT_UInt32)p[0])<<24) |
+ (((NPT_UInt32)p[1])<<16) |
+ (((NPT_UInt32)p[2])<< 8) |
+ (((NPT_UInt32)p[3]) ));
+}
+
+static inline void STORE32H(NPT_UInt32 x, NPT_UInt8* p)
+{
+ p[0] = (NPT_UInt8)(x>>24);
+ p[1] = (NPT_UInt8)(x>>16);
+ p[2] = (NPT_UInt8)(x>> 8);
+ p[3] = (NPT_UInt8)(x );
+}
+
+/*----------------------------------------------------------------------
+| NPT_AesBlockCipher
++---------------------------------------------------------------------*/
+class NPT_AesBlockCipher : public NPT_BlockCipher
+{
+public:
+ NPT_AesBlockCipher(const NPT_UInt8* key,
+ NPT_Size key_size);
+ NPT_Result ProcessBlock(const NPT_UInt8* , NPT_UInt8*) {
+ return NPT_ERROR_INTERNAL;
+ }
+ NPT_Size GetBlockSize() { return NPT_AES_BLOCK_SIZE; }
+ Algorithm GetAlgorithm() { return AES_128; }
+
+protected:
+ NPT_UInt32 m_eK[60];
+ NPT_UInt32 m_dK[60];
+ NPT_Cardinal m_RoundCount;
+};
+
+/*----------------------------------------------------------------------
+| NPT_AesBlockEncrypter
++---------------------------------------------------------------------*/
+class NPT_AesBlockEncrypter : public NPT_AesBlockCipher {
+public:
+ NPT_AesBlockEncrypter(const NPT_UInt8* key, NPT_Size key_size) :
+ NPT_AesBlockCipher(key, key_size) {}
+ Direction GetDirection() { return ENCRYPT; }
+ NPT_Result ProcessBlock(const NPT_UInt8* block_in, NPT_UInt8* block_out);
+};
+
+/*----------------------------------------------------------------------
+| NPT_AesBlockDecrypter
++---------------------------------------------------------------------*/
+class NPT_AesBlockDecrypter : public NPT_AesBlockCipher {
+public:
+ NPT_AesBlockDecrypter(const NPT_UInt8* key, NPT_Size key_size) :
+ NPT_AesBlockCipher(key, key_size) {}
+ Direction GetDirection() { return DECRYPT; }
+ NPT_Result ProcessBlock(const NPT_UInt8* block_in, NPT_UInt8* block_out);
+};
+
+/*----------------------------------------------------------------------
+| NPT_AesBlockCipher::NPT_AesBlockCipher
++---------------------------------------------------------------------*/
+NPT_AesBlockCipher::NPT_AesBlockCipher(const NPT_UInt8* key,
+ NPT_Size key_size)
+{
+ unsigned int i, j;
+ NPT_UInt32 temp;
+ NPT_UInt32 *rrk;
+
+ m_RoundCount = 10 + ((key_size/8)-2)*2;
+
+ /* setup the forward key */
+ i = 0;
+ NPT_UInt32* rk = m_eK;
+ rk[0] = LOAD32H(key );
+ rk[1] = LOAD32H(key + 4);
+ rk[2] = LOAD32H(key + 8);
+ rk[3] = LOAD32H(key + 12);
+ if (key_size == 16) {
+ j = 44;
+ for (;;) {
+ temp = rk[3];
+ rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10) {
+ break;
+ }
+ rk += 4;
+ }
+ } else if (key_size == 24) {
+ j = 52;
+ rk[4] = LOAD32H(key + 16);
+ rk[5] = LOAD32H(key + 20);
+ for (;;) {
+ #ifdef _MSC_VER
+ temp = m_eK[rk - m_eK + 5];
+ #else
+ temp = rk[5];
+ #endif
+ rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8) {
+ break;
+ }
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ } else if (key_size == 32) {
+ j = 60;
+ rk[4] = LOAD32H(key + 16);
+ rk[5] = LOAD32H(key + 20);
+ rk[6] = LOAD32H(key + 24);
+ rk[7] = LOAD32H(key + 28);
+ for (;;) {
+ temp = rk[7];
+ rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7) {
+ break;
+ }
+ temp = rk[11];
+ rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8));
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+ rk += 8;
+ }
+ } else {
+ /* this can't happen */
+ return;
+ }
+
+ /* setup the inverse key now */
+ rk = m_dK;
+ rrk = m_eK + j - 4;
+
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ /* copy first */
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk = *rrk;
+ rk -= 3; rrk -= 3;
+
+ for (i = 1; i < m_RoundCount; i++) {
+ rrk -= 4;
+ rk += 4;
+ temp = rrk[0];
+ rk[0] = setup_mix2(temp);
+ temp = rrk[1];
+ rk[1] = setup_mix2(temp);
+ temp = rrk[2];
+ rk[2] = setup_mix2(temp);
+ temp = rrk[3];
+ rk[3] = setup_mix2(temp);
+ }
+
+ /* copy last */
+ rrk -= 4;
+ rk += 4;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk++ = *rrk++;
+ *rk = *rrk;
+}
+
+/*----------------------------------------------------------------------
+| NPT_AesBlockEncrypter::ProcessBlock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_AesBlockEncrypter::ProcessBlock(const NPT_UInt8* pt, NPT_UInt8* ct)
+{
+ NPT_UInt32 s0, s1, s2, s3, t0, t1, t2, t3;
+ int Nr = m_RoundCount;
+ NPT_UInt32* rk = m_eK;
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = LOAD32H(pt ); s0 ^= rk[0];
+ s1 = LOAD32H(pt + 4); s1 ^= rk[1];
+ s2 = LOAD32H(pt + 8); s2 ^= rk[2];
+ s3 = LOAD32H(pt + 12); s3 ^= rk[3];
+
+ for (int r = 0; ; r++) {
+ rk += 4;
+ t0 =
+ Te0(NPT_BYTE(s0, 3)) ^
+ Te1(NPT_BYTE(s1, 2)) ^
+ Te2(NPT_BYTE(s2, 1)) ^
+ Te3(NPT_BYTE(s3, 0)) ^
+ rk[0];
+ t1 =
+ Te0(NPT_BYTE(s1, 3)) ^
+ Te1(NPT_BYTE(s2, 2)) ^
+ Te2(NPT_BYTE(s3, 1)) ^
+ Te3(NPT_BYTE(s0, 0)) ^
+ rk[1];
+ t2 =
+ Te0(NPT_BYTE(s2, 3)) ^
+ Te1(NPT_BYTE(s3, 2)) ^
+ Te2(NPT_BYTE(s0, 1)) ^
+ Te3(NPT_BYTE(s1, 0)) ^
+ rk[2];
+ t3 =
+ Te0(NPT_BYTE(s3, 3)) ^
+ Te1(NPT_BYTE(s0, 2)) ^
+ Te2(NPT_BYTE(s1, 1)) ^
+ Te3(NPT_BYTE(s2, 0)) ^
+ rk[3];
+ if (r == Nr-2) {
+ break;
+ }
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ rk += 4;
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Te4_3[NPT_BYTE(t0, 3)]) ^
+ (Te4_2[NPT_BYTE(t1, 2)]) ^
+ (Te4_1[NPT_BYTE(t2, 1)]) ^
+ (Te4_0[NPT_BYTE(t3, 0)]) ^
+ rk[0];
+ STORE32H(s0, ct);
+ s1 =
+ (Te4_3[NPT_BYTE(t1, 3)]) ^
+ (Te4_2[NPT_BYTE(t2, 2)]) ^
+ (Te4_1[NPT_BYTE(t3, 1)]) ^
+ (Te4_0[NPT_BYTE(t0, 0)]) ^
+ rk[1];
+ STORE32H(s1, ct+4);
+ s2 =
+ (Te4_3[NPT_BYTE(t2, 3)]) ^
+ (Te4_2[NPT_BYTE(t3, 2)]) ^
+ (Te4_1[NPT_BYTE(t0, 1)]) ^
+ (Te4_0[NPT_BYTE(t1, 0)]) ^
+ rk[2];
+ STORE32H(s2, ct+8);
+ s3 =
+ (Te4_3[NPT_BYTE(t3, 3)]) ^
+ (Te4_2[NPT_BYTE(t0, 2)]) ^
+ (Te4_1[NPT_BYTE(t1, 1)]) ^
+ (Te4_0[NPT_BYTE(t2, 0)]) ^
+ rk[3];
+ STORE32H(s3, ct+12);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_AesBlockDecrypter::ProcessBlock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_AesBlockDecrypter::ProcessBlock(const NPT_UInt8* ct, NPT_UInt8* pt)
+{
+ NPT_UInt32 s0, s1, s2, s3, t0, t1, t2, t3;
+
+ int Nr = m_RoundCount;
+ NPT_UInt32* rk = m_dK;
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = LOAD32H(ct ); s0 ^= rk[0];
+ s1 = LOAD32H(ct + 4); s1 ^= rk[1];
+ s2 = LOAD32H(ct + 8); s2 ^= rk[2];
+ s3 = LOAD32H(ct + 12); s3 ^= rk[3];
+
+ for (int r = 0; ; r++) {
+ rk += 4;
+ t0 =
+ Td0(NPT_BYTE(s0, 3)) ^
+ Td1(NPT_BYTE(s3, 2)) ^
+ Td2(NPT_BYTE(s2, 1)) ^
+ Td3(NPT_BYTE(s1, 0)) ^
+ rk[0];
+ t1 =
+ Td0(NPT_BYTE(s1, 3)) ^
+ Td1(NPT_BYTE(s0, 2)) ^
+ Td2(NPT_BYTE(s3, 1)) ^
+ Td3(NPT_BYTE(s2, 0)) ^
+ rk[1];
+ t2 =
+ Td0(NPT_BYTE(s2, 3)) ^
+ Td1(NPT_BYTE(s1, 2)) ^
+ Td2(NPT_BYTE(s0, 1)) ^
+ Td3(NPT_BYTE(s3, 0)) ^
+ rk[2];
+ t3 =
+ Td0(NPT_BYTE(s3, 3)) ^
+ Td1(NPT_BYTE(s2, 2)) ^
+ Td2(NPT_BYTE(s1, 1)) ^
+ Td3(NPT_BYTE(s0, 0)) ^
+ rk[3];
+ if (r == Nr-2) {
+ break;
+ }
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ rk += 4;
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[NPT_BYTE(t0, 3)] & 0xff000000) ^
+ (Td4[NPT_BYTE(t3, 2)] & 0x00ff0000) ^
+ (Td4[NPT_BYTE(t2, 1)] & 0x0000ff00) ^
+ (Td4[NPT_BYTE(t1, 0)] & 0x000000ff) ^
+ rk[0];
+ STORE32H(s0, pt);
+ s1 =
+ (Td4[NPT_BYTE(t1, 3)] & 0xff000000) ^
+ (Td4[NPT_BYTE(t0, 2)] & 0x00ff0000) ^
+ (Td4[NPT_BYTE(t3, 1)] & 0x0000ff00) ^
+ (Td4[NPT_BYTE(t2, 0)] & 0x000000ff) ^
+ rk[1];
+ STORE32H(s1, pt+4);
+ s2 =
+ (Td4[NPT_BYTE(t2, 3)] & 0xff000000) ^
+ (Td4[NPT_BYTE(t1, 2)] & 0x00ff0000) ^
+ (Td4[NPT_BYTE(t0, 1)] & 0x0000ff00) ^
+ (Td4[NPT_BYTE(t3, 0)] & 0x000000ff) ^
+ rk[2];
+ STORE32H(s2, pt+8);
+ s3 =
+ (Td4[NPT_BYTE(t3, 3)] & 0xff000000) ^
+ (Td4[NPT_BYTE(t2, 2)] & 0x00ff0000) ^
+ (Td4[NPT_BYTE(t1, 1)] & 0x0000ff00) ^
+ (Td4[NPT_BYTE(t0, 0)] & 0x000000ff) ^
+ rk[3];
+ STORE32H(s3, pt+12);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BlockCipher::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BlockCipher::Create(Algorithm algorithm,
+ Direction direction,
+ const NPT_UInt8* key,
+ NPT_Size key_size,
+ NPT_BlockCipher*& cipher)
+{
+ cipher = NULL;
+ switch (algorithm) {
+ case AES_128:
+ if (key == NULL || key_size != 16) return NPT_ERROR_INVALID_PARAMETERS;
+ switch (direction) {
+ case ENCRYPT:
+ cipher = new NPT_AesBlockEncrypter(key, 16);
+ return NPT_SUCCESS;
+
+ case DECRYPT:
+ cipher = new NPT_AesBlockDecrypter(key, 16);
+ return NPT_SUCCESS;
+
+ default:
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ default:
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_BlockCipher::ProcessCbc
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BlockCipher::ProcessCbc(const NPT_UInt8* input, NPT_Size input_size, const NPT_UInt8* iv, NPT_DataBuffer& output)
+{
+ // this version only supports block sizes of 16
+ if (GetBlockSize() != 16) return NPT_ERROR_NOT_SUPPORTED;
+
+ // decrypt or encrypt depending on the direction of the cipher
+ NPT_UInt8 chain[16];
+ if (iv) {
+ NPT_CopyMemory(chain, iv, 16);
+ } else {
+ NPT_SetMemory(chain, 0, 16);
+ }
+ if (GetDirection() == ENCRYPT) {
+ // pad
+ unsigned int padding_size = 16-(input_size%16);
+ NPT_DataBuffer padded_input;
+ padded_input.SetDataSize(input_size+padding_size);
+ NPT_UInt8* plaintext = padded_input.UseData();
+ NPT_CopyMemory(plaintext, input, input_size);
+ for (unsigned int x=0; x<padding_size; x++) {
+ plaintext[input_size+x] = padding_size;
+ }
+
+ // process all blocks
+ unsigned int block_count = (input_size+padding_size)/16;
+ output.SetDataSize(block_count*16);
+ NPT_UInt8* ciphertext = output.UseData();
+ for (unsigned int x=0; x<block_count; x++) {
+ // xor with the chaining block
+ for (unsigned int y=0; y<16; y++) {
+ plaintext[y] ^= chain[y];
+ }
+
+ // encrypt the block
+ NPT_Result result = ProcessBlock(plaintext, ciphertext);
+ if (NPT_FAILED(result)) return result;
+
+ // chain and move forward to the next block
+ NPT_CopyMemory(chain, ciphertext, 16);
+ plaintext += 16;
+ ciphertext += 16;
+ }
+ } else {
+ // check that we have an integral number of blocks
+ if (input_size%16) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // process all blocks
+ unsigned int block_count = input_size/16;
+ output.SetBufferSize(block_count*16);
+ NPT_UInt8* plaintext = output.UseData();
+ const NPT_UInt8* ciphertext = input;
+ for (unsigned int x=0; x<block_count; x++) {
+ // decrypt block
+ NPT_Result result = ProcessBlock(ciphertext, plaintext);
+ if (NPT_FAILED(result)) return result;
+
+ // xor with the chaining block
+ for (unsigned int y=0; y<16; y++) {
+ plaintext[y] ^= chain[y];
+ }
+
+ // chain and move forward to the next block
+ NPT_CopyMemory(chain, ciphertext, 16);
+ plaintext += 16;
+ ciphertext += 16;
+ }
+
+ // padding
+ plaintext -= 16;
+ unsigned int padding_size = plaintext[15];
+ if (padding_size == 0 || padding_size > 16) {
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ for (unsigned int y=0; y<padding_size; y++) {
+ if (plaintext[15-y] != padding_size) {
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ }
+ output.SetDataSize(block_count*16 - padding_size);
+ }
+
+ return NPT_SUCCESS;
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptCrypto.h b/lib/libUPnP/Neptune/Source/Core/NptCrypto.h
new file mode 100644
index 0000000..04eb58f
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptCrypto.h
@@ -0,0 +1,78 @@
+/*****************************************************************
+|
+| Neptune - Crypto
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_CRYPTO_H_
+#define _NPT_CRYPTO_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptDataBuffer.h"
+
+/*----------------------------------------------------------------------
+| NPT_BlockCipher
++---------------------------------------------------------------------*/
+class NPT_BlockCipher {
+public:
+ // types
+ typedef enum {
+ AES_128
+ } Algorithm;
+
+ typedef enum {
+ ENCRYPT,
+ DECRYPT
+ } Direction;
+
+ // factory
+ static NPT_Result Create(Algorithm algorithm,
+ Direction direction,
+ const NPT_UInt8* key,
+ NPT_Size key_size,
+ NPT_BlockCipher*& cipher);
+
+ // methods
+ virtual ~NPT_BlockCipher() {}
+ virtual NPT_Size GetBlockSize() = 0;
+ virtual Direction GetDirection() = 0;
+ virtual Algorithm GetAlgorithm() = 0;
+ virtual NPT_Result ProcessBlock(const NPT_UInt8* input, NPT_UInt8* output) = 0;
+ /**
+ * @param iv Initial vector (same size as cipher block size), or NULL for an IV made up of all zeros.
+ */
+ virtual NPT_Result ProcessCbc(const NPT_UInt8* input, NPT_Size input_size, const NPT_UInt8* iv, NPT_DataBuffer& output);
+
+protected:
+ NPT_BlockCipher() {} // don't instantiate directly
+};
+
+#endif // _NPT_CRYPTO_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDataBuffer.cpp b/lib/libUPnP/Neptune/Source/Core/NptDataBuffer.cpp
new file mode 100644
index 0000000..f5ab03c
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDataBuffer.cpp
@@ -0,0 +1,256 @@
+/*****************************************************************
+|
+| Neptune - Data Buffer
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptDataBuffer.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer() :
+ m_BufferIsLocal(true),
+ m_Buffer(NULL),
+ m_BufferSize(0),
+ m_DataSize(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer(NPT_Size bufferSize) :
+ m_BufferIsLocal(true),
+ m_Buffer(bufferSize?new NPT_Byte[bufferSize]:NULL),
+ m_BufferSize(bufferSize),
+ m_DataSize(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer(const void* data, NPT_Size data_size, bool copy) :
+ m_BufferIsLocal(copy),
+ m_Buffer(copy?(data_size?new NPT_Byte[data_size]:NULL):reinterpret_cast<NPT_Byte*>(const_cast<void*>(data))),
+ m_BufferSize(data_size),
+ m_DataSize(data_size)
+{
+ if (copy && data_size) NPT_CopyMemory(m_Buffer, data, data_size);
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer(const NPT_DataBuffer& other) :
+ m_BufferIsLocal(true),
+ m_Buffer(NULL),
+ m_BufferSize(other.m_DataSize),
+ m_DataSize(other.m_DataSize)
+{
+ if (m_BufferSize) {
+ m_Buffer = new NPT_Byte[m_BufferSize];
+ NPT_CopyMemory(m_Buffer, other.m_Buffer, m_BufferSize);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::~NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::~NPT_DataBuffer()
+{
+ Clear();
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::Clear
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::Clear()
+{
+ if (m_BufferIsLocal) {
+ delete[] m_Buffer;
+ }
+ m_Buffer = NULL;
+ m_DataSize = 0;
+ m_BufferSize = 0;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::operator=
++---------------------------------------------------------------------*/
+NPT_DataBuffer&
+NPT_DataBuffer::operator=(const NPT_DataBuffer& copy)
+{
+ // do nothing if we're assigning to ourselves
+ if (this != &copy) {
+ Clear();
+
+ m_BufferIsLocal = true;
+ m_BufferSize = copy.m_BufferSize;
+ m_DataSize = copy.m_DataSize;
+
+ if (m_BufferSize) {
+ m_Buffer = new NPT_Byte[m_BufferSize];
+ NPT_CopyMemory(m_Buffer, copy.m_Buffer, m_BufferSize);
+ }
+ }
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::operator==
++---------------------------------------------------------------------*/
+bool
+NPT_DataBuffer::operator==(const NPT_DataBuffer& other) const
+{
+ // check that the sizes match
+ if (m_DataSize != other.m_DataSize) return false;
+
+ return NPT_MemoryEqual(m_Buffer,
+ other.m_Buffer,
+ m_DataSize);
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::SetBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetBuffer(NPT_Byte* buffer, NPT_Size buffer_size)
+{
+ Clear();
+
+ // we're now using an external buffer
+ m_BufferIsLocal = false;
+ m_Buffer = buffer;
+ m_BufferSize = buffer_size;
+ m_DataSize = 0;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::SetBufferSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetBufferSize(NPT_Size buffer_size)
+{
+ if (m_BufferIsLocal) {
+ return ReallocateBuffer(buffer_size);
+ } else {
+ return NPT_ERROR_NOT_SUPPORTED; // you cannot change the
+ // buffer management mode
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::Reserve
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::Reserve(NPT_Size size)
+{
+ if (size <= m_BufferSize) return NPT_SUCCESS;
+
+ // try doubling the buffer to accomodate for the new size
+ NPT_Size new_size = m_BufferSize*2;
+ if (new_size < size) new_size = size;
+ return SetBufferSize(new_size);
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::SetDataSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetDataSize(NPT_Size size)
+{
+ if (size > m_BufferSize) {
+ // the buffer is too small, we need to reallocate it
+ if (m_BufferIsLocal) {
+ NPT_CHECK(ReallocateBuffer(size));
+ } else {
+ // we cannot reallocate an external buffer
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ }
+ m_DataSize = size;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::SetData
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetData(const NPT_Byte* data, NPT_Size size)
+{
+ if (size > m_BufferSize) {
+ if (m_BufferIsLocal) {
+ NPT_CHECK(ReallocateBuffer(size));
+ } else {
+ return NPT_ERROR_INVALID_STATE;
+ }
+ }
+ if (data) NPT_CopyMemory(m_Buffer, data, size);
+ m_DataSize = size;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer::ReallocateBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::ReallocateBuffer(NPT_Size size)
+{
+ // check that the existing data fits
+ if (m_DataSize > size) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // allocate a new buffer
+ NPT_Byte* newBuffer = new NPT_Byte[size];
+
+ // copy the contents of the previous buffer, if any
+ if (m_Buffer && m_DataSize) {
+ NPT_CopyMemory(newBuffer, m_Buffer, m_DataSize);
+ }
+
+ // destroy the previous buffer
+ delete[] m_Buffer;
+
+ // use the new buffer
+ m_Buffer = newBuffer;
+ m_BufferSize = size;
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDataBuffer.h b/lib/libUPnP/Neptune/Source/Core/NptDataBuffer.h
new file mode 100644
index 0000000..7e57c01
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDataBuffer.h
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+| Neptune - Datagram Packets
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DATA_BUFFER_H_
+#define _NPT_DATA_BUFFER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+| NPT_DataBuffer
++---------------------------------------------------------------------*/
+class NPT_DataBuffer
+{
+ public:
+ // constructors & destructor
+ NPT_DataBuffer(); // size unknown until first set
+ NPT_DataBuffer(NPT_Size size); // initial size specified
+ NPT_DataBuffer(const void* data, NPT_Size size, bool copy = true); // initial data and size specified
+ NPT_DataBuffer(const NPT_DataBuffer& other);
+ virtual ~NPT_DataBuffer();
+
+ // operators
+ NPT_DataBuffer& operator=(const NPT_DataBuffer& copy);
+ bool operator==(const NPT_DataBuffer& other) const;
+
+ // data buffer handling methods
+ virtual NPT_Result SetBuffer(NPT_Byte* buffer, NPT_Size bufferSize);
+ virtual NPT_Result SetBufferSize(NPT_Size bufferSize);
+ virtual NPT_Size GetBufferSize() const { return m_BufferSize; }
+ virtual NPT_Result Reserve(NPT_Size size);
+ virtual NPT_Result Clear();
+
+ // data handling methods
+ virtual const NPT_Byte* GetData() const { return m_Buffer; }
+ virtual NPT_Byte* UseData() { return m_Buffer; };
+ virtual NPT_Size GetDataSize() const { return m_DataSize; }
+ virtual NPT_Result SetDataSize(NPT_Size size);
+ virtual NPT_Result SetData(const NPT_Byte* data, NPT_Size dataSize);
+
+ protected:
+ // members
+ bool m_BufferIsLocal;
+ NPT_Byte* m_Buffer;
+ NPT_Size m_BufferSize;
+ NPT_Size m_DataSize;
+
+ // methods
+ NPT_Result ReallocateBuffer(NPT_Size size);
+};
+
+#endif // _NPT_DATA_BUFFER_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDebug.cpp b/lib/libUPnP/Neptune/Source/Core/NptDebug.cpp
new file mode 100644
index 0000000..d9b7041
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDebug.cpp
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+| Neptune - Debug Utilities
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <stdarg.h>
+#include "NptUtils.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_DEBUG_LOCAL_BUFFER_SIZE 1024
+#define NPT_DEBUG_BUFFER_INCREMENT 4096
+#define NPT_DEBUG_BUFFER_MAX_SIZE 65536
+
+/*----------------------------------------------------------------------
+| NPT_Debug
++---------------------------------------------------------------------*/
+void
+NPT_Debug(const char* format, ...)
+{
+#if defined(NPT_DEBUG)
+ char local_buffer[NPT_DEBUG_LOCAL_BUFFER_SIZE];
+ unsigned int buffer_size = NPT_DEBUG_LOCAL_BUFFER_SIZE;
+ char* buffer = local_buffer;
+ va_list args;
+
+ va_start(args, format);
+
+ for(;;) {
+ int result;
+
+ /* try to format the message (it might not fit) */
+ result = NPT_FormatStringVN(buffer, buffer_size-1, format, args);
+ buffer[buffer_size-1] = 0; /* force a NULL termination */
+ if (result >= 0) break;
+
+ /* the buffer was too small, try something bigger */
+ buffer_size = (buffer_size+NPT_DEBUG_BUFFER_INCREMENT)*2;
+ if (buffer_size > NPT_DEBUG_BUFFER_MAX_SIZE) break;
+ if (buffer != local_buffer) delete[] buffer;
+ buffer = new char[buffer_size];
+ if (buffer == NULL) return;
+ }
+
+ NPT_DebugOutput(buffer);
+ if (buffer != local_buffer) delete[] buffer;
+
+ va_end(args);
+#else
+ NPT_COMPILER_UNUSED(format);
+#endif
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDebug.h b/lib/libUPnP/Neptune/Source/Core/NptDebug.h
new file mode 100644
index 0000000..d4973a2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDebug.h
@@ -0,0 +1,56 @@
+/*****************************************************************
+|
+| Neptune - Debug Utilities
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DEBUG_H_
+#define _NPT_DEBUG_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+/*----------------------------------------------------------------------
+| standard macros
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_HAVE_ASSERT_H) && defined(NPT_DEBUG)
+#include <assert.h>
+#define NPT_ASSERT(x) assert(x)
+#else
+#define NPT_ASSERT(x) ((void)0)
+#endif
+
+/*----------------------------------------------------------------------
+| NPT_Debug
++---------------------------------------------------------------------*/
+extern void NPT_Debug(const char* format, ...);
+extern void NPT_DebugOutput(const char* message);
+
+#endif // _NPT_DEBUG_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDefs.h b/lib/libUPnP/Neptune/Source/Core/NptDefs.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDefs.h
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp b/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp
new file mode 100644
index 0000000..4e7fb74
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp
@@ -0,0 +1,685 @@
+/*****************************************************************
+|
+| Neptune - Message Digests
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*
+ Portions of this code are based on the code of LibTomCrypt
+ that was released into public domain by Tom St Denis.
+*/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptDigest.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_BASIC_DIGEST_BLOCK_SIZE 64
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define NPT_Digest_ROL(x, y) \
+( (((NPT_UInt32)(x) << (y)) | (((NPT_UInt32)(x) & 0xFFFFFFFFUL) >> (32 - (y)))) & 0xFFFFFFFFUL)
+#define NPT_Digest_ROR(x, y) \
+( ((((NPT_UInt32)(x)&0xFFFFFFFFUL)>>(NPT_UInt32)((y)&31)) | ((NPT_UInt32)(x)<<(NPT_UInt32)(32-((y)&31)))) & 0xFFFFFFFFUL)
+
+#define NPT_Sha1_F0(x,y,z) (z ^ (x & (y ^ z)))
+#define NPT_Sha1_F1(x,y,z) (x ^ y ^ z)
+#define NPT_Sha1_F2(x,y,z) ((x & y) | (z & (x | y)))
+#define NPT_Sha1_F3(x,y,z) (x ^ y ^ z)
+
+#define NPT_Sha1_FF0(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F0(b,c,d) + e + W[i] + 0x5a827999UL); b = NPT_Digest_ROL(b, 30);
+#define NPT_Sha1_FF1(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = NPT_Digest_ROL(b, 30);
+#define NPT_Sha1_FF2(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = NPT_Digest_ROL(b, 30);
+#define NPT_Sha1_FF3(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = NPT_Digest_ROL(b, 30);
+
+#define NPT_Sha256_Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define NPT_Sha256_Maj(x,y,z) (((x | y) & z) | (x & y))
+#define NPT_Sha256_S(x, n) NPT_Digest_ROR((x),(n))
+#define NPT_Sha256_R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
+#define NPT_Sha256_Sigma0(x) (NPT_Sha256_S(x, 2) ^ NPT_Sha256_S(x, 13) ^ NPT_Sha256_S(x, 22))
+#define NPT_Sha256_Sigma1(x) (NPT_Sha256_S(x, 6) ^ NPT_Sha256_S(x, 11) ^ NPT_Sha256_S(x, 25))
+#define NPT_Sha256_Gamma0(x) (NPT_Sha256_S(x, 7) ^ NPT_Sha256_S(x, 18) ^ NPT_Sha256_R(x, 3))
+#define NPT_Sha256_Gamma1(x) (NPT_Sha256_S(x, 17) ^ NPT_Sha256_S(x, 19) ^ NPT_Sha256_R(x, 10))
+
+
+#define NPT_Md5_F(x,y,z) (z ^ (x & (y ^ z)))
+#define NPT_Md5_G(x,y,z) (y ^ (z & (y ^ x)))
+#define NPT_Md5_H(x,y,z) (x ^ y ^ z)
+#define NPT_Md5_I(x,y,z) (y ^ (x | (~z)))
+
+#define NPT_Md5_FF(a,b,c,d,M,s,t) \
+ a = (a + NPT_Md5_F(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
+
+#define NPT_Md5_GG(a,b,c,d,M,s,t) \
+ a = (a + NPT_Md5_G(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
+
+#define NPT_Md5_HH(a,b,c,d,M,s,t) \
+ a = (a + NPT_Md5_H(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
+
+#define NPT_Md5_II(a,b,c,d,M,s,t) \
+ a = (a + NPT_Md5_I(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
+
+/*----------------------------------------------------------------------
+| NPT_BasicDigest
++---------------------------------------------------------------------*/
+class NPT_BasicDigest : public NPT_Digest
+{
+public:
+ NPT_BasicDigest();
+
+ // NPT_Digest methods
+ virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size);
+
+protected:
+ // methods
+ NPT_Result ComputeDigest(NPT_UInt32* state,
+ NPT_Cardinal state_count,
+ bool big_endian,
+ NPT_DataBuffer& digest);
+ virtual void CompressBlock(const NPT_UInt8* block) = 0;
+
+ // members
+ NPT_UInt64 m_Length;
+ NPT_UInt32 m_Pending;
+ NPT_UInt8 m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE];
+};
+
+/*----------------------------------------------------------------------
+| NPT_BasicDigest::NPT_BasicDigest
++---------------------------------------------------------------------*/
+NPT_BasicDigest::NPT_BasicDigest() :
+ m_Length(0),
+ m_Pending(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_BasicDigest::Update
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BasicDigest::Update(const NPT_UInt8* data, NPT_Size data_size)
+{
+ while (data_size > 0) {
+ if (m_Pending == 0 && data_size >= NPT_BASIC_DIGEST_BLOCK_SIZE) {
+ CompressBlock(data);
+ m_Length += NPT_BASIC_DIGEST_BLOCK_SIZE * 8;
+ data += NPT_BASIC_DIGEST_BLOCK_SIZE;
+ data_size -= NPT_BASIC_DIGEST_BLOCK_SIZE;
+ } else {
+ unsigned int chunk = data_size;
+ if (chunk > (NPT_BASIC_DIGEST_BLOCK_SIZE - m_Pending)) {
+ chunk = NPT_BASIC_DIGEST_BLOCK_SIZE - m_Pending;
+ }
+ NPT_CopyMemory(&m_Buffer[m_Pending], data, chunk);
+ m_Pending += chunk;
+ data += chunk;
+ data_size -= chunk;
+ if (m_Pending == NPT_BASIC_DIGEST_BLOCK_SIZE) {
+ CompressBlock(m_Buffer);
+ m_Length += 8 * NPT_BASIC_DIGEST_BLOCK_SIZE;
+ m_Pending = 0;
+ }
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+| NPT_BasicDigest::ComputeDigest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BasicDigest::ComputeDigest(NPT_UInt32* state,
+ NPT_Cardinal state_count,
+ bool big_endian,
+ NPT_DataBuffer& digest)
+{
+ // increase the length of the message
+ m_Length += m_Pending * 8;
+
+ // append the '1' bit
+ m_Buffer[m_Pending++] = 0x80;
+
+ // if there isn't enough space left for the size (8 bytes), then compress.
+ // then we can fall back to padding zeros and length encoding as normal.
+ if (m_Pending > NPT_BASIC_DIGEST_BLOCK_SIZE-8) {
+ while (m_Pending < NPT_BASIC_DIGEST_BLOCK_SIZE) {
+ m_Buffer[m_Pending++] = 0;
+ }
+ CompressBlock(m_Buffer);
+ m_Pending = 0;
+ }
+
+ // pad with zeroes up until the length
+ while (m_Pending < NPT_BASIC_DIGEST_BLOCK_SIZE-8) {
+ m_Buffer[m_Pending++] = 0;
+ }
+
+ // store length
+ if (big_endian) {
+ NPT_BytesFromInt64Be(&m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE-8], m_Length);
+ } else {
+ NPT_BytesFromInt64Le(&m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE-8], m_Length);
+ }
+ CompressBlock(m_Buffer);
+
+ // copy output
+ digest.SetDataSize(4*state_count);
+ NPT_UInt8* out = digest.UseData();
+ if (big_endian) {
+ for (unsigned int i = 0; i < state_count; i++) {
+ NPT_BytesFromInt32Be(out, state[i]);
+ out += 4;
+ }
+ } else {
+ for (unsigned int i = 0; i < state_count; i++) {
+ NPT_BytesFromInt32Le(out, state[i]);
+ out += 4;
+ }
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Sha1Digest
++---------------------------------------------------------------------*/
+class NPT_Sha1Digest : public NPT_BasicDigest
+{
+public:
+ NPT_Sha1Digest();
+
+ // NPT_Digest methods
+ virtual NPT_Result GetDigest(NPT_DataBuffer& digest);
+ virtual unsigned int GetSize() { return 20; }
+
+private:
+ // methods
+ virtual void CompressBlock(const NPT_UInt8* block);
+
+ // members
+ NPT_UInt32 m_State[5];
+};
+
+/*----------------------------------------------------------------------
+| NPT_Sha1Digest::NPT_Sha1Digest
++---------------------------------------------------------------------*/
+NPT_Sha1Digest::NPT_Sha1Digest()
+{
+ m_State[0] = 0x67452301UL;
+ m_State[1] = 0xefcdab89UL;
+ m_State[2] = 0x98badcfeUL;
+ m_State[3] = 0x10325476UL;
+ m_State[4] = 0xc3d2e1f0UL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Sha1Digest::CompressBlock
++---------------------------------------------------------------------*/
+void
+NPT_Sha1Digest::CompressBlock(const NPT_UInt8* block)
+{
+ NPT_UInt32 a,b,c,d,e,t,W[80];
+
+ // copy the 512-bit block into W[0..15]
+ for (unsigned int i = 0; i < 16; i++) {
+ W[i] = NPT_BytesToInt32Be(&block[4*i]);
+ }
+
+ // copy the state to local variables
+ a = m_State[0];
+ b = m_State[1];
+ c = m_State[2];
+ d = m_State[3];
+ e = m_State[4];
+
+ // expand it
+ unsigned int i;
+ for (i = 16; i < 80; i++) {
+ W[i] = NPT_Digest_ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
+ }
+
+ // compress
+ for (i = 0; i < 20; ) {
+ NPT_Sha1_FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 40; ) {
+ NPT_Sha1_FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 60; ) {
+ NPT_Sha1_FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ for (; i < 80; ) {
+ NPT_Sha1_FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+ }
+
+ // store the variables back into the state
+ m_State[0] += a;
+ m_State[1] += b;
+ m_State[2] += c;
+ m_State[3] += d;
+ m_State[4] += e;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Sha1Digest::GetDigest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Sha1Digest::GetDigest(NPT_DataBuffer& digest)
+{
+ return ComputeDigest(m_State, 5, true, digest);
+}
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+static const NPT_UInt32 NPT_Sha256_K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+ 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+ 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+ 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+ 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+ 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+ 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+ 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+ 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+ 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/*----------------------------------------------------------------------
+| NPT_Sha256Digest
++---------------------------------------------------------------------*/
+class NPT_Sha256Digest : public NPT_BasicDigest
+{
+public:
+ NPT_Sha256Digest();
+
+ // NPT_Digest methods
+ virtual NPT_Result GetDigest(NPT_DataBuffer& digest);
+ virtual unsigned int GetSize() { return 32; }
+
+private:
+ // methods
+ virtual void CompressBlock(const NPT_UInt8* block);
+
+ // members
+ NPT_UInt32 m_State[8];
+};
+
+/*----------------------------------------------------------------------
+| NPT_Sha256Digest::NPT_Sha256Digest
++---------------------------------------------------------------------*/
+NPT_Sha256Digest::NPT_Sha256Digest()
+{
+ m_State[0] = 0x6A09E667UL;
+ m_State[1] = 0xBB67AE85UL;
+ m_State[2] = 0x3C6EF372UL;
+ m_State[3] = 0xA54FF53AUL;
+ m_State[4] = 0x510E527FUL;
+ m_State[5] = 0x9B05688CUL;
+ m_State[6] = 0x1F83D9ABUL;
+ m_State[7] = 0x5BE0CD19UL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Sha256Digest::CompressBlock
++---------------------------------------------------------------------*/
+void
+NPT_Sha256Digest::CompressBlock(const NPT_UInt8* block)
+{
+ NPT_UInt32 S[8], W[64];
+
+ // copy the state into the local workspace
+ for (unsigned int i = 0; i < 8; i++) {
+ S[i] = m_State[i];
+ }
+
+ // copy the 512-bit block into W[0..15]
+ for (unsigned int i = 0; i < 16; i++) {
+ W[i] = NPT_BytesToInt32Be(&block[4*i]);
+ }
+
+ // fill W[16..63]
+ for (unsigned int i = 16; i < 64; i++) {
+ W[i] = NPT_Sha256_Gamma1(W[i - 2]) + W[i - 7] + NPT_Sha256_Gamma0(W[i - 15]) + W[i - 16];
+ }
+
+ // compress
+ for (unsigned int i = 0; i < 64; ++i) {
+ NPT_UInt32 t0 =
+ S[7] +
+ NPT_Sha256_Sigma1(S[4]) +
+ NPT_Sha256_Ch(S[4], S[5], S[6]) +
+ NPT_Sha256_K[i] +
+ W[i];
+ NPT_UInt32 t1 = NPT_Sha256_Sigma0(S[0]) + NPT_Sha256_Maj(S[0], S[1], S[2]);
+ S[3] += t0;
+ S[7] = t0 + t1;
+
+ NPT_UInt32 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
+ S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+ }
+
+ // store the local variables back into the state
+ for (unsigned i = 0; i < 8; i++) {
+ m_State[i] += S[i];
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Sha256Digest::GetDigest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Sha256Digest::GetDigest(NPT_DataBuffer& digest)
+{
+ return ComputeDigest(m_State, 8, true, digest);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Md5Digest
++---------------------------------------------------------------------*/
+class NPT_Md5Digest : public NPT_BasicDigest
+{
+public:
+ NPT_Md5Digest();
+
+ // NPT_Digest methods
+ virtual NPT_Result GetDigest(NPT_DataBuffer& digest);
+ virtual unsigned int GetSize() { return 16; }
+
+protected:
+ // methods
+ virtual void CompressBlock(const NPT_UInt8* block);
+
+ // members
+ NPT_UInt32 m_State[4];
+};
+
+/*----------------------------------------------------------------------
+| NPT_Md5Digest::NPT_Md5Digest
++---------------------------------------------------------------------*/
+NPT_Md5Digest::NPT_Md5Digest()
+{
+ m_State[0] = 0x67452301UL;
+ m_State[1] = 0xefcdab89UL;
+ m_State[2] = 0x98badcfeUL;
+ m_State[3] = 0x10325476UL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Md5Digest::CompressBlock
++---------------------------------------------------------------------*/
+void
+NPT_Md5Digest::CompressBlock(const NPT_UInt8* block)
+{
+ NPT_UInt32 a,b,c,d,W[16];
+
+ // copy the 512-bit block into W[0..15]
+ unsigned int i;
+ for (i = 0; i < 16; i++) {
+ W[i] = NPT_BytesToInt32Le(&block[4*i]);
+ }
+
+ // copy the state to local variables
+ a = m_State[0];
+ b = m_State[1];
+ c = m_State[2];
+ d = m_State[3];
+
+ // round 1
+ NPT_Md5_FF(a,b,c,d,W[ 0], 7,0xd76aa478UL)
+ NPT_Md5_FF(d,a,b,c,W[ 1],12,0xe8c7b756UL)
+ NPT_Md5_FF(c,d,a,b,W[ 2],17,0x242070dbUL)
+ NPT_Md5_FF(b,c,d,a,W[ 3],22,0xc1bdceeeUL)
+ NPT_Md5_FF(a,b,c,d,W[ 4], 7,0xf57c0fafUL)
+ NPT_Md5_FF(d,a,b,c,W[ 5],12,0x4787c62aUL)
+ NPT_Md5_FF(c,d,a,b,W[ 6],17,0xa8304613UL)
+ NPT_Md5_FF(b,c,d,a,W[ 7],22,0xfd469501UL)
+ NPT_Md5_FF(a,b,c,d,W[ 8], 7,0x698098d8UL)
+ NPT_Md5_FF(d,a,b,c,W[ 9],12,0x8b44f7afUL)
+ NPT_Md5_FF(c,d,a,b,W[10],17,0xffff5bb1UL)
+ NPT_Md5_FF(b,c,d,a,W[11],22,0x895cd7beUL)
+ NPT_Md5_FF(a,b,c,d,W[12], 7,0x6b901122UL)
+ NPT_Md5_FF(d,a,b,c,W[13],12,0xfd987193UL)
+ NPT_Md5_FF(c,d,a,b,W[14],17,0xa679438eUL)
+ NPT_Md5_FF(b,c,d,a,W[15],22,0x49b40821UL)
+
+ // round 2
+ NPT_Md5_GG(a,b,c,d,W[ 1], 5,0xf61e2562UL)
+ NPT_Md5_GG(d,a,b,c,W[ 6], 9,0xc040b340UL)
+ NPT_Md5_GG(c,d,a,b,W[11],14,0x265e5a51UL)
+ NPT_Md5_GG(b,c,d,a,W[ 0],20,0xe9b6c7aaUL)
+ NPT_Md5_GG(a,b,c,d,W[ 5], 5,0xd62f105dUL)
+ NPT_Md5_GG(d,a,b,c,W[10], 9,0x02441453UL)
+ NPT_Md5_GG(c,d,a,b,W[15],14,0xd8a1e681UL)
+ NPT_Md5_GG(b,c,d,a,W[ 4],20,0xe7d3fbc8UL)
+ NPT_Md5_GG(a,b,c,d,W[ 9], 5,0x21e1cde6UL)
+ NPT_Md5_GG(d,a,b,c,W[14], 9,0xc33707d6UL)
+ NPT_Md5_GG(c,d,a,b,W[ 3],14,0xf4d50d87UL)
+ NPT_Md5_GG(b,c,d,a,W[ 8],20,0x455a14edUL)
+ NPT_Md5_GG(a,b,c,d,W[13], 5,0xa9e3e905UL)
+ NPT_Md5_GG(d,a,b,c,W[ 2], 9,0xfcefa3f8UL)
+ NPT_Md5_GG(c,d,a,b,W[ 7],14,0x676f02d9UL)
+ NPT_Md5_GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
+
+ // round 3
+ NPT_Md5_HH(a,b,c,d,W[ 5], 4,0xfffa3942UL)
+ NPT_Md5_HH(d,a,b,c,W[ 8],11,0x8771f681UL)
+ NPT_Md5_HH(c,d,a,b,W[11],16,0x6d9d6122UL)
+ NPT_Md5_HH(b,c,d,a,W[14],23,0xfde5380cUL)
+ NPT_Md5_HH(a,b,c,d,W[ 1], 4,0xa4beea44UL)
+ NPT_Md5_HH(d,a,b,c,W[ 4],11,0x4bdecfa9UL)
+ NPT_Md5_HH(c,d,a,b,W[ 7],16,0xf6bb4b60UL)
+ NPT_Md5_HH(b,c,d,a,W[10],23,0xbebfbc70UL)
+ NPT_Md5_HH(a,b,c,d,W[13], 4,0x289b7ec6UL)
+ NPT_Md5_HH(d,a,b,c,W[ 0],11,0xeaa127faUL)
+ NPT_Md5_HH(c,d,a,b,W[ 3],16,0xd4ef3085UL)
+ NPT_Md5_HH(b,c,d,a,W[ 6],23,0x04881d05UL)
+ NPT_Md5_HH(a,b,c,d,W[ 9], 4,0xd9d4d039UL)
+ NPT_Md5_HH(d,a,b,c,W[12],11,0xe6db99e5UL)
+ NPT_Md5_HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
+ NPT_Md5_HH(b,c,d,a,W[ 2],23,0xc4ac5665UL)
+
+ // round 4
+ NPT_Md5_II(a,b,c,d,W[ 0], 6,0xf4292244UL)
+ NPT_Md5_II(d,a,b,c,W[ 7],10,0x432aff97UL)
+ NPT_Md5_II(c,d,a,b,W[14],15,0xab9423a7UL)
+ NPT_Md5_II(b,c,d,a,W[ 5],21,0xfc93a039UL)
+ NPT_Md5_II(a,b,c,d,W[12], 6,0x655b59c3UL)
+ NPT_Md5_II(d,a,b,c,W[ 3],10,0x8f0ccc92UL)
+ NPT_Md5_II(c,d,a,b,W[10],15,0xffeff47dUL)
+ NPT_Md5_II(b,c,d,a,W[ 1],21,0x85845dd1UL)
+ NPT_Md5_II(a,b,c,d,W[ 8], 6,0x6fa87e4fUL)
+ NPT_Md5_II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
+ NPT_Md5_II(c,d,a,b,W[ 6],15,0xa3014314UL)
+ NPT_Md5_II(b,c,d,a,W[13],21,0x4e0811a1UL)
+ NPT_Md5_II(a,b,c,d,W[ 4], 6,0xf7537e82UL)
+ NPT_Md5_II(d,a,b,c,W[11],10,0xbd3af235UL)
+ NPT_Md5_II(c,d,a,b,W[ 2],15,0x2ad7d2bbUL)
+ NPT_Md5_II(b,c,d,a,W[ 9],21,0xeb86d391UL)
+
+ // store the variables back into the state
+ m_State[0] += a;
+ m_State[1] += b;
+ m_State[2] += c;
+ m_State[3] += d;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Md5Digest::GetDigest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Md5Digest::GetDigest(NPT_DataBuffer& digest)
+{
+ return ComputeDigest(m_State, 4, false, digest);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HmacDigest
+|
+| compute Digest(key XOR opad, Digest(key XOR ipad, data))
+| key is the MAC key
+| ipad is the byte 0x36 repeated 64 times
+| opad is the byte 0x5c repeated 64 times
+| and data is the data to authenticate
+|
++---------------------------------------------------------------------*/
+class NPT_HmacDigest : public NPT_Digest
+{
+public:
+ NPT_HmacDigest(NPT_Digest::Algorithm algorithm,
+ const NPT_UInt8* key,
+ NPT_Size key_size);
+ ~NPT_HmacDigest();
+
+ // NPT_Digest methods
+ virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size) {
+ return m_InnerDigest->Update(data, data_size);
+ }
+ virtual NPT_Result GetDigest(NPT_DataBuffer& buffer);
+ virtual unsigned int GetSize() { return m_InnerDigest->GetSize(); }
+
+private:
+ NPT_Digest* m_InnerDigest;
+ NPT_Digest* m_OuterDigest;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HmacDigest::NPT_HmacDigest
++---------------------------------------------------------------------*/
+NPT_HmacDigest::NPT_HmacDigest(NPT_Digest::Algorithm algorithm,
+ const NPT_UInt8* key,
+ NPT_Size key_size)
+{
+ NPT_Digest::Create(algorithm, m_InnerDigest);
+ NPT_Digest::Create(algorithm, m_OuterDigest);
+
+ NPT_UInt8 workspace[NPT_BASIC_DIGEST_BLOCK_SIZE];
+
+ // if the key is larger than the block size, use a digest of the key
+ NPT_DataBuffer hk;
+ if (key_size > NPT_BASIC_DIGEST_BLOCK_SIZE) {
+ NPT_Digest* key_digest = NULL;
+ NPT_Digest::Create(algorithm, key_digest);
+ key_digest->Update(key, key_size);
+ key_digest->GetDigest(hk);
+ key = hk.GetData();
+ key_size = hk.GetDataSize();
+ delete key_digest;
+ }
+
+ // compute key XOR ipad
+ for (unsigned int i = 0; i < key_size; i++) {
+ workspace[i] = key[i] ^ 0x36;
+ }
+ for (unsigned int i = key_size; i < NPT_BASIC_DIGEST_BLOCK_SIZE; i++) {
+ workspace[i] = 0x36;
+ }
+
+ // start the inner digest with (key XOR ipad)
+ m_InnerDigest->Update(workspace, NPT_BASIC_DIGEST_BLOCK_SIZE);
+
+ // compute key XOR opad
+ for (unsigned int i = 0; i < key_size; i++) {
+ workspace[i] = key[i] ^ 0x5c;
+ }
+ for (unsigned int i = key_size; i < NPT_BASIC_DIGEST_BLOCK_SIZE; i++) {
+ workspace[i] = 0x5c;
+ }
+
+ // start the outer digest with (key XOR opad)
+ m_OuterDigest->Update(workspace, NPT_BASIC_DIGEST_BLOCK_SIZE);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HmacDigest::~NPT_HmacDigest
++---------------------------------------------------------------------*/
+NPT_HmacDigest::~NPT_HmacDigest()
+{
+ delete m_InnerDigest;
+ delete m_OuterDigest;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HmacDigest::GetDigest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HmacDigest::GetDigest(NPT_DataBuffer& mac)
+{
+ // finish the outer digest with the value of the inner digest
+ NPT_DataBuffer inner;
+ m_InnerDigest->GetDigest(inner);
+ m_OuterDigest->Update(inner.GetData(), inner.GetDataSize());
+
+ // return the value of the outer digest
+ return m_OuterDigest->GetDigest(mac);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Digest::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Digest::Create(Algorithm algorithm, NPT_Digest*& digest)
+{
+ switch (algorithm) {
+ case ALGORITHM_SHA1: digest = new NPT_Sha1Digest(); return NPT_SUCCESS;
+ case ALGORITHM_SHA256: digest = new NPT_Sha256Digest(); return NPT_SUCCESS;
+ case ALGORITHM_MD5: digest = new NPT_Md5Digest(); return NPT_SUCCESS;
+ default: return NPT_ERROR_NOT_SUPPORTED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Hmac::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Hmac::Create(NPT_Digest::Algorithm algorithm,
+ const NPT_UInt8* key,
+ NPT_Size key_size,
+ NPT_Digest*& digest)
+{
+ switch (algorithm) {
+ case NPT_Digest::ALGORITHM_SHA1:
+ case NPT_Digest::ALGORITHM_MD5:
+ digest = new NPT_HmacDigest(algorithm, key, key_size);
+ return NPT_SUCCESS;
+ default: return NPT_ERROR_NOT_SUPPORTED;
+ }
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDigest.h b/lib/libUPnP/Neptune/Source/Core/NptDigest.h
new file mode 100644
index 0000000..85b744c
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDigest.h
@@ -0,0 +1,78 @@
+/*****************************************************************
+|
+| Neptune - Message Digests
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DIGEST_H_
+#define _NPT_DIGEST_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptDataBuffer.h"
+
+/*----------------------------------------------------------------------
+| NPT_Digest
++---------------------------------------------------------------------*/
+class NPT_Digest {
+public:
+ // types
+ typedef enum {
+ ALGORITHM_SHA1,
+ ALGORITHM_SHA256,
+ ALGORITHM_MD5
+ } Algorithm;
+
+ // factory
+ static NPT_Result Create(Algorithm algorithm, NPT_Digest*& digest);
+
+ // methods
+ virtual ~NPT_Digest() {}
+ virtual unsigned int GetSize() = 0;
+ virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size) = 0;
+ virtual NPT_Result GetDigest(NPT_DataBuffer& digest) = 0;
+
+protected:
+ NPT_Digest() {} // don't instantiate directly
+};
+
+class NPT_Hmac {
+public:
+ static NPT_Result Create(NPT_Digest::Algorithm algorithm,
+ const NPT_UInt8* key,
+ NPT_Size key_size,
+ NPT_Digest*& digest);
+
+private:
+ // methods
+ NPT_Hmac() {} // don't instantiate
+};
+
+#endif // _NPT_DIGEST_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDynamicCast.h b/lib/libUPnP/Neptune/Source/Core/NptDynamicCast.h
new file mode 100644
index 0000000..0acab88
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDynamicCast.h
@@ -0,0 +1,89 @@
+/*****************************************************************
+|
+| Neptune - Dynamic Cast Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DYNAMIC_CAST_H_
+#define _NPT_DYNAMIC_CAST_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptCommon.h"
+#include "NptResults.h"
+#include "NptConfig.h"
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_NO_RTTI)
+#define NPT_DYNAMIC_CAST(_class,_object) \
+( ((_object)==0) ? 0 : reinterpret_cast<_class*>((_object)->DynamicCast(&_class::_class_##_class)) )
+#define NPT_IMPLEMENT_DYNAMIC_CAST(_class) \
+static int _class_##_class; \
+virtual void* DynamicCast(const void* class_anchor) { \
+ if (class_anchor == &_class::_class_##_class) { \
+ return static_cast<_class*>(this); \
+ } \
+ return NULL; \
+}
+#define NPT_IMPLEMENT_DYNAMIC_CAST_D(_class,_superclass)\
+static int _class_##_class; \
+virtual void* DynamicCast(const void* class_anchor) { \
+ if (class_anchor == &_class::_class_##_class) { \
+ return static_cast<_class*>(this); \
+ } else { \
+ return _superclass::DynamicCast(class_anchor); \
+ } \
+}
+#define NPT_IMPLEMENT_DYNAMIC_CAST_D2(_class,_superclass,_mixin)\
+static int _class_##_class; \
+virtual void* DynamicCast(const void* class_anchor) { \
+ if (class_anchor == &_class::_class_##_class) { \
+ return static_cast<_class*>(this); \
+ } else { \
+ void* sup = _superclass::DynamicCast(class_anchor); \
+ if (sup) return sup; \
+ return _mixin::DynamicCast(class_anchor); \
+ } \
+}
+#define NPT_DEFINE_DYNAMIC_CAST_ANCHOR(_class) int _class::_class_##_class = 0;
+
+#else
+
+#define NPT_DYNAMIC_CAST(_class,_object) dynamic_cast<_class*>(_object)
+#define NPT_IMPLEMENT_DYNAMIC_CAST(_class)
+#define NPT_IMPLEMENT_DYNAMIC_CAST_D(_class,_superclass)
+#define NPT_IMPLEMENT_DYNAMIC_CAST_D2(_class,_superclass,_mixin)
+#define NPT_DEFINE_DYNAMIC_CAST_ANCHOR(_class)
+
+#endif
+
+#endif // _NPT_DYNAMIC_CAST_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.cpp b/lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.cpp
new file mode 100644
index 0000000..556a4d8
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.cpp
@@ -0,0 +1,36 @@
+/*****************************************************************
+|
+| Neptune - Dynamic Libraries
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptDynamicLibraries.h"
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.h b/lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.h
new file mode 100644
index 0000000..50186cc
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptDynamicLibraries.h
@@ -0,0 +1,84 @@
+/*****************************************************************
+|
+| Neptune - Dynamic Libraries
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DYNAMIC_LIBRARIES_H_
+#define _NPT_DYNAMIC_LIBRARIES_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_DYANMIC_LIBRARY_LOAD_FLAG_NOW 1
+
+/*----------------------------------------------------------------------
+| NPT_DynamicLibraryInterface
++---------------------------------------------------------------------*/
+class NPT_DynamicLibraryInterface
+{
+public:
+ virtual ~NPT_DynamicLibraryInterface() {}
+ virtual NPT_Result FindSymbol(const char* name, void*& symbol) = 0;
+ virtual NPT_Result Unload() = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_DynamicLibrary
++---------------------------------------------------------------------*/
+class NPT_DynamicLibrary : public NPT_DynamicLibraryInterface
+{
+public:
+ // class methods
+ static NPT_Result Load(const char* name, NPT_Flags flags, NPT_DynamicLibrary*& library);
+
+ // destructor
+ ~NPT_DynamicLibrary() override { delete m_Delegate; }
+
+ // NPT_DynamicLibraryInterface methods
+ NPT_Result FindSymbol(const char* name, void*& symbol) override {
+ return m_Delegate->FindSymbol(name, symbol);
+ }
+ NPT_Result Unload() override {
+ return m_Delegate->Unload();
+ }
+
+private:
+ // methods
+ NPT_DynamicLibrary(NPT_DynamicLibraryInterface* delegate) : m_Delegate(delegate) {}
+
+ // members
+ NPT_DynamicLibraryInterface* m_Delegate;
+};
+
+#endif // _NPT_DYNAMIC_LIBRARIES_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptFile.cpp b/lib/libUPnP/Neptune/Source/Core/NptFile.cpp
new file mode 100644
index 0000000..e88e180
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptFile.cpp
@@ -0,0 +1,409 @@
+/*****************************************************************
+|
+| Neptune - Files
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptFile.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+#include "NptStreams.h"
+#include "NptDataBuffer.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.file")
+
+/*----------------------------------------------------------------------
+| NPT_FilePath::BaseName
++---------------------------------------------------------------------*/
+NPT_String
+NPT_FilePath::BaseName(const char* path, bool with_extension /* = true */)
+{
+ NPT_String result = path;
+ int separator = result.ReverseFind(Separator);
+ if (separator >= 0) {
+ result = path+separator+NPT_StringLength(Separator);
+ }
+
+ if (!with_extension) {
+ int dot = result.ReverseFind('.');
+ if (dot >= 0) {
+ result.SetLength(dot);
+ }
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_FilePath::DirName
++---------------------------------------------------------------------*/
+NPT_String
+NPT_FilePath::DirName(const char* path)
+{
+ NPT_String result = path;
+ int separator = result.ReverseFind(Separator);
+ if (separator >= 0) {
+ if (separator == 0) {
+ result.SetLength(NPT_StringLength(Separator));
+ } else {
+ result.SetLength(separator);
+ }
+ } else {
+ result.SetLength(0);
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_FilePath::FileExtension
++---------------------------------------------------------------------*/
+NPT_String
+NPT_FilePath::FileExtension(const char* path)
+{
+ NPT_String result = path;
+ int separator = result.ReverseFind('.');
+ if (separator >= 0) {
+ result = path+separator;
+ } else {
+ result.SetLength(0);
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_FilePath::Create
++---------------------------------------------------------------------*/
+NPT_String
+NPT_FilePath::Create(const char* directory, const char* basename)
+{
+ if (!directory || NPT_StringLength(directory) == 0) return basename;
+ if (!basename || NPT_StringLength(basename) == 0) return directory;
+
+ NPT_String result = directory;
+ if (!result.EndsWith(Separator) && basename[0] != Separator[0]) {
+ result += Separator;
+ }
+ result += basename;
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::CreateDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::CreateDir(const char* path, bool create_intermediate_dirs)
+{
+ NPT_String full_path = path;
+
+ // normalize path separators
+ full_path.Replace((NPT_FilePath::Separator[0] == '/')?'\\':'/', NPT_FilePath::Separator);
+
+ // remove superfluous delimiters at the end
+ full_path.TrimRight(NPT_FilePath::Separator);
+
+ // create intermediate directories if needed
+ if (create_intermediate_dirs) {
+ NPT_String dir_path;
+
+ // look for the next path separator
+ int separator = full_path.Find(NPT_FilePath::Separator, 1);
+ while (separator > 0) {
+ // copy the path up to the separator
+ dir_path = full_path.SubString(0, separator);
+
+ // create the directory non recursively
+ NPT_CHECK_WARNING(NPT_File::CreateDir(dir_path, false));
+
+ // look for the next delimiter
+ separator = full_path.Find(NPT_FilePath::Separator, separator + 1);
+ }
+ }
+
+ // create the final directory
+ NPT_Result result = NPT_File::CreateDir(full_path);
+
+ // return error only if file didn't exist
+ if (NPT_FAILED(result) && result != NPT_ERROR_FILE_ALREADY_EXISTS) {
+ return result;
+ }
+
+ return NPT_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+| NPT_File::RemoveDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::RemoveDir(const char* path, bool force_if_not_empty)
+{
+ NPT_String root_path = path;
+
+ // normalize path separators
+ root_path.Replace((NPT_FilePath::Separator[0] == '/')?'\\':'/', NPT_FilePath::Separator);
+
+ // remove superfluous delimiters at the end
+ root_path.TrimRight(NPT_FilePath::Separator);
+
+ // remove all entries in the directory if required
+ if (force_if_not_empty) {
+ // enumerate all entries
+ NPT_File dir(root_path);
+ NPT_List<NPT_String> entries;
+ NPT_CHECK_WARNING(dir.ListDir(entries));
+ for (NPT_List<NPT_String>::Iterator it = entries.GetFirstItem(); it; ++it) {
+ NPT_File::Remove(NPT_FilePath::Create(root_path, *it), true);
+ }
+ }
+
+ // remove the (now empty) directory
+ return NPT_File::RemoveDir(root_path);
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Load(const char* path, NPT_DataBuffer& buffer, NPT_FileInterface::OpenMode mode)
+{
+ // create and open the file
+ NPT_File file(path);
+ NPT_Result result = file.Open(mode);
+ if (NPT_FAILED(result)) return result;
+
+ // load the file
+ result = file.Load(buffer);
+
+ // close the file
+ file.Close();
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Load(const char* path, NPT_String& data, NPT_FileInterface::OpenMode mode)
+{
+ NPT_DataBuffer buffer;
+
+ // reset ouput params
+ data = "";
+
+ // create and open the file
+ NPT_File file(path);
+ NPT_Result result = file.Open(mode);
+ if (NPT_FAILED(result)) return result;
+
+ // load the file
+ result = file.Load(buffer);
+
+ if (NPT_SUCCEEDED(result) && buffer.GetDataSize() > 0) {
+ data.Assign((const char*)buffer.GetData(), buffer.GetDataSize());
+ data.SetLength(buffer.GetDataSize());
+ }
+
+ // close the file
+ file.Close();
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Save
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Save(const char* filename, NPT_String& data)
+{
+ NPT_DataBuffer buffer(data.GetChars(), data.GetLength());
+ return NPT_File::Save(filename, buffer);
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Save
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Save(const char* filename, const NPT_DataBuffer& buffer)
+{
+ // create and open the file
+ NPT_File file(filename);
+ NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_WRITE | NPT_FILE_OPEN_MODE_CREATE | NPT_FILE_OPEN_MODE_TRUNCATE);
+ if (NPT_FAILED(result)) return result;
+
+ // load the file
+ result = file.Save(buffer);
+
+ // close the file
+ file.Close();
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Load(NPT_DataBuffer& buffer)
+{
+ NPT_InputStreamReference input;
+
+ // get the input stream for the file
+ NPT_CHECK_WARNING(GetInputStream(input));
+
+ // read the stream
+ return input->Load(buffer);
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Save
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Save(const NPT_DataBuffer& buffer)
+{
+ NPT_OutputStreamReference output;
+
+ // get the output stream for the file
+ NPT_CHECK_WARNING(GetOutputStream(output));
+
+ // write to the stream
+ return output->WriteFully(buffer.GetData(), buffer.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetInfo(NPT_FileInfo& info)
+{
+ if (m_IsSpecial) {
+ info.m_Type = NPT_FileInfo::FILE_TYPE_SPECIAL;
+ info.m_Size = 0;
+ info.m_Attributes = 0;
+ info.m_AttributesMask = 0;
+ return NPT_SUCCESS;
+ }
+ return GetInfo(m_Path.GetChars(), &info);
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetSize(NPT_LargeSize& size)
+{
+ // default value
+ size = 0;
+
+ // get the file info
+ NPT_FileInfo info;
+ NPT_Result result = GetInfo(info);
+ if (NPT_FAILED(result)) {
+ return result;
+ }
+
+ switch (info.m_Type) {
+ case NPT_FileInfo::FILE_TYPE_DIRECTORY: {
+ NPT_List<NPT_String> entries;
+ NPT_CHECK_WARNING(ListDir(entries));
+ size = entries.GetItemCount();
+ break;
+ }
+
+ case NPT_FileInfo::FILE_TYPE_REGULAR:
+ case NPT_FileInfo::FILE_TYPE_OTHER:
+ size = info.m_Size;
+ return NPT_SUCCESS;
+
+ default:
+ break;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetSize(const char* path, NPT_LargeSize& size)
+{
+ NPT_File file(path);
+ return file.GetSize(size);
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Remove
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Remove(const char* path, bool recurse /* = false */)
+{
+ NPT_FileInfo info;
+
+ // make sure the path exists
+ NPT_CHECK_WARNING(GetInfo(path, &info));
+
+ if (info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY) {
+ return RemoveDir(path, recurse);
+ } else {
+ return RemoveFile(path);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Rename
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Rename(const char* path)
+{
+ NPT_Result result = Rename(m_Path.GetChars(), path);
+ if (NPT_SUCCEEDED(result)) {
+ m_Path = path;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::ListDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::ListDir(NPT_List<NPT_String>& entries)
+{
+ entries.Clear();
+ return ListDir(m_Path.GetChars(), entries);
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptFile.h b/lib/libUPnP/Neptune/Source/Core/NptFile.h
new file mode 100644
index 0000000..c6b2db2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptFile.h
@@ -0,0 +1,229 @@
+/*****************************************************************
+|
+| Neptune - Files
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_FILE_H_
+#define _NPT_FILE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptStreams.h"
+#include "NptTime.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_NO_SUCH_FILE = NPT_ERROR_BASE_FILE - 0;
+const int NPT_ERROR_FILE_NOT_OPEN = NPT_ERROR_BASE_FILE - 1;
+const int NPT_ERROR_FILE_BUSY = NPT_ERROR_BASE_FILE - 2;
+const int NPT_ERROR_FILE_ALREADY_OPEN = NPT_ERROR_BASE_FILE - 3;
+const int NPT_ERROR_FILE_NOT_READABLE = NPT_ERROR_BASE_FILE - 4;
+const int NPT_ERROR_FILE_NOT_WRITABLE = NPT_ERROR_BASE_FILE - 5;
+const int NPT_ERROR_FILE_NOT_DIRECTORY = NPT_ERROR_BASE_FILE - 6;
+const int NPT_ERROR_FILE_ALREADY_EXISTS = NPT_ERROR_BASE_FILE - 7;
+const int NPT_ERROR_FILE_NOT_ENOUGH_SPACE = NPT_ERROR_BASE_FILE - 8;
+const int NPT_ERROR_DIRECTORY_NOT_EMPTY = NPT_ERROR_BASE_FILE - 9;
+
+/**
+ * File open modes.
+ * Use a combination of these flags to indicate how a file should be opened
+ * Note all combinations of flags are valid or meaningful:
+ * If NPT_FILE_OPEN_MODE_WRITE is not set, then NPT_FILE_OPEN_MODE_CREATE,
+ * NPT_FILE_OPEN_MODE_TRUNCATE and NPT_FILE_OPEN_MODE_APPEND are ignored.
+ * If NPT_FILE_OPEN_MODE_APPEND is set, then NPT_FILE_OPEN_MODE_CREATE is
+ * automatically implied whether it is set or not.
+ * NPT_FILE_OPEN_MODE_CREATE and NPT_FILE_OPEN_MODE_TRUNCATE imply each
+ * other (if one is set, the other one is automatically implied)
+ */
+const unsigned int NPT_FILE_OPEN_MODE_READ = 0x01;
+const unsigned int NPT_FILE_OPEN_MODE_WRITE = 0x02;
+const unsigned int NPT_FILE_OPEN_MODE_CREATE = 0x04;
+const unsigned int NPT_FILE_OPEN_MODE_TRUNCATE = 0x08;
+const unsigned int NPT_FILE_OPEN_MODE_UNBUFFERED = 0x10;
+const unsigned int NPT_FILE_OPEN_MODE_APPEND = 0x20;
+
+const unsigned int NPT_FILE_ATTRIBUTE_READ_ONLY = 0x01;
+const unsigned int NPT_FILE_ATTRIBUTE_LINK = 0x02;
+
+#define NPT_FILE_STANDARD_INPUT "@STDIN"
+#define NPT_FILE_STANDARD_OUTPUT "@STDOUT"
+#define NPT_FILE_STANDARD_ERROR "@STDERR"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class NPT_DataBuffer;
+
+/*----------------------------------------------------------------------
+| NPT_FileInfo
++---------------------------------------------------------------------*/
+struct NPT_FileInfo
+{
+ // types
+ typedef enum {
+ FILE_TYPE_NONE,
+ FILE_TYPE_REGULAR,
+ FILE_TYPE_DIRECTORY,
+ FILE_TYPE_SPECIAL,
+ FILE_TYPE_OTHER
+ } FileType;
+
+ // constructor
+ NPT_FileInfo() : m_Type(FILE_TYPE_NONE), m_Size(0), m_AttributesMask(0), m_Attributes(0) {}
+
+ // members
+ FileType m_Type;
+ NPT_UInt64 m_Size;
+ NPT_Flags m_AttributesMask;
+ NPT_Flags m_Attributes;
+ NPT_TimeStamp m_CreationTime;
+ NPT_TimeStamp m_ModificationTime;
+};
+
+/*----------------------------------------------------------------------
+| NPT_FilePath
++---------------------------------------------------------------------*/
+class NPT_FilePath
+{
+public:
+ // class members
+ static const char* const Separator;
+
+ // class methods
+ static NPT_String BaseName(const char* path, bool with_extension = true);
+ static NPT_String DirName(const char* path);
+ static NPT_String FileExtension(const char* path);
+ static NPT_String Create(const char* directory, const char* base);
+
+private:
+ NPT_FilePath() {} // this class can't have instances
+};
+
+/*----------------------------------------------------------------------
+| NPT_FileInterface
++---------------------------------------------------------------------*/
+class NPT_FileInterface
+{
+public:
+ // types
+ typedef unsigned int OpenMode;
+
+ // constructors and destructor
+ virtual ~NPT_FileInterface() {}
+
+ // methods
+ virtual NPT_Result Open(OpenMode mode) = 0;
+ virtual NPT_Result Close() = 0;
+ virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream) = 0;
+ virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_File
++---------------------------------------------------------------------*/
+class NPT_File : public NPT_FileInterface
+{
+public:
+ // class methods
+ static NPT_Result GetRoots(NPT_List<NPT_String>& roots);
+ static NPT_Result GetSize(const char* path, NPT_LargeSize &size);
+ static NPT_Result GetInfo(const char* path, NPT_FileInfo* info = NULL);
+ static bool Exists(const char* path) { return NPT_SUCCEEDED(GetInfo(path)); }
+ static NPT_Result Remove(const char* path, bool recurse = false);
+ static NPT_Result RemoveFile(const char* path);
+ static NPT_Result RemoveDir(const char* path);
+ static NPT_Result RemoveDir(const char* path, bool force_if_not_empty);
+ static NPT_Result Rename(const char* from_path, const char* to_path);
+ static NPT_Result ListDir(const char* path, NPT_List<NPT_String>& entries, NPT_Ordinal start = 0, NPT_Cardinal count = 0);
+ static NPT_Result CreateDir(const char* path);
+ static NPT_Result CreateDir(const char* path, bool create_intermediate_dirs);
+ static NPT_Result GetWorkingDir(NPT_String& path);
+ static NPT_Result Load(const char* path, NPT_DataBuffer& buffer, NPT_FileInterface::OpenMode mode = NPT_FILE_OPEN_MODE_READ);
+ static NPT_Result Load(const char* path, NPT_String& data, NPT_FileInterface::OpenMode mode = NPT_FILE_OPEN_MODE_READ);
+ static NPT_Result Save(const char* path, NPT_String& data);
+ static NPT_Result Save(const char* path, const NPT_DataBuffer& buffer);
+
+ // constructors and destructor
+ NPT_File(const char* path);
+ ~NPT_File() override { delete m_Delegate; }
+
+ // methods
+ NPT_Result Load(NPT_DataBuffer& buffer);
+ NPT_Result Save(const NPT_DataBuffer& buffer);
+ const NPT_String& GetPath() { return m_Path; }
+ NPT_Result GetSize(NPT_LargeSize &size);
+ NPT_Result GetInfo(NPT_FileInfo& info);
+ NPT_Result ListDir(NPT_List<NPT_String>& entries);
+ NPT_Result Rename(const char* path);
+
+ // NPT_FileInterface methods
+ NPT_Result Open(OpenMode mode) override {
+ return m_Delegate->Open(mode);
+ }
+ NPT_Result Close() override {
+ return m_Delegate->Close();
+ }
+ NPT_Result GetInputStream(NPT_InputStreamReference& stream) override {
+ return m_Delegate->GetInputStream(stream);
+ }
+ NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) override {
+ return m_Delegate->GetOutputStream(stream);
+ }
+
+ // operators
+ NPT_File& operator=(const NPT_File& file);
+
+protected:
+ // members
+ NPT_FileInterface* m_Delegate;
+ NPT_String m_Path;
+ bool m_IsSpecial;
+};
+
+/*----------------------------------------------------------------------
+| NPT_FileDateComparator
++---------------------------------------------------------------------*/
+class NPT_FileDateComparator {
+public:
+ NPT_FileDateComparator(const char* directory) : m_Directory(directory) {}
+ NPT_Int32 operator()(const NPT_String& file1, const NPT_String& file2) const {
+ NPT_FileInfo info1, info2;
+ if (NPT_FAILED(NPT_File::GetInfo(NPT_FilePath::Create(m_Directory, file1), &info1))) return -1;
+ if (NPT_FAILED(NPT_File::GetInfo(NPT_FilePath::Create(m_Directory, file2), &info2))) return -1;
+ return (info1.m_ModificationTime == info2.m_ModificationTime) ? 0 : (info1.m_ModificationTime < info2.m_ModificationTime ? -1 : 1);
+ }
+
+private:
+ NPT_String m_Directory;
+};
+
+#endif // _NPT_FILE_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptHash.cpp b/lib/libUPnP/Neptune/Source/Core/NptHash.cpp
new file mode 100644
index 0000000..05d6aa4
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptHash.cpp
@@ -0,0 +1,137 @@
+/*****************************************************************
+|
+| Neptune - Hashing
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+#include "NptHash.h"
+
+/*----------------------------------------------------------------------
+| local constants
++---------------------------------------------------------------------*/
+// 32 bit magic FNV-1a prime
+const NPT_UInt32 NPT_FNV_32_PRIME = 0x01000193;
+
+/*----------------------------------------------------------------------
+| NPT_Fnv1aHash32
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_Fnv1aHash32(const NPT_UInt8* data, NPT_Size data_size, NPT_UInt32 hash_init)
+{
+ const NPT_UInt8* data_end = data + data_size;
+ NPT_UInt32 hash_value = hash_init;
+
+ while (data < data_end) {
+ hash_value ^= (NPT_UInt32)*data++;
+
+#if defined(NPT_CONFIG_FNV_HASH_USE_SHIFT_MUL)
+ hash_value += (hash_value<<1) + (hash_value<<4) + (hash_value<<7) + (hash_value<<8) + (hash_value<<24);
+#else
+ hash_value *= NPT_FNV_32_PRIME;
+#endif
+ }
+
+ return hash_value;
+}
+
+
+/*----------------------------------------------------------------------
+| NPT_Fnv1aHashStr32
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_Fnv1aHashStr32(const char* data, NPT_UInt32 hash_init)
+{
+ NPT_UInt32 hash_value = hash_init;
+
+ while (*data) {
+ hash_value ^= (NPT_UInt32)*data++;
+
+#if defined(NPT_CONFIG_FNV_HASH_USE_SHIFT_MUL)
+ hash_value += (hash_value<<1) + (hash_value<<4) + (hash_value<<7) + (hash_value<<8) + (hash_value<<24);
+#else
+ hash_value *= NPT_FNV_32_PRIME;
+#endif
+ }
+
+ return hash_value;
+}
+
+/*----------------------------------------------------------------------
+| NPT_FnvHash32
++---------------------------------------------------------------------*/
+// 64 bit magic FNV-1a prime
+const NPT_UInt64 NPT_FNV_64_PRIME = 0x100000001b3ULL;
+
+/*----------------------------------------------------------------------
+| NPT_Fnv1aHash64
++---------------------------------------------------------------------*/
+NPT_UInt64
+NPT_Fnv1aHash64(const NPT_UInt8* data, NPT_Size data_size, NPT_UInt64 hash_init)
+{
+ const NPT_UInt8* data_end = data + data_size;
+ NPT_UInt64 hash_value = hash_init;
+
+ while (data < data_end) {
+ hash_value ^= (NPT_UInt64)*data++;
+
+#if defined(NPT_CONFIG_FNV_HASH_USE_SHIFT_MUL)
+ hash_value += (hash_value << 1) + (hash_value << 4) + (hash_value << 5) + (hash_value << 7) + (hash_value << 8) + (hash_value << 40);
+#else
+ hash_value *= NPT_FNV_64_PRIME;
+#endif
+ }
+
+ return hash_value;
+}
+
+
+/*----------------------------------------------------------------------
+| NPT_Fnv1aHashStr64
++---------------------------------------------------------------------*/
+NPT_UInt64
+NPT_Fnv1aHashStr64(const char* data, NPT_UInt64 hash_init)
+{
+ NPT_UInt64 hash_value = hash_init;
+
+ while (*data) {
+ hash_value ^= (NPT_UInt64)*data++;
+
+#if defined(NPT_CONFIG_FNV_HASH_USE_SHIFT_MUL)
+ hash_value += (hash_value << 1) + (hash_value << 4) + (hash_value << 5) + (hash_value << 7) + (hash_value << 8) + (hash_value << 40);
+#else
+ hash_value *= NPT_FNV_64_PRIME;
+#endif
+ }
+
+ return hash_value;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptHash.h b/lib/libUPnP/Neptune/Source/Core/NptHash.h
new file mode 100644
index 0000000..d7b8776
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptHash.h
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+| Neptune - Hashing
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_HASH_H_
+#define _NPT_HASH_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| Fowler/Noll/Vo FNV-1a hash functions
++---------------------------------------------------------------------*/
+const NPT_UInt32 NPT_FNV1A_32_INIT = ((NPT_UInt32)0x811c9dc5);
+NPT_UInt32 NPT_Fnv1aHash32(const NPT_UInt8* data, NPT_Size data_size, NPT_UInt32 hash_init=NPT_FNV1A_32_INIT);
+NPT_UInt32 NPT_Fnv1aHashStr32(const char* data, NPT_UInt32 hash_init=NPT_FNV1A_32_INIT);
+const NPT_UInt64 NPT_FNV1A_64_INIT = ((NPT_UInt64)0xcbf29ce484222325ULL);
+NPT_UInt64 NPT_Fnv1aHash64(const NPT_UInt8* data, NPT_Size data_size, NPT_UInt64 hash_init=NPT_FNV1A_64_INIT);
+NPT_UInt64 NPT_Fnv1aHashStr64(const char* data, NPT_UInt64 hash_init=NPT_FNV1A_64_INIT);
+
+/*----------------------------------------------------------------------
+| NPT_Hash
++---------------------------------------------------------------------*/
+template <typename K>
+struct NPT_Hash
+{
+};
+
+template <>
+struct NPT_Hash<const char*>
+{
+ NPT_UInt32 operator()(const char* s) const { return NPT_Fnv1aHashStr32(s); }
+};
+
+template <>
+struct NPT_Hash<char*>
+{
+ NPT_UInt32 operator()(char* s) const { return NPT_Fnv1aHashStr32(s); }
+};
+
+template <>
+struct NPT_Hash<int>
+{
+ NPT_UInt32 operator()(int i) const { return NPT_Fnv1aHash32(reinterpret_cast<const NPT_UInt8*>(&i), sizeof(int)); }
+};
+
+template <>
+struct NPT_Hash<unsigned int>
+{
+ NPT_UInt32 operator()(unsigned int i) const { return NPT_Fnv1aHash32(reinterpret_cast<const NPT_UInt8*>(&i), sizeof(int)); }
+};
+
+#endif // _NPT_HASH_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptHttp.cpp b/lib/libUPnP/Neptune/Source/Core/NptHttp.cpp
new file mode 100644
index 0000000..db2c507
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptHttp.cpp
@@ -0,0 +1,3483 @@
+/*****************************************************************
+|
+| Neptune - HTTP Protocol
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptHttp.h"
+#include "NptSockets.h"
+#include "NptBufferedStreams.h"
+#include "NptDebug.h"
+#include "NptVersion.h"
+#include "NptUtils.h"
+#include "NptFile.h"
+#include "NptSystem.h"
+#include "NptLogging.h"
+#include "NptTls.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.http")
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const char* const NPT_HTTP_DEFAULT_403_HTML = "<html><head><title>403 Forbidden</title></head><body><h1>Forbidden</h1><p>Access to this URL is forbidden.</p></html>";
+const char* const NPT_HTTP_DEFAULT_404_HTML = "<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></html>";
+const char* const NPT_HTTP_DEFAULT_500_HTML = "<html><head><title>500 Internal Error</title></head><body><h1>Internal Error</h1><p>The server encountered an unexpected condition which prevented it from fulfilling the request.</p></html>";
+
+/*----------------------------------------------------------------------
+| NPT_HttpUrl::NPT_HttpUrl
++---------------------------------------------------------------------*/
+NPT_HttpUrl::NPT_HttpUrl(const char* url, bool ignore_scheme) :
+ NPT_Url(url)
+{
+ if (!ignore_scheme) {
+ if (GetSchemeId() != NPT_Uri::SCHEME_ID_HTTP &&
+ GetSchemeId() != NPT_Uri::SCHEME_ID_HTTPS) {
+ Reset();
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpUrl::NPT_HttpUrl
++---------------------------------------------------------------------*/
+NPT_HttpUrl::NPT_HttpUrl(const char* host,
+ NPT_UInt16 port,
+ const char* path,
+ const char* query,
+ const char* fragment) :
+ NPT_Url("http", host, port, path, query, fragment)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpUrl::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_HttpUrl::ToString(bool with_fragment) const
+{
+ NPT_UInt16 default_port;
+ switch (m_SchemeId) {
+ case SCHEME_ID_HTTP: default_port = NPT_HTTP_DEFAULT_PORT; break;
+ case SCHEME_ID_HTTPS: default_port = NPT_HTTPS_DEFAULT_PORT; break;
+ default: default_port = 0;
+ }
+ return NPT_Url::ToStringWithDefaultPort(default_port, with_fragment);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeader::NPT_HttpHeader
++---------------------------------------------------------------------*/
+NPT_HttpHeader::NPT_HttpHeader(const char* name, const char* value):
+ m_Name(name),
+ m_Value(value)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeader::~NPT_HttpHeader
++---------------------------------------------------------------------*/
+NPT_HttpHeader::~NPT_HttpHeader()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeader::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeader::Emit(NPT_OutputStream& stream) const
+{
+ stream.WriteString(m_Name);
+ stream.WriteFully(": ", 2);
+ stream.WriteString(m_Value);
+ stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+ NPT_LOG_FINEST_2("header %s: %s", m_Name.GetChars(), m_Value.GetChars());
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeader::SetName
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeader::SetName(const char* name)
+{
+ m_Name = name;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeader::~NPT_HttpHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeader::SetValue(const char* value)
+{
+ m_Value = value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::NPT_HttpHeaders
++---------------------------------------------------------------------*/
+NPT_HttpHeaders::NPT_HttpHeaders()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::~NPT_HttpHeaders
++---------------------------------------------------------------------*/
+NPT_HttpHeaders::~NPT_HttpHeaders()
+{
+ m_Headers.Apply(NPT_ObjectDeleter<NPT_HttpHeader>());
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::Parse(NPT_BufferedInputStream& stream)
+{
+ NPT_String header_name;
+ NPT_String header_value;
+ bool header_pending = false;
+ NPT_String line;
+
+ while (NPT_SUCCEEDED(stream.ReadLine(line, NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH))) {
+ if (line.GetLength() == 0) {
+ // empty line, end of headers
+ break;
+ }
+ if (header_pending && (line[0] == ' ' || line[0] == '\t')) {
+ // continuation (folded header)
+ header_value.Append(line.GetChars()+1, line.GetLength()-1);
+ } else {
+ // add the pending header to the list
+ if (header_pending) {
+ header_value.Trim();
+ AddHeader(header_name, header_value);
+ header_pending = false;
+ NPT_LOG_FINEST_2("header - %s: %s",
+ header_name.GetChars(),
+ header_value.GetChars());
+ }
+
+ // find the colon separating the name and the value
+ int colon_index = line.Find(':');
+ if (colon_index < 1) {
+ // invalid syntax, ignore
+ continue;
+ }
+ header_name = line.Left(colon_index);
+
+ // the field value starts at the first non-whitespace
+ const char* value = line.GetChars()+colon_index+1;
+ while (*value == ' ' || *value == '\t') {
+ value++;
+ }
+ header_value = value;
+
+ // the header is pending
+ header_pending = true;
+ }
+ }
+
+ // if we have a header pending, add it now
+ if (header_pending) {
+ header_value.Trim();
+ AddHeader(header_name, header_value);
+ NPT_LOG_FINEST_2("header %s: %s",
+ header_name.GetChars(),
+ header_value.GetChars());
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::Emit(NPT_OutputStream& stream) const
+{
+ // for each header in the list
+ NPT_List<NPT_HttpHeader*>::Iterator header = m_Headers.GetFirstItem();
+ while (header) {
+ // emit the header
+ NPT_CHECK_WARNING((*header)->Emit(stream));
+ ++header;
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::GetHeader
++---------------------------------------------------------------------*/
+NPT_HttpHeader*
+NPT_HttpHeaders::GetHeader(const char* name) const
+{
+ // check args
+ if (name == NULL) return NULL;
+
+ // find a matching header
+ NPT_List<NPT_HttpHeader*>::Iterator header = m_Headers.GetFirstItem();
+ while (header) {
+ if ((*header)->GetName().Compare(name, true) == 0) {
+ return *header;
+ }
+ ++header;
+ }
+
+ // not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::AddHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::AddHeader(const char* name, const char* value)
+{
+ return m_Headers.Add(new NPT_HttpHeader(name, value));
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::RemoveHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::RemoveHeader(const char* name)
+{
+ bool found = false;
+
+ NPT_HttpHeader* header = NULL;
+ while ((header = GetHeader(name))) {
+ m_Headers.Remove(header);
+ delete header;
+ found = true;
+ }
+ return found?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::SetHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::SetHeader(const char* name, const char* value, bool replace)
+{
+ NPT_HttpHeader* header = GetHeader(name);
+ if (header == NULL) {
+ return AddHeader(name, value);
+ } else if (replace) {
+ return header->SetValue(value);
+ } else {
+ return NPT_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders::GetHeaderValue
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_HttpHeaders::GetHeaderValue(const char* name) const
+{
+ NPT_HttpHeader* header = GetHeader(name);
+ if (header == NULL) {
+ return NULL;
+ } else {
+ return &header->GetValue();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntityBodyInputStream
++---------------------------------------------------------------------*/
+class NPT_HttpEntityBodyInputStream : public NPT_InputStream
+{
+public:
+ // constructor and desctructor
+ NPT_HttpEntityBodyInputStream(NPT_BufferedInputStreamReference& source,
+ NPT_LargeSize size,
+ bool size_is_known,
+ bool chunked,
+ NPT_HttpClient::Connection* connection,
+ bool should_persist);
+ ~NPT_HttpEntityBodyInputStream() override;
+
+ // methods
+ bool SizeIsKnown() { return m_SizeIsKnown; }
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result Seek(NPT_Position /*offset*/) override {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ NPT_Result Tell(NPT_Position& offset) override {
+ offset = m_Position;
+ return NPT_SUCCESS;
+ }
+ NPT_Result GetSize(NPT_LargeSize& size) override {
+ size = m_Size;
+ return NPT_SUCCESS;
+ }
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+private:
+ // methods
+ virtual void OnFullyRead();
+
+ // members
+ NPT_LargeSize m_Size;
+ bool m_SizeIsKnown;
+ bool m_Chunked;
+ NPT_HttpClient::Connection* m_Connection;
+ bool m_ShouldPersist;
+ NPT_Position m_Position;
+ NPT_InputStreamReference m_Source;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntityBodyInputStream::NPT_HttpEntityBodyInputStream
++---------------------------------------------------------------------*/
+NPT_HttpEntityBodyInputStream::NPT_HttpEntityBodyInputStream(
+ NPT_BufferedInputStreamReference& source,
+ NPT_LargeSize size,
+ bool size_is_known,
+ bool chunked,
+ NPT_HttpClient::Connection* connection,
+ bool should_persist) :
+ m_Size(size),
+ m_SizeIsKnown(size_is_known),
+ m_Chunked(chunked),
+ m_Connection(connection),
+ m_ShouldPersist(should_persist),
+ m_Position(0)
+{
+ if (size_is_known && size == 0) {
+ OnFullyRead();
+ } else {
+ if (chunked) {
+ m_Source = NPT_InputStreamReference(new NPT_HttpChunkedInputStream(source));
+ } else {
+ m_Source = source;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntityBodyInputStream::~NPT_HttpEntityBodyInputStream
++---------------------------------------------------------------------*/
+NPT_HttpEntityBodyInputStream::~NPT_HttpEntityBodyInputStream()
+{
+ delete m_Connection;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntityBodyInputStream::OnFullyRead
++---------------------------------------------------------------------*/
+void
+NPT_HttpEntityBodyInputStream::OnFullyRead()
+{
+ m_Source = NULL;
+ if (m_Connection && m_ShouldPersist) {
+ m_Connection->Recycle();
+ m_Connection = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntityBodyInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntityBodyInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ if (bytes_read) *bytes_read = 0;
+
+ // return now if we've already reached the end
+ if (m_Source.IsNull()) return NPT_ERROR_EOS;
+
+ // clamp to the max possible read size
+ if (!m_Chunked && m_SizeIsKnown) {
+ NPT_LargeSize max_can_read = m_Size-m_Position;
+ if (max_can_read == 0) return NPT_ERROR_EOS;
+ if (bytes_to_read > max_can_read) bytes_to_read = (NPT_Size)max_can_read;
+ }
+
+ // read from the source
+ NPT_Size source_bytes_read = 0;
+ NPT_Result result = m_Source->Read(buffer, bytes_to_read, &source_bytes_read);
+ if (NPT_SUCCEEDED(result)) {
+ m_Position += source_bytes_read;
+ if (bytes_read) *bytes_read = source_bytes_read;
+ }
+
+ // check if we've reached the end
+ if (result == NPT_ERROR_EOS || (m_SizeIsKnown && (m_Position == m_Size))) {
+ OnFullyRead();
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntityBodyInputStream::GetAvaialble
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntityBodyInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ if (m_Source.IsNull()) {
+ available = 0;
+ return NPT_SUCCESS;
+ }
+ NPT_Result result = m_Source->GetAvailable(available);
+ if (NPT_FAILED(result)) {
+ available = 0;
+ return result;
+ }
+ if (available > m_Size-m_Position) {
+ available = m_Size-m_Position;
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::NPT_HttpEntity
++---------------------------------------------------------------------*/
+NPT_HttpEntity::NPT_HttpEntity() :
+ m_ContentLength(0),
+ m_ContentLengthIsKnown(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::NPT_HttpEntity
++---------------------------------------------------------------------*/
+NPT_HttpEntity::NPT_HttpEntity(const NPT_HttpHeaders& headers) :
+ m_ContentLength(0),
+ m_ContentLengthIsKnown(false)
+{
+ SetHeaders(headers);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetHeaders
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetHeaders(const NPT_HttpHeaders& headers)
+{
+ NPT_HttpHeader* header;
+
+ // Content-Length
+ header = headers.GetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH);
+ if (header != NULL) {
+ m_ContentLengthIsKnown = true;
+ NPT_LargeSize length;
+ if (NPT_SUCCEEDED(header->GetValue().ToInteger64(length))) {
+ m_ContentLength = length;
+ } else {
+ m_ContentLength = 0;
+ }
+ }
+
+ // Content-Type
+ header = headers.GetHeader(NPT_HTTP_HEADER_CONTENT_TYPE);
+ if (header != NULL) {
+ m_ContentType = header->GetValue();
+ }
+
+ // Content-Encoding
+ header = headers.GetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING);
+ if (header != NULL) {
+ m_ContentEncoding = header->GetValue();
+ }
+
+ // Transfer-Encoding
+ header = headers.GetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING);
+ if (header != NULL) {
+ m_TransferEncoding = header->GetValue();
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::~NPT_HttpEntity
++---------------------------------------------------------------------*/
+NPT_HttpEntity::~NPT_HttpEntity()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::GetInputStream(NPT_InputStreamReference& stream)
+{
+ // reset output params first
+ stream = NULL;
+
+ if (m_InputStream.IsNull()) return NPT_FAILURE;
+
+ stream = m_InputStream;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetInputStream(const NPT_InputStreamReference& stream,
+ bool update_content_length /* = false */)
+{
+ m_InputStream = stream;
+
+ // get the content length from the stream
+ if (update_content_length && !stream.IsNull()) {
+ NPT_LargeSize length;
+ if (NPT_SUCCEEDED(stream->GetSize(length))) {
+ return SetContentLength(length);
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetInputStream(const void* data, NPT_Size data_size)
+{
+ NPT_MemoryStream* memory_stream = new NPT_MemoryStream(data, data_size);
+ NPT_InputStreamReference body(memory_stream);
+ return SetInputStream(body, true);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetInputStream(const char* string)
+{
+ if (string == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+ NPT_MemoryStream* memory_stream = new NPT_MemoryStream((const void*)string,
+ NPT_StringLength(string));
+ NPT_InputStreamReference body(memory_stream);
+ return SetInputStream(body, true);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetInputStream(const NPT_String& string)
+{
+ NPT_MemoryStream* memory_stream = new NPT_MemoryStream((const void*)string.GetChars(),
+ string.GetLength());
+ NPT_InputStreamReference body(memory_stream);
+ return SetInputStream(body, true);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::Load(NPT_DataBuffer& buffer)
+{
+ // check that we have an input stream
+ if (m_InputStream.IsNull()) return NPT_ERROR_INVALID_STATE;
+
+ // load the stream into the buffer
+ if (m_ContentLength != (NPT_Size)m_ContentLength) return NPT_ERROR_OUT_OF_RANGE;
+ return m_InputStream->Load(buffer, (NPT_Size)m_ContentLength);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetContentLength
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetContentLength(NPT_LargeSize length)
+{
+ m_ContentLength = length;
+ m_ContentLengthIsKnown = true;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetContentType
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetContentType(const char* type)
+{
+ m_ContentType = type;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetContentEncoding
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetContentEncoding(const char* encoding)
+{
+ m_ContentEncoding = encoding;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity::SetTransferEncoding
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::SetTransferEncoding(const char* encoding)
+{
+ m_TransferEncoding = encoding;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage::NPT_HttpMessage
++---------------------------------------------------------------------*/
+NPT_HttpMessage::NPT_HttpMessage(const char* protocol) :
+ m_Protocol(protocol),
+ m_Entity(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage::NPT_HttpMessage
++---------------------------------------------------------------------*/
+NPT_HttpMessage::~NPT_HttpMessage()
+{
+ delete m_Entity;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage::SetEntity
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpMessage::SetEntity(NPT_HttpEntity* entity)
+{
+ if (entity != m_Entity) {
+ delete m_Entity;
+ m_Entity = entity;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage::ParseHeaders
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpMessage::ParseHeaders(NPT_BufferedInputStream& stream)
+{
+ return m_Headers.Parse(stream);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::NPT_HttpRequest
++---------------------------------------------------------------------*/
+NPT_HttpRequest::NPT_HttpRequest(const NPT_HttpUrl& url,
+ const char* method,
+ const char* protocol) :
+ NPT_HttpMessage(protocol),
+ m_Url(url),
+ m_Method(method)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::NPT_HttpRequest
++---------------------------------------------------------------------*/
+NPT_HttpRequest::NPT_HttpRequest(const char* url,
+ const char* method,
+ const char* protocol) :
+ NPT_HttpMessage(protocol),
+ m_Url(url),
+ m_Method(method)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::SetUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::SetUrl(const char* url)
+{
+ m_Url = url;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::SetUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::SetUrl(const NPT_HttpUrl& url)
+{
+ m_Url = url;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::Parse(NPT_BufferedInputStream& stream,
+ const NPT_SocketAddress* endpoint,
+ NPT_HttpRequest*& request)
+{
+ // default return value
+ request = NULL;
+
+skip_first_empty_line:
+ // read the request line
+ NPT_String line;
+ NPT_CHECK_FINER(stream.ReadLine(line, NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH));
+ NPT_LOG_FINEST_1("http request: %s", line.GetChars());
+
+ // cleanup lines that may contain '\0' as first character, clients such
+ // Spotify desktop app send SSDP M-SEARCH requests followed by an extra
+ // '\0' character which stays in the buffered stream and messes up parsing
+ // the next request.
+ while (line.GetLength() > 0 && line[0] == '\0') {
+ line = line.Erase(0, 1);
+ }
+
+ // when using keep-alive connections, clients such as XBox 360
+ // incorrectly send a few empty lines as body for GET requests
+ // so we try to skip them until we find something to parse
+ if (line.GetLength() == 0) goto skip_first_empty_line;
+
+ // check the request line
+ int first_space = line.Find(' ');
+ if (first_space < 0) {
+ NPT_LOG_FINE_1("http request: %s", line.GetChars());
+ return NPT_ERROR_HTTP_INVALID_REQUEST_LINE;
+ }
+ int second_space = line.Find(' ', first_space+1);
+ if (second_space < 0) {
+ NPT_LOG_FINE_1("http request: %s", line.GetChars());
+ return NPT_ERROR_HTTP_INVALID_REQUEST_LINE;
+ }
+
+ // parse the request line
+ NPT_String method = line.SubString(0, first_space);
+ NPT_String uri = line.SubString(first_space+1, second_space-first_space-1);
+ NPT_String protocol = line.SubString(second_space+1);
+
+ // create a request
+ bool proxy_style_request = false;
+ if (uri.StartsWith("http://", true)) {
+ // proxy-style request with absolute URI
+ request = new NPT_HttpRequest(uri, method, protocol);
+ proxy_style_request = true;
+ } else {
+ // normal absolute path request
+ request = new NPT_HttpRequest("http:", method, protocol);
+ }
+
+ // parse headers
+ NPT_Result result = request->ParseHeaders(stream);
+ if (NPT_FAILED(result)) {
+ delete request;
+ request = NULL;
+ return result;
+ }
+
+ // update the URL
+ if (!proxy_style_request) {
+ request->m_Url.SetScheme("http");
+ request->m_Url.ParsePathPlus(uri);
+ request->m_Url.SetPort(NPT_HTTP_DEFAULT_PORT);
+
+ // check for a Host: header
+ NPT_HttpHeader* host_header = request->GetHeaders().GetHeader(NPT_HTTP_HEADER_HOST);
+ if (host_header) {
+ request->m_Url.SetHost(host_header->GetValue());
+
+ // host sometimes doesn't contain port
+ if (endpoint) {
+ request->m_Url.SetPort(endpoint->GetPort());
+ }
+ } else {
+ // use the endpoint as the host
+ if (endpoint) {
+ request->m_Url.SetHost(endpoint->ToString());
+ } else {
+ // use defaults
+ request->m_Url.SetHost("localhost");
+ }
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::~NPT_HttpRequest
++---------------------------------------------------------------------*/
+NPT_HttpRequest::~NPT_HttpRequest()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::Emit(NPT_OutputStream& stream, bool use_proxy) const
+{
+ // write the request line
+ stream.WriteString(m_Method);
+ stream.WriteFully(" ", 1);
+ if (use_proxy) {
+ stream.WriteString(m_Url.ToString(false));
+ } else {
+ stream.WriteString(m_Url.ToRequestString());
+ }
+ stream.WriteFully(" ", 1);
+ stream.WriteString(m_Protocol);
+ stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+ // emit headers
+ m_Headers.Emit(stream);
+
+ // finish with an empty line
+ stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse::NPT_HttpResponse
++---------------------------------------------------------------------*/
+NPT_HttpResponse::NPT_HttpResponse(NPT_HttpStatusCode status_code,
+ const char* reason_phrase,
+ const char* protocol) :
+ NPT_HttpMessage(protocol),
+ m_StatusCode(status_code),
+ m_ReasonPhrase(reason_phrase)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse::~NPT_HttpResponse
++---------------------------------------------------------------------*/
+NPT_HttpResponse::~NPT_HttpResponse()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse::SetStatus
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::SetStatus(NPT_HttpStatusCode status_code,
+ const char* reason_phrase,
+ const char* protocol)
+{
+ m_StatusCode = status_code;
+ m_ReasonPhrase = reason_phrase;
+ if (protocol) m_Protocol = protocol;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse::SetProtocol
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::SetProtocol(const char* protocol)
+{
+ m_Protocol = protocol;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::Emit(NPT_OutputStream& stream) const
+{
+ // write the request line
+ stream.WriteString(m_Protocol);
+ stream.WriteFully(" ", 1);
+ stream.WriteString(NPT_String::FromInteger(m_StatusCode));
+ stream.WriteFully(" ", 1);
+ stream.WriteString(m_ReasonPhrase);
+ stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+ // emit headers
+ m_Headers.Emit(stream);
+
+ // finish with an empty line
+ stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::Parse(NPT_BufferedInputStream& stream,
+ NPT_HttpResponse*& response)
+{
+ // default return value
+ response = NULL;
+
+ // read the response line
+ NPT_String line;
+ NPT_CHECK_WARNING(stream.ReadLine(line, NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH));
+
+ NPT_LOG_FINER_1("http response: %s", line.GetChars());
+
+ // check the response line
+ // we are lenient here, as we allow the response to deviate slightly from
+ // strict HTTP (for example, ICY servers response with a method equal to
+ // ICY insead of HTTP/1.X)
+ int first_space = line.Find(' ');
+ if (first_space < 1) return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ int second_space = line.Find(' ', first_space+1);
+ if (second_space < 0) {
+ // some servers omit (incorrectly) the space and Reason-Code
+ // but we don't fail them just for that. Just check that the
+ // status code looks ok
+ if (line.GetLength() != 12) {
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+ } else if (second_space-first_space != 4) {
+ // the status code is not of length 3
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+
+ // parse the response line
+ NPT_String protocol = line.SubString(0, first_space);
+ NPT_String status_code = line.SubString(first_space+1, 3);
+ NPT_String reason_phrase = line.SubString(first_space+1+3+1,
+ line.GetLength()-(first_space+1+3+1));
+
+ // create a response object
+ NPT_UInt32 status_code_int = 0;
+ status_code.ToInteger(status_code_int);
+ response = new NPT_HttpResponse(status_code_int, reason_phrase, protocol);
+
+ // parse headers
+ NPT_Result result = response->ParseHeaders(stream);
+ if (NPT_FAILED(result)) {
+ delete response;
+ response = NULL;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEnvProxySelector
++---------------------------------------------------------------------*/
+class NPT_HttpEnvProxySelector : public NPT_HttpProxySelector,
+ public NPT_AutomaticCleaner::Singleton
+{
+public:
+ static NPT_HttpEnvProxySelector* GetInstance();
+
+ // NPT_HttpProxySelector methods
+ NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy) override;
+
+private:
+ // class variables
+ static NPT_HttpEnvProxySelector* Instance;
+
+ // class methods
+ static void ParseProxyEnv(const NPT_String& env, NPT_HttpProxyAddress& proxy);
+
+ // members
+ NPT_HttpProxyAddress m_HttpProxy;
+ NPT_HttpProxyAddress m_HttpsProxy;
+ NPT_List<NPT_String> m_NoProxy;
+ NPT_HttpProxyAddress m_AllProxy;
+};
+NPT_HttpEnvProxySelector* NPT_HttpEnvProxySelector::Instance = NULL;
+
+/*----------------------------------------------------------------------
+| NPT_HttpEnvProxySelector::GetInstance
++---------------------------------------------------------------------*/
+NPT_HttpEnvProxySelector*
+NPT_HttpEnvProxySelector::GetInstance()
+{
+ if (Instance) return Instance;
+
+ NPT_SingletonLock::GetInstance().Lock();
+ if (Instance == NULL) {
+ // create the shared instance
+ Instance = new NPT_HttpEnvProxySelector();
+
+ // prepare for recycling
+ NPT_AutomaticCleaner::GetInstance()->Register(Instance);
+
+ // parse the http proxy settings
+ NPT_String http_proxy;
+ NPT_Environment::Get("http_proxy", http_proxy);
+ ParseProxyEnv(http_proxy, Instance->m_HttpProxy);
+ NPT_LOG_FINE_2("http_proxy: %s:%d", Instance->m_HttpProxy.GetHostName().GetChars(), Instance->m_HttpProxy.GetPort());
+
+ // parse the https proxy settings
+ NPT_String https_proxy;
+ if (NPT_FAILED(NPT_Environment::Get("HTTPS_PROXY", https_proxy))) {
+ NPT_Environment::Get("https_proxy", https_proxy);
+ }
+ ParseProxyEnv(https_proxy, Instance->m_HttpsProxy);
+ NPT_LOG_FINE_2("https_proxy: %s:%d", Instance->m_HttpsProxy.GetHostName().GetChars(), Instance->m_HttpsProxy.GetPort());
+
+ // parse the all-proxy settings
+ NPT_String all_proxy;
+ if (NPT_FAILED(NPT_Environment::Get("ALL_PROXY", all_proxy))) {
+ NPT_Environment::Get("all_proxy", all_proxy);
+ }
+ ParseProxyEnv(all_proxy, Instance->m_AllProxy);
+ NPT_LOG_FINE_2("all_proxy: %s:%d", Instance->m_AllProxy.GetHostName().GetChars(), Instance->m_AllProxy.GetPort());
+
+ // parse the no-proxy settings
+ NPT_String no_proxy;
+ if (NPT_FAILED(NPT_Environment::Get("NO_PROXY", no_proxy))) {
+ NPT_Environment::Get("no_proxy", no_proxy);
+ }
+ if (no_proxy.GetLength()) {
+ Instance->m_NoProxy = no_proxy.Split(",");
+ }
+ }
+ NPT_SingletonLock::GetInstance().Unlock();
+
+ return Instance;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEnvProxySelector::ParseProxyEnv
++---------------------------------------------------------------------*/
+void
+NPT_HttpEnvProxySelector::ParseProxyEnv(const NPT_String& env,
+ NPT_HttpProxyAddress& proxy)
+{
+ // ignore empty strings
+ if (env.GetLength() == 0) return;
+
+ NPT_String proxy_spec;
+ if (env.Find("://") >= 0) {
+ proxy_spec = env;
+ } else {
+ proxy_spec = "http://"+env;
+ }
+ NPT_Url url(proxy_spec);
+ proxy.SetHostName(url.GetHost());
+ proxy.SetPort(url.GetPort());
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpEnvProxySelector::GetProxyForUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEnvProxySelector::GetProxyForUrl(const NPT_HttpUrl& url,
+ NPT_HttpProxyAddress& proxy)
+{
+ NPT_HttpProxyAddress* protocol_proxy = NULL;
+ switch (url.GetSchemeId()) {
+ case NPT_Uri::SCHEME_ID_HTTP:
+ protocol_proxy = &m_HttpProxy;
+ break;
+
+ case NPT_Uri::SCHEME_ID_HTTPS:
+ protocol_proxy = &m_HttpsProxy;
+ break;
+
+ default:
+ return NPT_ERROR_HTTP_NO_PROXY;
+ }
+
+ // check for no-proxy first
+ if (m_NoProxy.GetItemCount()) {
+ for (NPT_List<NPT_String>::Iterator i = m_NoProxy.GetFirstItem();
+ i;
+ ++i) {
+ if ((*i) == "*") {
+ return NPT_ERROR_HTTP_NO_PROXY;
+ }
+ if (url.GetHost().EndsWith(*i, true)) {
+ if (url.GetHost().GetLength() == (*i).GetLength()) {
+ // exact match
+ return NPT_ERROR_HTTP_NO_PROXY;
+ }
+ if (url.GetHost().GetChars()[url.GetHost().GetLength()-(*i).GetLength()-1] == '.') {
+ // subdomain match
+ return NPT_ERROR_HTTP_NO_PROXY;
+ }
+ }
+ }
+ }
+
+ // check the protocol proxy
+ if (protocol_proxy->GetHostName().GetLength()) {
+ proxy = *protocol_proxy;
+ return NPT_SUCCESS;
+ }
+
+ // use the default proxy
+ proxy = m_AllProxy;
+
+ return proxy.GetHostName().GetLength()?NPT_SUCCESS:NPT_ERROR_HTTP_NO_PROXY;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpProxySelector::GetDefault
++---------------------------------------------------------------------*/
+static bool NPT_HttpProxySelector_ConfigChecked = false;
+static unsigned int NPT_HttpProxySelector_Config = 0;
+const unsigned int NPT_HTTP_PROXY_SELECTOR_CONFIG_NONE = 0;
+const unsigned int NPT_HTTP_PROXY_SELECTOR_CONFIG_ENV = 1;
+const unsigned int NPT_HTTP_PROXY_SELECTOR_CONFIG_SYSTEM = 2;
+NPT_HttpProxySelector*
+NPT_HttpProxySelector::GetDefault()
+{
+ if (!NPT_HttpProxySelector_ConfigChecked) {
+ NPT_String config;
+ if (NPT_SUCCEEDED(NPT_Environment::Get("NEPTUNE_NET_CONFIG_PROXY_SELECTOR", config))) {
+ if (config.Compare("noproxy", true) == 0) {
+ NPT_HttpProxySelector_Config = NPT_HTTP_PROXY_SELECTOR_CONFIG_NONE;
+ } else if (config.Compare("env", true) == 0) {
+ NPT_HttpProxySelector_Config = NPT_HTTP_PROXY_SELECTOR_CONFIG_ENV;
+ } else if (config.Compare("system", true) == 0) {
+ NPT_HttpProxySelector_Config = NPT_HTTP_PROXY_SELECTOR_CONFIG_SYSTEM;
+ } else {
+ NPT_HttpProxySelector_Config = NPT_HTTP_PROXY_SELECTOR_CONFIG_NONE;
+ }
+ }
+ NPT_HttpProxySelector_ConfigChecked = true;
+ }
+
+ switch (NPT_HttpProxySelector_Config) {
+ case NPT_HTTP_PROXY_SELECTOR_CONFIG_NONE:
+ // no proxy
+ return NULL;
+
+ case NPT_HTTP_PROXY_SELECTOR_CONFIG_ENV:
+ // use the shared instance
+ return NPT_HttpEnvProxySelector::GetInstance();
+
+ case NPT_HTTP_PROXY_SELECTOR_CONFIG_SYSTEM:
+ // use the sytem proxy selector
+ return GetSystemSelector();
+
+ default:
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpProxySelector::GetSystemSelector
++---------------------------------------------------------------------*/
+#if !defined(NPT_CONFIG_HAVE_SYSTEM_PROXY_SELECTOR)
+NPT_HttpProxySelector*
+NPT_HttpProxySelector::GetSystemSelector()
+{
+ return NULL;
+}
+#endif
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticProxySelector
++---------------------------------------------------------------------*/
+class NPT_HttpStaticProxySelector : public NPT_HttpProxySelector
+{
+public:
+ // constructor
+ NPT_HttpStaticProxySelector(const char* http_propxy_hostname,
+ NPT_UInt16 http_proxy_port,
+ const char* https_proxy_hostname,
+ NPT_UInt16 htts_proxy_port);
+
+ // NPT_HttpProxySelector methods
+ NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy) override;
+
+private:
+ // members
+ NPT_HttpProxyAddress m_HttpProxy;
+ NPT_HttpProxyAddress m_HttpsProxy;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticProxySelector::NPT_HttpStaticProxySelector
++---------------------------------------------------------------------*/
+NPT_HttpStaticProxySelector::NPT_HttpStaticProxySelector(const char* http_proxy_hostname,
+ NPT_UInt16 http_proxy_port,
+ const char* https_proxy_hostname,
+ NPT_UInt16 https_proxy_port) :
+ m_HttpProxy( http_proxy_hostname, http_proxy_port),
+ m_HttpsProxy(https_proxy_hostname, https_proxy_port)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticProxySelector::GetProxyForUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpStaticProxySelector::GetProxyForUrl(const NPT_HttpUrl& url,
+ NPT_HttpProxyAddress& proxy)
+{
+ switch (url.GetSchemeId()) {
+ case NPT_Uri::SCHEME_ID_HTTP:
+ proxy = m_HttpProxy;
+ break;
+
+ case NPT_Uri::SCHEME_ID_HTTPS:
+ proxy = m_HttpsProxy;
+ break;
+
+ default:
+ return NPT_ERROR_HTTP_NO_PROXY;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::NPT_HttpConnectionManager
++---------------------------------------------------------------------*/
+NPT_HttpConnectionManager::NPT_HttpConnectionManager() :
+ m_Lock(true),
+ m_MaxConnections(NPT_HTTP_CONNECTION_MANAGER_MAX_CONNECTION_POOL_SIZE),
+ m_MaxConnectionAge(NPT_HTTP_CONNECTION_MANAGER_MAX_CONNECTION_AGE)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::~NPT_HttpConnectionManager
++---------------------------------------------------------------------*/
+NPT_HttpConnectionManager::~NPT_HttpConnectionManager()
+{
+ // set abort flag and wait for thread to finish
+ m_Aborted.SetValue(1);
+ Wait();
+
+ m_Connections.Apply(NPT_ObjectDeleter<Connection>());
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::GetInstance
++---------------------------------------------------------------------*/
+NPT_HttpConnectionManager*
+NPT_HttpConnectionManager::GetInstance()
+{
+ if (Instance) return Instance;
+
+ NPT_SingletonLock::GetInstance().Lock();
+ if (Instance == NULL) {
+ // create the shared instance
+ Instance = new NPT_HttpConnectionManager();
+
+ // register to for automatic cleanup
+ NPT_AutomaticCleaner::GetInstance()->RegisterHttpConnectionManager(Instance);
+
+ // Start shared instance
+ Instance->Start();
+ }
+ NPT_SingletonLock::GetInstance().Unlock();
+
+ return Instance;
+}
+NPT_HttpConnectionManager* NPT_HttpConnectionManager::Instance = NULL;
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Run
++---------------------------------------------------------------------*/
+void
+NPT_HttpConnectionManager::Run()
+{
+ // try to cleanup every 5 secs
+ while (m_Aborted.WaitUntilEquals(1, 5000) == NPT_ERROR_TIMEOUT) {
+ NPT_AutoLock lock(m_Lock);
+ Cleanup();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Cleanup
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::Cleanup()
+{
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ NPT_TimeStamp delta((float)m_MaxConnectionAge);
+
+ NPT_List<Connection*>::Iterator tail = m_Connections.GetLastItem();
+ while (tail) {
+ if (now < (*tail)->m_TimeStamp + delta) break;
+ NPT_LOG_FINE_1("cleaning up connection (%d remain)", m_Connections.GetItemCount());
+ delete *tail;
+ m_Connections.Erase(tail);
+ tail = m_Connections.GetLastItem();
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::FindConnection
++---------------------------------------------------------------------*/
+NPT_HttpConnectionManager::Connection*
+NPT_HttpConnectionManager::FindConnection(NPT_SocketAddress& address)
+{
+ NPT_AutoLock lock(m_Lock);
+ Cleanup();
+
+ for (NPT_List<Connection*>::Iterator i = m_Connections.GetFirstItem();
+ i;
+ ++i) {
+ Connection* connection = *i;
+
+ NPT_SocketInfo info;
+ if (NPT_FAILED(connection->GetInfo(info))) continue;
+
+ if (info.remote_address == address) {
+ m_Connections.Erase(i);
+ return connection;
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Track
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::Track(NPT_HttpClient* client, NPT_HttpClient::Connection* connection)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // look if already tracking client connections
+ ConnectionList* connections = NULL;
+ if (NPT_SUCCEEDED(m_ClientConnections.Get(client, connections))) {
+ // return immediately if connection is already associated with client
+ if (connections->Find(NPT_ObjectComparator<NPT_HttpClient::Connection*>(connection))) {
+ NPT_LOG_WARNING("Connection already associated to client.");
+ return NPT_SUCCESS;
+ }
+ connections->Add(connection);
+ return NPT_SUCCESS;
+ }
+
+ // new client connections
+ ConnectionList new_connections;
+
+ // add connection to new client connection list
+ new_connections.Add(connection);
+
+ // track new client connections
+ m_ClientConnections.Put(client, new_connections);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::UntrackConnection
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::UntrackConnection(NPT_HttpClient::Connection* connection)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (!connection) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // look for connection by enumerating all client connections
+ NPT_List<NPT_Map<NPT_HttpClient*, ConnectionList>::Entry*>::Iterator entry =
+ m_ClientConnections.GetEntries().GetFirstItem();
+ while (entry) {
+ NPT_HttpClient*& client = (NPT_HttpClient*&)(*entry)->GetKey();
+ ConnectionList& connections = (ConnectionList&)(*entry)->GetValue();
+
+ // look for connection in client connection list
+ NPT_List<NPT_HttpClient::Connection*>::Iterator i =
+ connections.Find(NPT_ObjectComparator<NPT_HttpClient::Connection*>(connection));
+ if (i) {
+ // remove it
+ connections.Erase(i);
+
+ // untrack client if no more active connections for it
+ if (connections.GetItemCount() == 0) {
+ m_ClientConnections.Erase(client);
+ }
+
+ return NPT_SUCCESS;
+ }
+ ++entry;
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Untrack
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::Untrack(NPT_HttpClient::Connection* connection)
+{
+ // check first if ConnectionCanceller Instance has not been released already
+ // with static finalizers
+ if (Instance == NULL) return NPT_FAILURE;
+
+ return GetInstance()->UntrackConnection(connection);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Recycle
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::Recycle(NPT_HttpConnectionManager::Connection* connection)
+{
+ // Untrack connection
+ UntrackConnection(connection);
+
+ {
+ NPT_AutoLock lock(m_Lock);
+ Cleanup();
+
+ // remove older connections to make room
+ while (m_Connections.GetItemCount() >= m_MaxConnections) {
+ NPT_List<Connection*>::Iterator head = m_Connections.GetFirstItem();
+ if (!head) break;
+ delete *head;
+ m_Connections.Erase(head);
+ NPT_LOG_FINER("removing connection from pool to make some room");
+ }
+
+ if (connection) {
+
+ // label this connection with the current timestamp and flag
+ NPT_System::GetCurrentTimeStamp(connection->m_TimeStamp);
+ connection->m_IsRecycled = true;
+
+ // add the connection to the pool
+ m_Connections.Add(connection);
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::AbortConnections
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::AbortConnections(NPT_HttpClient* client)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ ConnectionList* connections = NULL;
+ if (NPT_SUCCEEDED(m_ClientConnections.Get(client, connections))) {
+ for (NPT_List<NPT_HttpClient::Connection*>::Iterator i = connections->GetFirstItem();
+ i;
+ ++i) {
+ (*i)->Abort();
+ }
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Connection::Connection
++---------------------------------------------------------------------*/
+NPT_HttpConnectionManager::Connection::Connection(NPT_HttpConnectionManager& manager,
+ NPT_SocketReference& socket,
+ NPT_InputStreamReference input_stream,
+ NPT_OutputStreamReference output_stream) :
+ m_Manager(manager),
+ m_IsRecycled(false),
+ m_Socket(socket),
+ m_InputStream(input_stream),
+ m_OutputStream(output_stream)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Connection::~Connection
++---------------------------------------------------------------------*/
+NPT_HttpConnectionManager::Connection::~Connection()
+{
+ NPT_HttpConnectionManager::Untrack(this);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager::Connection::Recycle
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpConnectionManager::Connection::Recycle()
+{
+ return m_Manager.Recycle(this);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::NPT_HttpClient
++---------------------------------------------------------------------*/
+NPT_HttpClient::NPT_HttpClient(Connector* connector, bool transfer_ownership) :
+ m_ProxySelector(NPT_HttpProxySelector::GetDefault()),
+ m_ProxySelectorIsOwned(false),
+ m_Connector(connector),
+ m_ConnectorIsOwned(transfer_ownership),
+ m_Aborted(false)
+{
+ if (connector == NULL) {
+ m_Connector = new NPT_HttpTlsConnector();
+ m_ConnectorIsOwned = true;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::~NPT_HttpClient
++---------------------------------------------------------------------*/
+NPT_HttpClient::~NPT_HttpClient()
+{
+ if (m_ProxySelectorIsOwned) {
+ delete m_ProxySelector;
+ }
+ if (m_ConnectorIsOwned) {
+ delete m_Connector;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SetConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetConfig(const Config& config)
+{
+ m_Config = config;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SetProxy
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetProxy(const char* http_proxy_hostname,
+ NPT_UInt16 http_proxy_port,
+ const char* https_proxy_hostname,
+ NPT_UInt16 https_proxy_port)
+{
+ if (m_ProxySelectorIsOwned) {
+ delete m_ProxySelector;
+ m_ProxySelector = NULL;
+ m_ProxySelectorIsOwned = false;
+ }
+
+ // use a static proxy to hold on to the settings
+ m_ProxySelector = new NPT_HttpStaticProxySelector(http_proxy_hostname,
+ http_proxy_port,
+ https_proxy_hostname,
+ https_proxy_port);
+ m_ProxySelectorIsOwned = true;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SetProxySelector
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetProxySelector(NPT_HttpProxySelector* selector)
+{
+ if (m_ProxySelectorIsOwned && m_ProxySelector != selector) {
+ delete m_ProxySelector;
+ }
+ m_ProxySelector = selector;
+ m_ProxySelectorIsOwned = false;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SetConnector
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetConnector(Connector* connector)
+{
+ if (m_ConnectorIsOwned && m_Connector != connector) {
+ delete m_Connector;
+ }
+ m_Connector = connector;
+ m_ConnectorIsOwned = false;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SetTimeouts
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetTimeouts(NPT_Timeout connection_timeout,
+ NPT_Timeout io_timeout,
+ NPT_Timeout name_resolver_timeout)
+{
+ m_Config.m_ConnectionTimeout = connection_timeout;
+ m_Config.m_IoTimeout = io_timeout;
+ m_Config.m_NameResolverTimeout = name_resolver_timeout;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SetUserAgent
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetUserAgent(const char* user_agent)
+{
+ m_Config.m_UserAgent = user_agent;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::TrackConnection
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::TrackConnection(Connection* connection)
+{
+ NPT_AutoLock lock(m_AbortLock);
+ if (m_Aborted) return NPT_ERROR_CANCELLED;
+ return NPT_HttpConnectionManager::GetInstance()->Track(this, connection);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SendRequestOnce
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SendRequestOnce(NPT_HttpRequest& request,
+ NPT_HttpResponse*& response,
+ NPT_HttpRequestContext* context /* = NULL */)
+{
+ // setup default values
+ NPT_Result result = NPT_SUCCESS;
+ response = NULL;
+
+ NPT_LOG_FINE_1("requesting URL %s", request.GetUrl().ToString().GetChars());
+
+ // get the address and port to which we need to connect
+ NPT_HttpProxyAddress proxy;
+ bool use_proxy = false;
+ if (m_ProxySelector) {
+ // we have a proxy selector, ask it to select a proxy for this URL
+ result = m_ProxySelector->GetProxyForUrl(request.GetUrl(), proxy);
+ if (NPT_FAILED(result) && result != NPT_ERROR_HTTP_NO_PROXY) {
+ NPT_LOG_WARNING_1("proxy selector failure (%d)", result);
+ return result;
+ }
+ use_proxy = !proxy.GetHostName().IsEmpty();
+ }
+
+ // connect to the server or proxy
+ Connection* connection = NULL;
+ bool http_1_1 = (request.GetProtocol() == NPT_HTTP_PROTOCOL_1_1);
+ NPT_Reference<Connection> cref;
+
+ // send the request to the server (in a loop, since we may need to reconnect with 1.1)
+ bool reconnect = false;
+ unsigned int watchdog = NPT_HTTP_MAX_RECONNECTS;
+ do {
+ cref = NULL;
+ connection = NULL;
+ NPT_LOG_FINE_3("calling connector (proxy:%s) (http 1.1:%s) (url:%s)",
+ use_proxy?"yes":"no", http_1_1?"yes":"no", request.GetUrl().ToStringWithDefaultPort(0).GetChars());
+ NPT_CHECK_WARNING(m_Connector->Connect(request.GetUrl(),
+ *this,
+ use_proxy?&proxy:NULL,
+ http_1_1,
+ connection));
+ NPT_LOG_FINE_1("got connection (reused: %s)", connection->IsRecycled()?"true":"false");
+
+ NPT_InputStreamReference input_stream = connection->GetInputStream();
+ NPT_OutputStreamReference output_stream = connection->GetOutputStream();
+
+ cref = connection;
+ reconnect = connection->IsRecycled();
+
+ // update context if any
+ if (context) {
+ NPT_SocketInfo info;
+ cref->GetInfo(info);
+ context->SetLocalAddress(info.local_address);
+ context->SetRemoteAddress(info.remote_address);
+ }
+
+ NPT_HttpEntity* entity = request.GetEntity();
+ NPT_InputStreamReference body_stream;
+
+ if (reconnect && entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream)) && NPT_FAILED(body_stream->Seek(0))) {
+ // if body is not seekable, we can't afford to reuse a connection
+ // that could fail, so we reconnect a new one instead
+ NPT_LOG_FINE("rewinding body stream would fail ... create new connection");
+ continue;
+ }
+
+ // decide if this connection should persist
+ NPT_HttpHeaders& headers = request.GetHeaders();
+ bool should_persist = http_1_1;
+ if (!connection->SupportsPersistence()) {
+ should_persist = false;
+ }
+ if (should_persist) {
+ const NPT_String* connection_header = headers.GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
+ if (connection_header && (*connection_header == "close")) {
+ should_persist = false;
+ }
+ }
+
+ if (m_Config.m_UserAgent.GetLength()) {
+ headers.SetHeader(NPT_HTTP_HEADER_USER_AGENT, m_Config.m_UserAgent, false); // set but don't replace
+ }
+
+ result = WriteRequest(*output_stream.AsPointer(), request, should_persist, use_proxy);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE_1("failed to write request headers (%d)", result);
+ if (reconnect && !m_Aborted) {
+ if (!body_stream.IsNull()) {
+ // go back to the start of the body so that we can resend
+ NPT_LOG_FINE("rewinding body stream in order to resend");
+ result = body_stream->Seek(0);
+ if (NPT_FAILED(result)) {
+ NPT_CHECK_FINE(NPT_ERROR_HTTP_CANNOT_RESEND_BODY);
+ }
+ }
+ continue;
+ } else {
+ return result;
+ }
+ }
+
+ result = ReadResponse(input_stream,
+ should_persist,
+ request.GetMethod() != NPT_HTTP_METHOD_HEAD,
+ response,
+ &cref);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE_1("failed to parse the response (%d)", result);
+ if (reconnect && !m_Aborted /*&&
+ (result == NPT_ERROR_EOS ||
+ result == NPT_ERROR_CONNECTION_ABORTED ||
+ result == NPT_ERROR_CONNECTION_RESET ||
+ result == NPT_ERROR_READ_FAILED) GBG: don't look for specific error codes */) {
+ NPT_LOG_FINE("error is not fatal, retrying");
+ if (!body_stream.IsNull()) {
+ // go back to the start of the body so that we can resend
+ NPT_LOG_FINE("rewinding body stream in order to resend");
+ result = body_stream->Seek(0);
+ if (NPT_FAILED(result)) {
+ NPT_CHECK_FINE(NPT_ERROR_HTTP_CANNOT_RESEND_BODY);
+ }
+ }
+ continue;
+ } else {
+ // don't retry
+ return result;
+ }
+ }
+ break;
+ } while (reconnect && --watchdog && !m_Aborted);
+
+ // check that we have a valid connection
+ if (NPT_FAILED(result) && !m_Aborted) {
+ NPT_LOG_FINE("failed after max reconnection attempts");
+ return NPT_ERROR_HTTP_TOO_MANY_RECONNECTS;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::WriteRequest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::WriteRequest(NPT_OutputStream& output_stream,
+ NPT_HttpRequest& request,
+ bool should_persist,
+ bool use_proxy /* = false */)
+{
+ NPT_Result result = NPT_SUCCESS;
+
+ // add any headers that may be missing
+ NPT_HttpHeaders& headers = request.GetHeaders();
+
+ if (!should_persist) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close", false); // set but don't replace
+ }
+
+ NPT_String host = request.GetUrl().GetHost();
+ NPT_UInt16 default_port = 0;
+ switch (request.GetUrl().GetSchemeId()) {
+ case NPT_Uri::SCHEME_ID_HTTP: default_port = NPT_HTTP_DEFAULT_PORT; break;
+ case NPT_Uri::SCHEME_ID_HTTPS: default_port = NPT_HTTPS_DEFAULT_PORT; break;
+ default: break;
+ }
+ if (request.GetUrl().GetPort() != default_port) {
+ host += ":";
+ host += NPT_String::FromInteger(request.GetUrl().GetPort());
+ }
+ headers.SetHeader(NPT_HTTP_HEADER_HOST, host, false); // set but don't replace
+
+ // get the request entity to set additional headers
+ NPT_InputStreamReference body_stream;
+ NPT_HttpEntity* entity = request.GetEntity();
+ if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
+ // set the content length if known
+ if (entity->ContentLengthIsKnown()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH,
+ NPT_String::FromInteger(entity->GetContentLength()));
+ }
+
+ // content type
+ NPT_String content_type = entity->GetContentType();
+ if (!content_type.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+ }
+
+ // content encoding
+ NPT_String content_encoding = entity->GetContentEncoding();
+ if (!content_encoding.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+ }
+
+ // transfer encoding
+ const NPT_String& transfer_encoding = entity->GetTransferEncoding();
+ if (!transfer_encoding.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING, transfer_encoding);
+ }
+ }
+
+ // create a memory stream to buffer the headers
+ NPT_MemoryStream header_stream;
+
+ // emit the request headers into the header buffer
+ request.Emit(header_stream, use_proxy && request.GetUrl().GetSchemeId()==NPT_Url::SCHEME_ID_HTTP);
+
+ // send the headers
+ NPT_CHECK_WARNING(output_stream.WriteFully(header_stream.GetData(), header_stream.GetDataSize()));
+
+ // send request body
+ if (entity && !body_stream.IsNull()) {
+ // check for chunked transfer encoding
+ NPT_OutputStream* dest = &output_stream;
+ if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
+ dest = new NPT_HttpChunkedOutputStream(output_stream);
+ }
+
+ NPT_LOG_FINE_1("sending body stream, %lld bytes", entity->GetContentLength()); //FIXME: Would be 0 for chunked encoding
+ NPT_LargeSize bytes_written = 0;
+
+ // content length = 0 means copy until input returns EOS
+ result = NPT_StreamToStreamCopy(*body_stream.AsPointer(), *dest, 0, entity->GetContentLength(), &bytes_written);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE_3("body stream only partially sent, %lld bytes (%d:%s)",
+ bytes_written,
+ result,
+ NPT_ResultText(result));
+ }
+
+ // flush to write out any buffered data left in chunked output if used
+ dest->Flush();
+
+ // cleanup (this will send zero size chunk followed by CRLF)
+ if (dest != &output_stream) delete dest;
+ }
+
+ // flush the output stream so that everything is sent to the server
+ output_stream.Flush();
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::ReadResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::ReadResponse(NPT_InputStreamReference& input_stream,
+ bool should_persist,
+ bool expect_entity,
+ NPT_HttpResponse*& response,
+ NPT_Reference<Connection>* cref /* = NULL */)
+{
+ NPT_Result result;
+
+ // setup default values
+ response = NULL;
+
+ // create a buffered stream for this socket stream
+ NPT_BufferedInputStreamReference buffered_input_stream(new NPT_BufferedInputStream(input_stream));
+
+ // parse the response
+ for (unsigned int watchcat = 0; watchcat < NPT_HTTP_MAX_100_RESPONSES; watchcat++) {
+ // parse the response
+ result = NPT_HttpResponse::Parse(*buffered_input_stream, response);
+ NPT_CHECK_FINE(result);
+
+ if (response->GetStatusCode() >= 100 && response->GetStatusCode() < 200) {
+ NPT_LOG_FINE_1("got %d response, continuing", response->GetStatusCode());
+ delete response;
+ response = NULL;
+ continue;
+ }
+ NPT_LOG_FINER_2("got response, code=%d, msg=%s",
+ response->GetStatusCode(),
+ response->GetReasonPhrase().GetChars());
+ break;
+ }
+
+ // check that we have a valid response
+ if (response == NULL) {
+ NPT_LOG_FINE("failed after max continuation attempts");
+ return NPT_ERROR_HTTP_TOO_MANY_RECONNECTS;
+ }
+
+ // unbuffer the stream
+ buffered_input_stream->SetBufferSize(0);
+
+ // decide if we should still try to reuse this connection later on
+ if (should_persist) {
+ const NPT_String* connection_header = response->GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
+ if (response->GetProtocol() == NPT_HTTP_PROTOCOL_1_1) {
+ if (connection_header && (*connection_header == "close")) {
+ should_persist = false;
+ }
+ } else {
+ if (!connection_header || (*connection_header != "keep-alive")) {
+ should_persist = false;
+ }
+ }
+ }
+
+ // create an entity if one is expected in the response
+ if (expect_entity) {
+ NPT_HttpEntity* response_entity = new NPT_HttpEntity(response->GetHeaders());
+
+ // check if the content length is known
+ bool have_content_length = (response->GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH) != NULL);
+
+ // check for chunked Transfer-Encoding
+ bool chunked = false;
+ if (response_entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
+ chunked = true;
+ response_entity->SetTransferEncoding(NULL);
+ }
+
+ // prepare to transfer ownership of the connection if needed
+ Connection* connection = NULL;
+ if (cref) {
+ connection = cref->AsPointer();
+ cref->Detach(); // release the internal ref
+ // don't delete connection now so we can abort while readin response body,
+ // just pass ownership to NPT_HttpEntityBodyInputStream so it can recycle it
+ // when done if connection should persist
+ }
+
+ // create the body stream wrapper
+ NPT_InputStream* response_body_stream =
+ new NPT_HttpEntityBodyInputStream(buffered_input_stream,
+ response_entity->GetContentLength(),
+ have_content_length,
+ chunked,
+ connection,
+ should_persist);
+ response_entity->SetInputStream(NPT_InputStreamReference(response_body_stream));
+ response->SetEntity(response_entity);
+ } else {
+ if (should_persist && cref) {
+ Connection* connection = cref->AsPointer();
+ cref->Detach(); // release the internal ref
+ connection->Recycle();
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::SendRequest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SendRequest(NPT_HttpRequest& request,
+ NPT_HttpResponse*& response,
+ NPT_HttpRequestContext* context /* = NULL */)
+{
+ NPT_Cardinal watchdog = m_Config.m_MaxRedirects+1;
+ bool keep_going;
+ NPT_Result result;
+
+ // reset aborted flag
+ m_Aborted = false;
+
+ // default value
+ response = NULL;
+
+ // check that for GET requests there is no entity
+ if (request.GetEntity() != NULL &&
+ request.GetMethod() == NPT_HTTP_METHOD_GET) {
+ return NPT_ERROR_HTTP_INVALID_REQUEST;
+ }
+
+ do {
+ keep_going = false;
+ result = SendRequestOnce(request, response, context);
+ if (NPT_FAILED(result)) break;
+ if (response && m_Config.m_MaxRedirects &&
+ (request.GetMethod() == NPT_HTTP_METHOD_GET ||
+ request.GetMethod() == NPT_HTTP_METHOD_HEAD) &&
+ (response->GetStatusCode() == 301 ||
+ response->GetStatusCode() == 302 ||
+ response->GetStatusCode() == 303 ||
+ response->GetStatusCode() == 307)) {
+ // handle redirect
+ const NPT_String* location = response->GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_LOCATION);
+ if (location) {
+ // check for location fields that are not absolute URLs
+ // (this is not allowed by the standard, but many web servers do it
+ if (location->StartsWith("/") ||
+ (!location->StartsWith("http://", true) &&
+ !location->StartsWith("https://", true))) {
+ NPT_LOG_FINE_1("Location: header (%s) is not an absolute URL, using it as a relative URL", location->GetChars());
+ if (location->StartsWith("/")) {
+ NPT_LOG_FINE_1("redirecting to absolute path %s", location->GetChars());
+ request.GetUrl().ParsePathPlus(*location);
+ } else {
+ NPT_String redirect_path = request.GetUrl().GetPath();
+ int slash_pos = redirect_path.ReverseFind('/');
+ if (slash_pos >= 0) {
+ redirect_path.SetLength(slash_pos+1);
+ } else {
+ redirect_path = "/";
+ }
+ redirect_path += *location;
+ NPT_LOG_FINE_1("redirecting to absolute path %s", redirect_path.GetChars());
+ request.GetUrl().ParsePathPlus(redirect_path);
+ }
+ } else {
+ // replace the request url
+ NPT_LOG_FINE_1("redirecting to %s", location->GetChars());
+ request.SetUrl(*location);
+ // remove host header so it is replaced based on new url
+ request.GetHeaders().RemoveHeader(NPT_HTTP_HEADER_HOST);
+ }
+ keep_going = true;
+ delete response;
+ response = NULL;
+ }
+ }
+ } while (keep_going && --watchdog && !m_Aborted);
+
+ // check if we were bitten by the watchdog
+ if (watchdog == 0) {
+ NPT_LOG_WARNING("too many HTTP redirects");
+ return NPT_ERROR_HTTP_TOO_MANY_REDIRECTS;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient::Abort
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::Abort()
+{
+ NPT_AutoLock lock(m_AbortLock);
+ m_Aborted = true;
+
+ NPT_HttpConnectionManager::GetInstance()->AbortConnections(this);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequestContext::NPT_HttpRequestContext
++---------------------------------------------------------------------*/
+NPT_HttpRequestContext::NPT_HttpRequestContext(const NPT_SocketAddress* local_address,
+ const NPT_SocketAddress* remote_address)
+{
+ if (local_address) m_LocalAddress = *local_address;
+ if (remote_address) m_RemoteAddress = *remote_address;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::NPT_HttpServer
++---------------------------------------------------------------------*/
+NPT_HttpServer::NPT_HttpServer(NPT_UInt16 listen_port, bool cancellable) :
+ m_Socket(cancellable?NPT_SOCKET_FLAG_CANCELLABLE:0),
+ m_BoundPort(0),
+ m_ServerHeader("Neptune/" NPT_NEPTUNE_VERSION_STRING),
+ m_Run(true)
+{
+ m_Config.m_ListenAddress = NPT_IpAddress::Any;
+ m_Config.m_ListenPort = listen_port;
+ m_Config.m_IoTimeout = NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT;
+ m_Config.m_ConnectionTimeout = NPT_HTTP_SERVER_DEFAULT_CONNECTION_TIMEOUT;
+ m_Config.m_ReuseAddress = true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::NPT_HttpServer
++---------------------------------------------------------------------*/
+NPT_HttpServer::NPT_HttpServer(NPT_IpAddress listen_address,
+ NPT_UInt16 listen_port,
+ bool cancellable) :
+ m_Socket(cancellable?NPT_SOCKET_FLAG_CANCELLABLE:0),
+ m_BoundPort(0),
+ m_ServerHeader("Neptune/" NPT_NEPTUNE_VERSION_STRING),
+ m_Run(true)
+{
+ m_Config.m_ListenAddress = listen_address;
+ m_Config.m_ListenPort = listen_port;
+ m_Config.m_IoTimeout = NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT;
+ m_Config.m_ConnectionTimeout = NPT_HTTP_SERVER_DEFAULT_CONNECTION_TIMEOUT;
+ m_Config.m_ReuseAddress = true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::~NPT_HttpServer
++---------------------------------------------------------------------*/
+NPT_HttpServer::~NPT_HttpServer()
+{
+ m_RequestHandlers.Apply(NPT_ObjectDeleter<HandlerConfig>());
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::Bind
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::Bind()
+{
+ // check if we're already bound
+ if (m_BoundPort != 0) return NPT_SUCCESS;
+
+ // bind
+ NPT_Result result = m_Socket.Bind(
+ NPT_SocketAddress(m_Config.m_ListenAddress, m_Config.m_ListenPort),
+ m_Config.m_ReuseAddress);
+ if (NPT_FAILED(result)) return result;
+
+ // update the bound port info
+ NPT_SocketInfo info;
+ m_Socket.GetInfo(info);
+ m_BoundPort = info.local_address.GetPort();
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::SetConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetConfig(const Config& config)
+{
+ m_Config = config;
+
+ // check that we can bind to this listen port
+ return Bind();
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::SetListenPort
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetListenPort(NPT_UInt16 port, bool reuse_address)
+{
+ m_Config.m_ListenPort = port;
+ m_Config.m_ReuseAddress = reuse_address;
+ return Bind();
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::SetTimeouts
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetTimeouts(NPT_Timeout connection_timeout,
+ NPT_Timeout io_timeout)
+{
+ m_Config.m_ConnectionTimeout = connection_timeout;
+ m_Config.m_IoTimeout = io_timeout;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::SetServerHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetServerHeader(const char* server_header)
+{
+ m_ServerHeader = server_header;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::Abort
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::Abort()
+{
+ m_Socket.Cancel();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::WaitForNewClient
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::WaitForNewClient(NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output,
+ NPT_HttpRequestContext* context,
+ NPT_Flags socket_flags)
+{
+ // ensure that we're bound
+ NPT_CHECK_FINE(Bind());
+
+ // wait for a connection
+ NPT_Socket* client;
+ NPT_LOG_FINE_2("waiting for new connection on %s:%d...",
+ (const char*)m_Config.m_ListenAddress.ToString(),
+ m_BoundPort);
+ NPT_Result result = m_Socket.WaitForNewClient(client, m_Config.m_ConnectionTimeout, socket_flags);
+ if (result != NPT_ERROR_TIMEOUT) {
+ NPT_CHECK_WARNING(result);
+ } else {
+ NPT_CHECK_FINE(result);
+ }
+ if (client == NULL) return NPT_ERROR_INTERNAL;
+
+ // get the client info
+ if (context) {
+ NPT_SocketInfo client_info;
+ client->GetInfo(client_info);
+
+ context->SetLocalAddress(client_info.local_address);
+ context->SetRemoteAddress(client_info.remote_address);
+
+ NPT_LOG_FINE_2("client connected (%s <- %s)",
+ client_info.local_address.ToString().GetChars(),
+ client_info.remote_address.ToString().GetChars());
+ }
+
+ // configure the socket
+ client->SetReadTimeout(m_Config.m_IoTimeout);
+ client->SetWriteTimeout(m_Config.m_IoTimeout);
+
+ // get the streams
+ client->GetInputStream(input);
+ client->GetOutputStream(output);
+
+ // we don't need the socket anymore
+ delete client;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::Loop
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::Loop(bool cancellable_sockets)
+{
+ NPT_InputStreamReference input;
+ NPT_OutputStreamReference output;
+ NPT_HttpRequestContext context;
+ NPT_Result result;
+
+ do {
+ // wait for a client to connect
+ NPT_Flags flags = cancellable_sockets?NPT_SOCKET_FLAG_CANCELLABLE:0;
+ result = WaitForNewClient(input, output, &context, flags);
+ NPT_LOG_FINE_2("WaitForNewClient returned %d (%s)",
+ result,
+ NPT_ResultText(result));
+ if (!m_Run) break;
+ if (result == NPT_ERROR_TIMEOUT) continue;
+
+ // respond to the client
+ if (NPT_SUCCEEDED(result)) {
+ // send a response
+ result = RespondToClient(input, output, context);
+ NPT_LOG_FINE_2("ResponToClient returned %d (%s)",
+ result,
+ NPT_ResultText(result));
+ } else {
+ NPT_LOG_FINE_2("WaitForNewClient returned %d (%s)",
+ result,
+ NPT_ResultText(result));
+ // if there was an error, wait a short time to avoid spinning
+ if (result != NPT_ERROR_TERMINATED) {
+ NPT_LOG_FINE("sleeping before restarting the loop");
+ NPT_System::Sleep(1.0);
+ }
+ }
+
+ // release the stream references so that the socket can be closed
+ input = NULL;
+ output = NULL;
+ } while (m_Run && result != NPT_ERROR_TERMINATED);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::HandlerConfig::HandlerConfig
++---------------------------------------------------------------------*/
+NPT_HttpServer::HandlerConfig::HandlerConfig(NPT_HttpRequestHandler* handler,
+ const char* path,
+ bool include_children,
+ bool transfer_ownership) :
+ m_Handler(handler),
+ m_Path(path),
+ m_IncludeChildren(include_children),
+ m_HandlerIsOwned(transfer_ownership)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::HandlerConfig::~HandlerConfig
++---------------------------------------------------------------------*/
+NPT_HttpServer::HandlerConfig::~HandlerConfig()
+{
+ if (m_HandlerIsOwned) delete m_Handler;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::AddRequestHandler
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::AddRequestHandler(NPT_HttpRequestHandler* handler,
+ const char* path,
+ bool include_children,
+ bool transfer_ownership)
+{
+ return m_RequestHandlers.Add(new HandlerConfig(handler, path, include_children, transfer_ownership));
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::FindRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpRequestHandler*
+NPT_HttpServer::FindRequestHandler(NPT_HttpRequest& request)
+{
+ NPT_String path = NPT_Uri::PercentDecode(request.GetUrl().GetPath());
+ for (NPT_List<HandlerConfig*>::Iterator it = m_RequestHandlers.GetFirstItem();
+ it;
+ ++it) {
+ HandlerConfig* config = *it;
+ if (config->m_IncludeChildren) {
+ if (path.StartsWith(config->m_Path)) {
+ return config->m_Handler;
+ }
+ } else {
+ if (path == config->m_Path) {
+ return config->m_Handler;
+ }
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::FindRequestHandlers
++---------------------------------------------------------------------*/
+NPT_List<NPT_HttpRequestHandler*>
+NPT_HttpServer::FindRequestHandlers(NPT_HttpRequest& request)
+{
+ NPT_List<NPT_HttpRequestHandler*> handlers;
+
+ for (NPT_List<HandlerConfig*>::Iterator it = m_RequestHandlers.GetFirstItem();
+ it;
+ ++it) {
+ HandlerConfig* config = *it;
+ if (config->m_IncludeChildren) {
+ if (request.GetUrl().GetPath(true).StartsWith(config->m_Path)) {
+ handlers.Add(config->m_Handler);
+ }
+ } else {
+ if (request.GetUrl().GetPath(true) == config->m_Path) {
+ handlers.Insert(handlers.GetFirstItem(), config->m_Handler);
+ }
+ }
+ }
+
+ return handlers;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::RespondToClient
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::RespondToClient(NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output,
+ const NPT_HttpRequestContext& context)
+{
+ NPT_HttpRequest* request;
+ NPT_HttpResponse* response = NULL;
+ NPT_Result result = NPT_ERROR_NO_SUCH_ITEM;
+ bool terminate_server = false;
+
+ NPT_HttpResponder responder(input, output);
+ NPT_CHECK_WARNING(responder.ParseRequest(request, &context.GetLocalAddress()));
+ NPT_LOG_FINE_1("request, path=%s", request->GetUrl().ToRequestString(true).GetChars());
+
+ // prepare the response body
+ NPT_HttpEntity* body = new NPT_HttpEntity();
+
+ NPT_HttpRequestHandler* handler = FindRequestHandler(*request);
+ if (handler) {
+ // create a response object
+ response = new NPT_HttpResponse(200, "OK", NPT_HTTP_PROTOCOL_1_0);
+ response->SetEntity(body);
+
+ // ask the handler to setup the response
+ result = handler->SetupResponse(*request, context, *response);
+ }
+ if (result == NPT_ERROR_NO_SUCH_ITEM || handler == NULL) {
+ body->SetInputStream(NPT_HTTP_DEFAULT_404_HTML);
+ body->SetContentType("text/html");
+ if (response == NULL) {
+ response = new NPT_HttpResponse(404, "Not Found", NPT_HTTP_PROTOCOL_1_0);
+ } else {
+ response->SetStatus(404, "Not Found");
+ }
+ response->SetEntity(body);
+ if (handler) {
+ handler->Completed(NPT_ERROR_NO_SUCH_ITEM);
+ handler = NULL;
+ }
+ } else if (result == NPT_ERROR_PERMISSION_DENIED) {
+ body->SetInputStream(NPT_HTTP_DEFAULT_403_HTML);
+ body->SetContentType("text/html");
+ response->SetStatus(403, "Forbidden");
+ handler->Completed(NPT_ERROR_PERMISSION_DENIED);
+ handler = NULL;
+ } else if (result == NPT_ERROR_TERMINATED) {
+ // mark that we want to exit
+ terminate_server = true;
+ } else if (NPT_FAILED(result)) {
+ body->SetInputStream(NPT_HTTP_DEFAULT_500_HTML);
+ body->SetContentType("text/html");
+ response->SetStatus(500, "Internal Error");
+ handler->Completed(result);
+ handler = NULL;
+ }
+
+ // augment the headers with server information
+ if (m_ServerHeader.GetLength()) {
+ response->GetHeaders().SetHeader(NPT_HTTP_HEADER_SERVER, m_ServerHeader, false);
+ }
+
+ // send the response headers
+ result = responder.SendResponseHeaders(*response);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_2("SendResponseHeaders failed (%d:%s)", result, NPT_ResultText(result));
+ goto end;
+ }
+
+ // send the body
+ if (request->GetMethod() != NPT_HTTP_METHOD_HEAD) {
+ if (handler) {
+ result = handler->SendResponseBody(context, *response, *output);
+ } else {
+ // send body manually in case there was an error with the handler or no handler was found
+ NPT_InputStreamReference body_stream;
+ body->GetInputStream(body_stream);
+ if (!body_stream.IsNull()) {
+ result = NPT_StreamToStreamCopy(*body_stream, *output, 0, body->GetContentLength());
+ if (NPT_FAILED(result)) {
+ NPT_LOG_INFO_2("NPT_StreamToStreamCopy returned %d (%s)", result, NPT_ResultText(result));
+ goto end;
+ }
+ }
+ }
+ }
+
+ // flush
+ output->Flush();
+
+ // if we need to die, we return an error code
+ if (NPT_SUCCEEDED(result) && terminate_server) result = NPT_ERROR_TERMINATED;
+
+end:
+ // cleanup
+ delete response;
+ delete request;
+
+ if (handler) {
+ handler->Completed(result);
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder::NPT_HttpResponder
++---------------------------------------------------------------------*/
+NPT_HttpResponder::NPT_HttpResponder(NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output) :
+ m_Input(new NPT_BufferedInputStream(input)),
+ m_Output(output)
+{
+ m_Config.m_IoTimeout = NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder::~NPT_HttpResponder
++---------------------------------------------------------------------*/
+NPT_HttpResponder::~NPT_HttpResponder()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer::Terminate
++---------------------------------------------------------------------*/
+void NPT_HttpServer::Terminate()
+{
+ m_Run = false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder::SetConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::SetConfig(const Config& config)
+{
+ m_Config = config;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder::SetTimeout
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::SetTimeout(NPT_Timeout io_timeout)
+{
+ m_Config.m_IoTimeout = io_timeout;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder::ParseRequest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::ParseRequest(NPT_HttpRequest*& request,
+ const NPT_SocketAddress* local_address)
+{
+ // rebuffer the stream in case we're using a keep-alive connection
+ m_Input->SetBufferSize(NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE);
+
+ // parse the request
+ NPT_CHECK_FINE(NPT_HttpRequest::Parse(*m_Input, local_address, request));
+
+ // unbuffer the stream
+ m_Input->SetBufferSize(0);
+
+ // don't create an entity if no body is expected
+ if (request->GetMethod() == NPT_HTTP_METHOD_GET ||
+ request->GetMethod() == NPT_HTTP_METHOD_HEAD ||
+ request->GetMethod() == NPT_HTTP_METHOD_TRACE) {
+ return NPT_SUCCESS;
+ }
+
+ // set the entity info
+ NPT_HttpEntity* entity = new NPT_HttpEntity(request->GetHeaders());
+ if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
+ entity->SetInputStream(NPT_InputStreamReference(new NPT_HttpChunkedInputStream(m_Input)));
+ } else {
+ entity->SetInputStream(m_Input);
+ }
+ request->SetEntity(entity);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder::SendResponseHeaders
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::SendResponseHeaders(NPT_HttpResponse& response)
+{
+ // add default headers
+ NPT_HttpHeaders& headers = response.GetHeaders();
+ if (response.GetProtocol() == NPT_HTTP_PROTOCOL_1_0) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONNECTION,
+ "close", false); // set but don't replace
+ }
+
+ // add computed headers
+ NPT_HttpEntity* entity = response.GetEntity();
+ if (entity) {
+ // content type
+ const NPT_String& content_type = entity->GetContentType();
+ if (!content_type.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+ }
+
+ // content encoding
+ const NPT_String& content_encoding = entity->GetContentEncoding();
+ if (!content_encoding.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+ }
+
+ // transfer encoding
+ const NPT_String& transfer_encoding = entity->GetTransferEncoding();
+ if (!transfer_encoding.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING, transfer_encoding);
+ }
+
+ // set the content length if known
+ if (entity->ContentLengthIsKnown()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH,
+ NPT_String::FromInteger(entity->GetContentLength()));
+ } else if (transfer_encoding.IsEmpty() || transfer_encoding.Compare(NPT_HTTP_TRANSFER_ENCODING_CHUNKED, true)) {
+ // no content length, the only way client will know we're done
+ // is when we'll close the connection unless it's chunked encoding
+ headers.SetHeader(NPT_HTTP_HEADER_CONNECTION,
+ "close", true); // set and replace
+ }
+ } else {
+ // force content length to 0 if there is no message body
+ // (necessary for 1.1 or 1.0 with keep-alive connections)
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
+ }
+
+ // create a memory stream to buffer the response line and headers
+ NPT_MemoryStream buffer;
+
+ // emit the response line
+ NPT_CHECK_WARNING(response.Emit(buffer));
+
+ // send the buffer
+ NPT_CHECK_WARNING(m_Output->WriteFully(buffer.GetData(), buffer.GetDataSize()));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequestHandler Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+NPT_DEFINE_DYNAMIC_CAST_ANCHOR(NPT_HttpRequestHandler)
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequestHandler::SendResponseBody
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequestHandler::SendResponseBody(const NPT_HttpRequestContext& /*context*/,
+ NPT_HttpResponse& response,
+ NPT_OutputStream& output)
+{
+ NPT_HttpEntity* entity = response.GetEntity();
+ if (entity == NULL) return NPT_SUCCESS;
+
+ NPT_InputStreamReference body_stream;
+ entity->GetInputStream(body_stream);
+ if (body_stream.IsNull()) return NPT_SUCCESS;
+
+ // check for chunked transfer encoding
+ NPT_OutputStream* dest = &output;
+ if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
+ dest = new NPT_HttpChunkedOutputStream(output);
+ }
+
+ // send the body
+ NPT_LOG_FINE_1("sending body stream, %lld bytes", entity->GetContentLength());
+ NPT_LargeSize bytes_written = 0;
+ NPT_Result result = NPT_StreamToStreamCopy(*body_stream, *dest, 0, entity->GetContentLength(), &bytes_written);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE_3("body stream only partially sent, %lld bytes (%d:%s)",
+ bytes_written,
+ result,
+ NPT_ResultText(result));
+ }
+
+ // flush to write out any buffered data left in chunked output if used
+ dest->Flush();
+
+ // cleanup (this will send zero size chunk followed by CRLF)
+ if (dest != &output) delete dest;
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler(const void* data,
+ NPT_Size size,
+ const char* mime_type,
+ bool copy) :
+ m_MimeType(mime_type),
+ m_Buffer(data, size, copy)
+{}
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler(const char* document,
+ const char* mime_type,
+ bool copy) :
+ m_MimeType(mime_type),
+ m_Buffer(document, NPT_StringLength(document), copy)
+{}
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticRequestHandler::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpStaticRequestHandler::SetupResponse(NPT_HttpRequest& /*request*/,
+ const NPT_HttpRequestContext& /*context*/,
+ NPT_HttpResponse& response)
+{
+ NPT_HttpEntity* entity = response.GetEntity();
+ if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+ entity->SetContentType(m_MimeType);
+ entity->SetInputStream(m_Buffer.GetData(), m_Buffer.GetDataSize());
+
+ return NPT_SUCCESS;
+}
+
+const NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry
+NPT_HttpFileRequestHandler_DefaultFileTypeMap[] = {
+ {"xml", "text/xml; charset=\"utf-8\"" },
+ {"htm", "text/html" },
+ {"html", "text/html" },
+ {"c", "text/plain"},
+ {"h", "text/plain"},
+ {"txt", "text/plain"},
+ {"css", "text/css" },
+ {"manifest", "text/cache-manifest"},
+ {"gif", "image/gif" },
+ {"thm", "image/jpeg"},
+ {"png", "image/png"},
+ {"tif", "image/tiff"},
+ {"tiff", "image/tiff"},
+ {"jpg", "image/jpeg"},
+ {"jpeg", "image/jpeg"},
+ {"jpe", "image/jpeg"},
+ {"jp2", "image/jp2" },
+ {"png", "image/png" },
+ {"bmp", "image/bmp" },
+ {"aif", "audio/x-aiff"},
+ {"aifc", "audio/x-aiff"},
+ {"aiff", "audio/x-aiff"},
+ {"flac", "audio/x-flac"},
+ {"mka", "audio/x-matroska"},
+ {"mpa", "audio/mpeg"},
+ {"mp2", "audio/mpeg"},
+ {"mp3", "audio/mpeg"},
+ {"m4a", "audio/mp4"},
+ {"wma", "audio/x-ms-wma"},
+ {"wav", "audio/x-wav"},
+ {"mkv", "video/x-matroska"},
+ {"mpeg", "video/mpeg"},
+ {"mpg", "video/mpeg"},
+ {"mp4", "video/mp4"},
+ {"m4v", "video/mp4"},
+ {"ts", "video/MP2T"}, // RFC 3555
+ {"mpegts", "video/MP2T"},
+ {"mov", "video/quicktime"},
+ {"qt", "video/quicktime"},
+ {"wmv", "video/x-ms-wmv"},
+ {"wtv", "video/x-ms-wmv"},
+ {"asf", "video/x-ms-asf"},
+ {"mkv", "video/x-matroska"},
+ {"mk3d", "video/x-matroska-3d"},
+ {"flv", "video/x-flv"},
+ {"avi", "video/x-msvideo"},
+ {"divx", "video/x-msvideo"},
+ {"xvid", "video/x-msvideo"},
+ {"doc", "application/msword"},
+ {"js", "application/javascript"},
+ {"m3u8", "application/x-mpegURL"},
+ {"pdf", "application/pdf"},
+ {"ps", "application/postscript"},
+ {"eps", "application/postscript"},
+ {"zip", "application/zip"}
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler::NPT_HttpFileRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpFileRequestHandler::NPT_HttpFileRequestHandler(const char* url_root,
+ const char* file_root,
+ bool auto_dir,
+ const char* auto_index) :
+ m_UrlRoot(url_root),
+ m_FileRoot(file_root),
+ m_DefaultMimeType("text/html"),
+ m_UseDefaultFileTypeMap(true),
+ m_AutoDir(auto_dir),
+ m_AutoIndex(auto_index)
+{
+}
+
+/*----------------------------------------------------------------------
+| helper functions FIXME: need to move these to a separate module
++---------------------------------------------------------------------*/
+static NPT_UInt32
+_utf8_decode(const char** str)
+{
+ NPT_UInt32 result;
+ NPT_UInt32 min_value;
+ unsigned int bytes_left;
+
+ if (**str == 0) {
+ return ~0;
+ } else if ((**str & 0x80) == 0x00) {
+ result = *(*str)++;
+ bytes_left = 0;
+ min_value = 0;
+ } else if ((**str & 0xE0) == 0xC0) {
+ result = *(*str)++ & 0x1F;
+ bytes_left = 1;
+ min_value = 0x80;
+ } else if ((**str & 0xF0) == 0xE0) {
+ result = *(*str)++ & 0x0F;
+ bytes_left = 2;
+ min_value = 0x800;
+ } else if ((**str & 0xF8) == 0xF0) {
+ result = *(*str)++ & 0x07;
+ bytes_left = 3;
+ min_value = 0x10000;
+ } else {
+ return ~0;
+ }
+
+ while (bytes_left--) {
+ if (**str == 0 || (**str & 0xC0) != 0x80) return ~0;
+ result = (result << 6) | (*(*str)++ & 0x3F);
+ }
+
+ if (result < min_value || (result & 0xFFFFF800) == 0xD800 || result > 0x10FFFF) {
+ return ~0;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HtmlEncode
++---------------------------------------------------------------------*/
+static NPT_String
+NPT_HtmlEncode(const char* str, const char* chars)
+{
+ NPT_String encoded;
+
+ // check args
+ if (str == NULL) return encoded;
+
+ // reserve at least the size of the current uri
+ encoded.Reserve(NPT_StringLength(str));
+
+ // process each character
+ while (*str) {
+ NPT_UInt32 c = _utf8_decode(&str);
+ bool encode = false;
+ if (c < ' ' || c > '~') {
+ encode = true;
+ } else {
+ const char* match = chars;
+ while (*match) {
+ if (c == (NPT_UInt32)*match) {
+ encode = true;
+ break;
+ }
+ ++match;
+ }
+ }
+ if (encode) {
+ // encode
+ char hex[9];
+ encoded += "&#x";
+ unsigned int len = 0;
+ if (c > 0xFFFF) {
+ NPT_ByteToHex((unsigned char)(c>>24), &hex[0], true);
+ NPT_ByteToHex((unsigned char)(c>>16), &hex[2], true);
+ len = 4;
+ }
+ NPT_ByteToHex((unsigned char)(c>>8), &hex[len ], true);
+ NPT_ByteToHex((unsigned char)(c ), &hex[len+2], true);
+ hex[len+4] = ';';
+ encoded.Append(hex, len+5);
+ } else {
+ // no encoding required
+ encoded += (char)c;
+ }
+ }
+
+ return encoded;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpFileRequestHandler::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& /* context */,
+ NPT_HttpResponse& response)
+{
+ NPT_HttpEntity* entity = response.GetEntity();
+ if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+ // check the method
+ if (request.GetMethod() != NPT_HTTP_METHOD_GET &&
+ request.GetMethod() != NPT_HTTP_METHOD_HEAD) {
+ response.SetStatus(405, "Method Not Allowed");
+ return NPT_SUCCESS;
+ }
+
+ // set some default headers
+ response.GetHeaders().SetHeader(NPT_HTTP_HEADER_ACCEPT_RANGES, "bytes");
+
+ // declare HTTP/1.1 if the client asked for it
+ if (request.GetProtocol() == NPT_HTTP_PROTOCOL_1_1) {
+ response.SetProtocol(NPT_HTTP_PROTOCOL_1_1);
+ }
+
+ // TODO: we need to normalize the request path
+
+ // check that the request's path is an entry under the url root
+ if (!request.GetUrl().GetPath(true).StartsWith(m_UrlRoot)) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // compute the filename
+ NPT_String filename = m_FileRoot;
+ NPT_String relative_path = NPT_Url::PercentDecode(request.GetUrl().GetPath().GetChars()+m_UrlRoot.GetLength());
+ filename += "/";
+ filename += relative_path;
+ NPT_LOG_FINE_1("filename = %s", filename.GetChars());
+
+ // get info about the file
+ NPT_FileInfo info;
+ NPT_File::GetInfo(filename, &info);
+
+ // check if this is a directory
+ if (info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY) {
+ NPT_LOG_FINE("file is a DIRECTORY");
+ if (m_AutoDir) {
+ if (m_AutoIndex.GetLength()) {
+ NPT_LOG_FINE("redirecting to auto-index");
+ filename += NPT_FilePath::Separator;
+ filename += m_AutoIndex;
+ if (NPT_File::Exists(filename)) {
+ NPT_String location = m_UrlRoot+"/"+m_AutoIndex;
+ response.SetStatus(302, "Found");
+ response.GetHeaders().SetHeader(NPT_HTTP_HEADER_LOCATION, location);
+ } else {
+ return NPT_ERROR_PERMISSION_DENIED;
+ }
+ } else {
+ NPT_LOG_FINE("doing auto-dir");
+
+ // get the dir entries
+ NPT_List<NPT_String> entries;
+ NPT_File::ListDir(filename, entries);
+
+ NPT_String html;
+ html.Reserve(1024+128*entries.GetItemCount());
+
+ NPT_String html_dirname = NPT_HtmlEncode(relative_path, "<>&");
+ html += "<hmtl><head><title>Directory Listing for /";
+ html += html_dirname;
+ html += "</title></head><body>";
+ html += "<h2>Directory Listing for /";
+ html += html_dirname;
+ html += "</h2><hr><ul>\r\n";
+ NPT_String url_base_path = NPT_HtmlEncode(request.GetUrl().GetPath(), "<>&\"");
+
+ for (NPT_List<NPT_String>::Iterator i = entries.GetFirstItem();
+ i;
+ ++i) {
+ NPT_String url_filename = NPT_HtmlEncode(*i, "<>&");
+ html += "<li><a href=\"";
+ html += url_base_path;
+ if (!url_base_path.EndsWith("/")) html += "/";
+ html += url_filename;
+ html += "\">";
+ html +=url_filename;
+
+ NPT_String full_path = filename;
+ full_path += "/";
+ full_path += *i;
+ NPT_File::GetInfo(full_path, &info);
+ if (info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY) html += "/";
+
+ html += "</a><br>\r\n";
+ }
+ html += "</ul></body></html>";
+
+ entity->SetContentType("text/html");
+ entity->SetInputStream(html);
+ return NPT_SUCCESS;
+ }
+ } else {
+ return NPT_ERROR_PERMISSION_DENIED;
+ }
+ }
+
+ // open the file
+ NPT_File file(filename);
+ NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_READ);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE("file not found");
+ return NPT_ERROR_NO_SUCH_ITEM;
+ }
+ NPT_InputStreamReference stream;
+ file.GetInputStream(stream);
+
+ // check for range requests
+ const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE);
+
+ // setup entity body
+ NPT_CHECK(SetupResponseBody(response, stream, range_spec));
+
+ // set the response body
+ entity->SetContentType(GetContentType(filename));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler::SetupResponseBody
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpFileRequestHandler::SetupResponseBody(NPT_HttpResponse& response,
+ NPT_InputStreamReference& stream,
+ const NPT_String* range_spec /* = NULL */)
+{
+ NPT_HttpEntity* entity = response.GetEntity();
+ if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+ if (range_spec) {
+ const NPT_String* accept_range = response.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_ACCEPT_RANGES);
+
+ if (response.GetEntity()->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED ||
+ (accept_range && accept_range->Compare("bytes"))) {
+ NPT_LOG_FINE("range request not supported");
+ response.SetStatus(416, "Requested Range Not Satisfiable");
+ return NPT_SUCCESS;
+ }
+
+ // measure the stream size
+ bool has_stream_size = false;
+ NPT_LargeSize stream_size = 0;
+ NPT_Result result = stream->GetSize(stream_size);
+ if (NPT_SUCCEEDED(result)) {
+ has_stream_size = true;
+ NPT_LOG_FINE_1("body size=%lld", stream_size);
+ if (stream_size == 0) return NPT_SUCCESS;
+ }
+
+ if (!range_spec->StartsWith("bytes=")) {
+ NPT_LOG_FINE("unknown range spec");
+ response.SetStatus(400, "Bad Request");
+ return NPT_SUCCESS;
+ }
+ NPT_String valid_range;
+ NPT_String range(range_spec->GetChars()+6);
+ if (range.Find(',') >= 0) {
+ NPT_LOG_FINE("multi-range requests not supported");
+ if (has_stream_size) {
+ valid_range = "bytes */";
+ valid_range += NPT_String::FromInteger(stream_size);
+ response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, valid_range.GetChars());
+ }
+ response.SetStatus(416, "Requested Range Not Satisfiable");
+ return NPT_SUCCESS;
+ }
+ int sep = range.Find('-');
+ NPT_UInt64 range_start = 0;
+ NPT_UInt64 range_end = 0;
+ bool has_start = false;
+ bool has_end = false;
+ bool satisfied = false;
+ if (sep < 0) {
+ NPT_LOG_FINE("invalid syntax");
+ response.SetStatus(400, "Bad Request");
+ return NPT_SUCCESS;
+ } else {
+ if ((unsigned int)sep+1 < range.GetLength()) {
+ result = NPT_ParseInteger64(range.GetChars()+sep+1, range_end);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE("failed to parse range end");
+ return result;
+ }
+ range.SetLength(sep);
+ has_end = true;
+ }
+ if (sep > 0) {
+ result = range.ToInteger64(range_start);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_FINE("failed to parse range start");
+ return result;
+ }
+ has_start = true;
+ }
+
+ if (!has_stream_size) {
+ if (has_start && range_start == 0 && !has_end) {
+ bool update_content_length = (entity->GetTransferEncoding() != NPT_HTTP_TRANSFER_ENCODING_CHUNKED);
+ // use the whole file stream as a body
+ return entity->SetInputStream(stream, update_content_length);
+ } else {
+ NPT_LOG_WARNING_2("file.GetSize() failed (%d:%s)", result, NPT_ResultText(result));
+ NPT_LOG_FINE("range request not supported");
+ response.SetStatus(416, "Requested Range Not Satisfiable");
+ return NPT_SUCCESS;
+ }
+ }
+
+ if (has_start) {
+ // some clients sends incorrect range_end equal to size
+ // we try to handle it
+ if (!has_end || range_end == stream_size) range_end = stream_size-1;
+ } else {
+ if (has_end) {
+ if (range_end <= stream_size) {
+ range_start = stream_size-range_end;
+ range_end = stream_size-1;
+ }
+ }
+ }
+ NPT_LOG_FINE_2("final range: start=%lld, end=%lld", range_start, range_end);
+ if (range_start > range_end) {
+ NPT_LOG_FINE("invalid range");
+ response.SetStatus(400, "Bad Request");
+ satisfied = false;
+ } else if (range_end >= stream_size) {
+ response.SetStatus(416, "Requested Range Not Satisfiable");
+ NPT_LOG_FINE("out of range");
+ satisfied = false;
+ } else {
+ satisfied = true;
+ }
+ }
+ if (satisfied && range_start != 0) {
+ // seek in the stream
+ result = stream->Seek(range_start);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_2("stream.Seek() failed (%d:%s)", result, NPT_ResultText(result));
+ satisfied = false;
+ }
+ }
+ if (!satisfied) {
+ if (!valid_range.IsEmpty()) response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, valid_range.GetChars());
+ response.SetStatus(416, "Requested Range Not Satisfiable");
+ return NPT_SUCCESS;
+ }
+
+ // use a portion of the file stream as a body
+ entity->SetInputStream(stream, false);
+ entity->SetContentLength(range_end-range_start+1);
+ response.SetStatus(206, "Partial Content");
+ valid_range = "bytes ";
+ valid_range += NPT_String::FromInteger(range_start);
+ valid_range += "-";
+ valid_range += NPT_String::FromInteger(range_end);
+ valid_range += "/";
+ valid_range += NPT_String::FromInteger(stream_size);
+ response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, valid_range.GetChars());
+ } else {
+ bool update_content_length = (entity->GetTransferEncoding() != NPT_HTTP_TRANSFER_ENCODING_CHUNKED);
+ // use the whole file stream as a body
+ entity->SetInputStream(stream, update_content_length);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler::GetContentType
++---------------------------------------------------------------------*/
+const char*
+NPT_HttpFileRequestHandler::GetDefaultContentType(const char* extension)
+{
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(NPT_HttpFileRequestHandler_DefaultFileTypeMap); i++) {
+ if (NPT_String::Compare(extension, NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].extension, true) == 0) {
+ const char* type = NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].mime_type;
+ NPT_LOG_FINE_1("using type from default list: %s", type);
+ return type;
+ }
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler::GetContentType
++---------------------------------------------------------------------*/
+const char*
+NPT_HttpFileRequestHandler::GetContentType(const NPT_String& filename)
+{
+ int last_dot = filename.ReverseFind('.');
+ if (last_dot > 0) {
+ NPT_String extension = filename.GetChars()+last_dot+1;
+ extension.MakeLowercase();
+
+ NPT_LOG_FINE_1("extension=%s", extension.GetChars());
+
+ NPT_String* mime_type;
+ if (NPT_SUCCEEDED(m_FileTypeMap.Get(extension, mime_type))) {
+ NPT_LOG_FINE_1("found mime type in map: %s", mime_type->GetChars());
+ return mime_type->GetChars();
+ }
+
+ // not found, look in the default map if necessary
+ if (m_UseDefaultFileTypeMap) {
+ const char* type = NPT_HttpFileRequestHandler::GetDefaultContentType(extension);
+ if (type) return type;
+ }
+ }
+
+ NPT_LOG_FINE("using default mime type");
+ return m_DefaultMimeType;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::NPT_HttpChunkedInputStream
++---------------------------------------------------------------------*/
+NPT_HttpChunkedInputStream::NPT_HttpChunkedInputStream(
+ NPT_BufferedInputStreamReference& stream) :
+ m_Source(stream),
+ m_CurrentChunkSize(0),
+ m_Eos(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::~NPT_HttpChunkedInputStream
++---------------------------------------------------------------------*/
+NPT_HttpChunkedInputStream::~NPT_HttpChunkedInputStream()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::NPT_HttpChunkedInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read /* = NULL */)
+{
+ // set the initial state of return values
+ if (bytes_read) *bytes_read = 0;
+
+ // check for end of stream
+ if (m_Eos) return NPT_ERROR_EOS;
+
+ // shortcut
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // read next chunk size if needed
+ if (m_CurrentChunkSize == 0) {
+ // buffered mode
+ m_Source->SetBufferSize(4096);
+
+ NPT_String size_line;
+ NPT_CHECK_FINE(m_Source->ReadLine(size_line));
+
+ // decode size (in hex)
+ m_CurrentChunkSize = 0;
+ if (size_line.GetLength() < 1) {
+ NPT_LOG_WARNING("empty chunk size line");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ const char* size_hex = size_line.GetChars();
+ while (*size_hex != '\0' &&
+ *size_hex != ' ' &&
+ *size_hex != ';' &&
+ *size_hex != '\r' &&
+ *size_hex != '\n') {
+ int nibble = NPT_HexToNibble(*size_hex);
+ if (nibble < 0) {
+ NPT_LOG_WARNING_1("invalid chunk size format (%s)", size_line.GetChars());
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ m_CurrentChunkSize = (m_CurrentChunkSize<<4)|nibble;
+ ++size_hex;
+ }
+ NPT_LOG_FINEST_1("start of chunk, size=%d", m_CurrentChunkSize);
+
+ // 0 = end of body
+ if (m_CurrentChunkSize == 0) {
+ NPT_LOG_FINEST("end of chunked stream, reading trailers");
+
+ // read footers until empty line
+ NPT_String footer;
+ do {
+ NPT_CHECK_FINE(m_Source->ReadLine(footer));
+ } while (!footer.IsEmpty());
+ m_Eos = true;
+
+ NPT_LOG_FINEST("end of chunked stream, done");
+ return NPT_ERROR_EOS;
+ }
+
+ // unbuffer source
+ m_Source->SetBufferSize(0);
+ }
+
+ // read no more than what's left in chunk
+ NPT_Size chunk_bytes_read;
+ if (bytes_to_read > m_CurrentChunkSize) bytes_to_read = m_CurrentChunkSize;
+ NPT_CHECK_FINE(m_Source->Read(buffer, bytes_to_read, &chunk_bytes_read));
+
+ // ready to go to next chunk?
+ m_CurrentChunkSize -= chunk_bytes_read;
+ if (m_CurrentChunkSize == 0) {
+ NPT_LOG_FINEST("reading end of chunk");
+
+ // when a chunk is finished, a \r\n follows
+ char newline[2];
+ NPT_CHECK_FINE(m_Source->ReadFully(newline, 2));
+ if (newline[0] != '\r' || newline[1] != '\n') {
+ NPT_LOG_WARNING("invalid end of chunk (expected \\r\\n)");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ }
+
+ // update output params
+ if (bytes_read) *bytes_read = chunk_bytes_read;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedInputStream::Seek(NPT_Position /*offset*/)
+{
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedInputStream::Tell(NPT_Position& offset)
+{
+ offset = 0;
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedInputStream::GetSize(NPT_LargeSize& size)
+{
+ return m_Source->GetSize(size);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ return m_Source->GetAvailable(available);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedOutputStream::NPT_HttpChunkedOutputStream
++---------------------------------------------------------------------*/
+NPT_HttpChunkedOutputStream::NPT_HttpChunkedOutputStream(NPT_OutputStream& stream) :
+ m_Stream(stream)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedOutputStream::~NPT_HttpChunkedOutputStream
++---------------------------------------------------------------------*/
+NPT_HttpChunkedOutputStream::~NPT_HttpChunkedOutputStream()
+{
+ // zero size chunk followed by CRLF (no trailer)
+ m_Stream.WriteFully("0" NPT_HTTP_LINE_TERMINATOR NPT_HTTP_LINE_TERMINATOR, 5);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedOutputStream::Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written)
+{
+ // default values
+ if (bytes_written) *bytes_written = 0;
+
+ // shortcut
+ if (bytes_to_write == 0) return NPT_SUCCESS;
+
+ // write the chunk header
+ char size[16];
+ size[15] = '\n';
+ size[14] = '\r';
+ char* c = &size[14];
+ unsigned int char_count = 2;
+ unsigned int value = bytes_to_write;
+ do {
+ unsigned int digit = (unsigned int)(value%16);
+ if (digit < 10) {
+ *--c = '0'+digit;
+ } else {
+ *--c = 'A'+digit-10;
+ }
+ char_count++;
+ value /= 16;
+ } while(value);
+ NPT_Result result = m_Stream.WriteFully(c, char_count);
+ if (NPT_FAILED(result)) return result;
+
+ // write the chunk data
+ result = m_Stream.WriteFully(buffer, bytes_to_write);
+ if (NPT_FAILED(result)) return result;
+
+ // finish the chunk
+ result = m_Stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+ if (NPT_SUCCEEDED(result) && bytes_written) {
+ *bytes_written = bytes_to_write;
+ }
+ return result;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptHttp.h b/lib/libUPnP/Neptune/Source/Core/NptHttp.h
new file mode 100644
index 0000000..3d2a0d2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptHttp.h
@@ -0,0 +1,866 @@
+/*****************************************************************
+|
+| Neptune - HTTP Protocol
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_HTTP_H_
+#define _NPT_HTTP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptUri.h"
+#include "NptTypes.h"
+#include "NptList.h"
+#include "NptBufferedStreams.h"
+#include "NptSockets.h"
+#include "NptMap.h"
+#include "NptDynamicCast.h"
+#include "NptVersion.h"
+#include "NptTime.h"
+#include "NptThreads.h"
+#include "NptAutomaticCleaner.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_HTTP_DEFAULT_PORT = 80;
+const unsigned int NPT_HTTPS_DEFAULT_PORT = 443;
+const unsigned int NPT_HTTP_INVALID_PORT = 0;
+
+const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT = 30000;
+const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_IO_TIMEOUT = 30000;
+const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_NAME_RESOLVER_TIMEOUT = 60000;
+const unsigned int NPT_HTTP_CLIENT_DEFAULT_MAX_REDIRECTS = 20;
+
+const NPT_Timeout NPT_HTTP_SERVER_DEFAULT_CONNECTION_TIMEOUT = NPT_TIMEOUT_INFINITE;
+const NPT_Timeout NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT = 60000;
+
+const unsigned int NPT_HTTP_CONNECTION_MANAGER_MAX_CONNECTION_POOL_SIZE = 5;
+const unsigned int NPT_HTTP_CONNECTION_MANAGER_MAX_CONNECTION_AGE = 30; // seconds
+const unsigned int NPT_HTTP_MAX_RECONNECTS = 10;
+const unsigned int NPT_HTTP_MAX_100_RESPONSES = 10;
+
+const int NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH = 8192;
+const int NPT_HTTP_PROTOCOL_MAX_HEADER_COUNT = 100;
+
+#define NPT_HTTP_PROTOCOL_1_0 "HTTP/1.0"
+#define NPT_HTTP_PROTOCOL_1_1 "HTTP/1.1"
+#define NPT_HTTP_METHOD_GET "GET"
+#define NPT_HTTP_METHOD_HEAD "HEAD"
+#define NPT_HTTP_METHOD_POST "POST"
+#define NPT_HTTP_METHOD_PUT "PUT"
+#define NPT_HTTP_METHOD_OPTIONS "OPTIONS"
+#define NPT_HTTP_METHOD_DELETE "DELETE"
+#define NPT_HTTP_METHOD_TRACE "TRACE"
+
+#define NPT_HTTP_HEADER_HOST "Host"
+#define NPT_HTTP_HEADER_CONNECTION "Connection"
+#define NPT_HTTP_HEADER_USER_AGENT "User-Agent"
+#define NPT_HTTP_HEADER_SERVER "Server"
+#define NPT_HTTP_HEADER_CONTENT_LENGTH "Content-Length"
+#define NPT_HTTP_HEADER_CONTENT_TYPE "Content-Type"
+#define NPT_HTTP_HEADER_CONTENT_ENCODING "Content-Encoding"
+#define NPT_HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding"
+#define NPT_HTTP_HEADER_LOCATION "Location"
+#define NPT_HTTP_HEADER_RANGE "Range"
+#define NPT_HTTP_HEADER_CONTENT_RANGE "Content-Range"
+#define NPT_HTTP_HEADER_COOKIE "Cookie"
+#define NPT_HTTP_HEADER_ACCEPT_RANGES "Accept-Ranges"
+#define NPT_HTTP_HEADER_CONTENT_RANGE "Content-Range"
+#define NPT_HTTP_HEADER_AUTHORIZATION "Authorization"
+
+#define NPT_HTTP_TRANSFER_ENCODING_CHUNKED "chunked"
+
+
+const int NPT_ERROR_HTTP_INVALID_RESPONSE_LINE = NPT_ERROR_BASE_HTTP - 0;
+const int NPT_ERROR_HTTP_INVALID_REQUEST_LINE = NPT_ERROR_BASE_HTTP - 1;
+const int NPT_ERROR_HTTP_NO_PROXY = NPT_ERROR_BASE_HTTP - 2;
+const int NPT_ERROR_HTTP_INVALID_REQUEST = NPT_ERROR_BASE_HTTP - 3;
+const int NPT_ERROR_HTTP_METHOD_NOT_SUPPORTED = NPT_ERROR_BASE_HTTP - 4;
+const int NPT_ERROR_HTTP_TOO_MANY_REDIRECTS = NPT_ERROR_BASE_HTTP - 5;
+const int NPT_ERROR_HTTP_TOO_MANY_RECONNECTS = NPT_ERROR_BASE_HTTP - 6;
+const int NPT_ERROR_HTTP_CANNOT_RESEND_BODY = NPT_ERROR_BASE_HTTP - 7;
+
+#define NPT_HTTP_LINE_TERMINATOR "\r\n"
+
+#if !defined(NPT_CONFIG_HTTP_DEFAULT_USER_AGENT)
+#define NPT_CONFIG_HTTP_DEFAULT_USER_AGENT "Neptune/" NPT_NEPTUNE_VERSION_STRING
+#endif
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef unsigned int NPT_HttpStatusCode;
+typedef NPT_UrlQuery NPT_HttpUrlQuery; // for backward compatibility
+
+/*----------------------------------------------------------------------
+| NPT_HttpUrl
++---------------------------------------------------------------------*/
+class NPT_HttpUrl : public NPT_Url {
+public:
+ // constructors
+ NPT_HttpUrl() {}
+ NPT_HttpUrl(const char* host,
+ NPT_UInt16 port,
+ const char* path,
+ const char* query = NULL,
+ const char* fragment = NULL);
+ NPT_HttpUrl(const char* url, bool ignore_scheme = false);
+
+ // methods
+ NPT_String ToString(bool with_fragment = true) const override;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpProtocol
++---------------------------------------------------------------------*/
+class NPT_HttpProtocol
+{
+public:
+ // class methods
+ const char* GetStatusCodeString(NPT_HttpStatusCode status_code);
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeader
++---------------------------------------------------------------------*/
+class NPT_HttpHeader {
+public:
+ // constructors and destructor
+ NPT_HttpHeader(const char* name, const char* value);
+ ~NPT_HttpHeader();
+
+ // methods
+ NPT_Result Emit(NPT_OutputStream& stream) const;
+ const NPT_String& GetName() const { return m_Name; }
+ const NPT_String& GetValue() const { return m_Value; }
+ NPT_Result SetName(const char* name);
+ NPT_Result SetValue(const char* value);
+
+private:
+ // members
+ NPT_String m_Name;
+ NPT_String m_Value;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaders
++---------------------------------------------------------------------*/
+class NPT_HttpHeaders {
+public:
+ // constructors and destructor
+ NPT_HttpHeaders();
+ ~NPT_HttpHeaders();
+
+ // methods
+ NPT_Result Parse(NPT_BufferedInputStream& stream);
+ NPT_Result Emit(NPT_OutputStream& stream) const;
+ const NPT_List<NPT_HttpHeader*>& GetHeaders() const { return m_Headers; }
+ NPT_HttpHeader* GetHeader(const char* name) const;
+ const NPT_String* GetHeaderValue(const char* name) const;
+ NPT_Result SetHeader(const char* name, const char* value, bool replace=true);
+ NPT_Result AddHeader(const char* name, const char* value);
+ NPT_Result RemoveHeader(const char* name);
+
+private:
+ // members
+ NPT_List<NPT_HttpHeader*> m_Headers;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpEntity
++---------------------------------------------------------------------*/
+class NPT_HttpEntity {
+public:
+ // constructors and destructor
+ NPT_HttpEntity();
+ NPT_HttpEntity(const NPT_HttpHeaders& headers);
+ virtual ~NPT_HttpEntity();
+
+ // methods
+ NPT_Result SetInputStream(const NPT_InputStreamReference& stream,
+ bool update_content_length = false);
+ NPT_Result SetInputStream(const void* data, NPT_Size size);
+ NPT_Result SetInputStream(const NPT_String& string);
+ NPT_Result SetInputStream(const char* string);
+ NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+ NPT_Result Load(NPT_DataBuffer& buffer);
+ NPT_Result SetHeaders(const NPT_HttpHeaders& headers);
+
+ // field access
+ NPT_Result SetContentLength(NPT_LargeSize length);
+ NPT_Result SetContentType(const char* type);
+ NPT_Result SetContentEncoding(const char* encoding);
+ NPT_Result SetTransferEncoding(const char* encoding);
+ NPT_LargeSize GetContentLength() { return m_ContentLength; }
+ const NPT_String& GetContentType() { return m_ContentType; }
+ const NPT_String& GetContentEncoding() { return m_ContentEncoding; }
+ const NPT_String& GetTransferEncoding() { return m_TransferEncoding;}
+ bool ContentLengthIsKnown() { return m_ContentLengthIsKnown; }
+
+private:
+ // members
+ NPT_InputStreamReference m_InputStream;
+ NPT_LargeSize m_ContentLength;
+ NPT_String m_ContentType;
+ NPT_String m_ContentEncoding;
+ NPT_String m_TransferEncoding;
+ bool m_ContentLengthIsKnown;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage
++---------------------------------------------------------------------*/
+class NPT_HttpMessage {
+public:
+ // constructors and destructor
+ virtual ~NPT_HttpMessage();
+
+ // methods
+ const NPT_String& GetProtocol() const {
+ return m_Protocol;
+ }
+ NPT_Result SetProtocol(const char* protocol) {
+ m_Protocol = protocol;
+ return NPT_SUCCESS;
+ }
+ NPT_HttpHeaders& GetHeaders() {
+ return m_Headers;
+ }
+ const NPT_HttpHeaders& GetHeaders() const {
+ return m_Headers;
+ }
+ NPT_Result SetEntity(NPT_HttpEntity* entity);
+ NPT_HttpEntity* GetEntity() {
+ return m_Entity;
+ }
+ NPT_HttpEntity* GetEntity() const {
+ return m_Entity;
+ }
+ virtual NPT_Result ParseHeaders(NPT_BufferedInputStream& stream);
+
+protected:
+ // constructors
+ NPT_HttpMessage(const char* protocol);
+
+ // members
+ NPT_String m_Protocol;
+ NPT_HttpHeaders m_Headers;
+ NPT_HttpEntity* m_Entity;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequest
++---------------------------------------------------------------------*/
+class NPT_HttpRequest : public NPT_HttpMessage {
+public:
+ // class methods
+ static NPT_Result Parse(NPT_BufferedInputStream& stream,
+ const NPT_SocketAddress* endpoint,
+ NPT_HttpRequest*& request);
+
+ // constructors and destructor
+ NPT_HttpRequest(const NPT_HttpUrl& url,
+ const char* method,
+ const char* protocol = NPT_HTTP_PROTOCOL_1_0);
+ NPT_HttpRequest(const char* url,
+ const char* method,
+ const char* protocol = NPT_HTTP_PROTOCOL_1_0);
+ ~NPT_HttpRequest() override;
+
+ // methods
+ const NPT_HttpUrl& GetUrl() const { return m_Url; }
+ NPT_HttpUrl& GetUrl() { return m_Url; }
+ NPT_Result SetUrl(const char* url);
+ NPT_Result SetUrl(const NPT_HttpUrl& url);
+ const NPT_String& GetMethod() const { return m_Method; }
+ virtual NPT_Result Emit(NPT_OutputStream& stream, bool use_proxy=false) const;
+
+protected:
+ // members
+ NPT_HttpUrl m_Url;
+ NPT_String m_Method;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponse
++---------------------------------------------------------------------*/
+class NPT_HttpResponse : public NPT_HttpMessage {
+public:
+ // class methods
+ static NPT_Result Parse(NPT_BufferedInputStream& stream,
+ NPT_HttpResponse*& response);
+
+ // constructors and destructor
+ NPT_HttpResponse(NPT_HttpStatusCode status_code,
+ const char* reason_phrase,
+ const char* protocol = NPT_HTTP_PROTOCOL_1_0);
+ ~NPT_HttpResponse() override;
+
+ // methods
+ NPT_Result SetStatus(NPT_HttpStatusCode status_code,
+ const char* reason_phrase,
+ const char* protocol = NULL);
+ NPT_Result SetProtocol(const char* protocol);
+ NPT_HttpStatusCode GetStatusCode() const { return m_StatusCode; }
+ const NPT_String& GetReasonPhrase() const { return m_ReasonPhrase; }
+ virtual NPT_Result Emit(NPT_OutputStream& stream) const;
+
+protected:
+ // members
+ NPT_HttpStatusCode m_StatusCode;
+ NPT_String m_ReasonPhrase;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpProxyAddress
++---------------------------------------------------------------------*/
+class NPT_HttpProxyAddress
+{
+public:
+ NPT_HttpProxyAddress() : m_Port(NPT_HTTP_INVALID_PORT) {}
+ NPT_HttpProxyAddress(const char* hostname, NPT_UInt16 port) :
+ m_HostName(hostname), m_Port(port) {}
+
+ const NPT_String& GetHostName() const { return m_HostName; }
+ void SetHostName(const char* hostname) { m_HostName = hostname; }
+ NPT_UInt16 GetPort() const { return m_Port; }
+ void SetPort(NPT_UInt16 port) { m_Port = port; }
+
+private:
+ NPT_String m_HostName;
+ NPT_UInt16 m_Port;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpProxySelector
++---------------------------------------------------------------------*/
+class NPT_HttpProxySelector
+{
+public:
+ // class methods
+ static NPT_HttpProxySelector* GetDefault();
+ static NPT_HttpProxySelector* GetSystemSelector();
+
+ // methods
+ virtual ~NPT_HttpProxySelector() {};
+ virtual NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy) = 0;
+
+private:
+ // class members
+ static NPT_HttpProxySelector* m_SystemDefault;
+};
+
+class NPT_HttpRequestContext;
+
+/*----------------------------------------------------------------------
+| NPT_HttpClient
++---------------------------------------------------------------------*/
+class NPT_HttpClient {
+public:
+ // types
+ struct Config {
+ Config() : m_ConnectionTimeout( NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT),
+ m_IoTimeout( NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT),
+ m_NameResolverTimeout(NPT_HTTP_CLIENT_DEFAULT_NAME_RESOLVER_TIMEOUT),
+ m_MaxRedirects( NPT_HTTP_CLIENT_DEFAULT_MAX_REDIRECTS),
+ m_UserAgent( NPT_CONFIG_HTTP_DEFAULT_USER_AGENT) {}
+ NPT_Timeout m_ConnectionTimeout;
+ NPT_Timeout m_IoTimeout;
+ NPT_Timeout m_NameResolverTimeout;
+ NPT_Cardinal m_MaxRedirects;
+ NPT_String m_UserAgent;
+ };
+
+ class Connection {
+ public:
+ virtual ~Connection() {}
+ virtual NPT_InputStreamReference& GetInputStream() = 0;
+ virtual NPT_OutputStreamReference& GetOutputStream() = 0;
+ virtual NPT_Result GetInfo(NPT_SocketInfo& info) = 0;
+ virtual bool SupportsPersistence() { return false; }
+ virtual bool IsRecycled() { return false; }
+ virtual NPT_Result Recycle() { delete this; return NPT_SUCCESS; }
+ virtual NPT_Result Abort() { return NPT_ERROR_NOT_IMPLEMENTED; }
+ };
+
+ class Connector {
+ public:
+ virtual ~Connector() {}
+
+ virtual NPT_Result Connect(const NPT_HttpUrl& url,
+ NPT_HttpClient& client,
+ const NPT_HttpProxyAddress* proxy,
+ bool reuse, // whether we can reuse a connection or not
+ Connection*& connection) = 0;
+
+ protected:
+ NPT_Result TrackConnection(NPT_HttpClient& client,
+ Connection* connection) { return client.TrackConnection(connection); }
+ Connector() {} // don't instantiate directly
+ };
+
+ // class methods
+ static NPT_Result WriteRequest(NPT_OutputStream& output_stream,
+ NPT_HttpRequest& request,
+ bool should_persist,
+ bool use_proxy = false);
+ static NPT_Result ReadResponse(NPT_InputStreamReference& input_stream,
+ bool should_persist,
+ bool expect_entity,
+ NPT_HttpResponse*& response,
+ NPT_Reference<Connection>* cref = NULL);
+
+ /**
+ * @param connector Pointer to a connector instance, or NULL to use
+ * the default (TCP) connector.
+ * @param transfer_ownership Boolean flag. If true, the NPT_HttpClient object
+ * becomes the owner of the passed Connector and will delete it when it is
+ * itself deleted. If false, the caller keeps the ownership of the connector.
+ * This flag is ignored if the connector parameter is NULL.
+ */
+ NPT_HttpClient(Connector* connector = NULL, bool transfer_ownership = true);
+
+ virtual ~NPT_HttpClient();
+
+ // methods
+ NPT_Result SendRequest(NPT_HttpRequest& request,
+ NPT_HttpResponse*& response,
+ NPT_HttpRequestContext* context = NULL);
+ NPT_Result Abort();
+ const Config& GetConfig() const { return m_Config; }
+ NPT_Result SetConfig(const Config& config);
+ NPT_Result SetProxy(const char* http_proxy_hostname,
+ NPT_UInt16 http_proxy_port,
+ const char* https_proxy_hostname = NULL,
+ NPT_UInt16 https_proxy_port = 0);
+ NPT_Result SetProxySelector(NPT_HttpProxySelector* selector);
+ NPT_Result SetConnector(Connector* connector);
+ NPT_Result SetTimeouts(NPT_Timeout connection_timeout,
+ NPT_Timeout io_timeout,
+ NPT_Timeout name_resolver_timeout);
+ NPT_Result SetUserAgent(const char* user_agent);
+ NPT_Result SetOptions(NPT_Flags options, bool on);
+
+protected:
+ // methods
+ NPT_Result TrackConnection(Connection* connection);
+ NPT_Result SendRequestOnce(NPT_HttpRequest& request,
+ NPT_HttpResponse*& response,
+ NPT_HttpRequestContext* context = NULL);
+
+ // members
+ Config m_Config;
+ NPT_HttpProxySelector* m_ProxySelector;
+ bool m_ProxySelectorIsOwned;
+ Connector* m_Connector;
+ bool m_ConnectorIsOwned;
+ NPT_Mutex m_AbortLock;
+ bool m_Aborted;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpConnectionManager
++---------------------------------------------------------------------*/
+class NPT_HttpConnectionManager : public NPT_Thread,
+ public NPT_AutomaticCleaner::Singleton
+{
+public:
+ // singleton management
+ static NPT_HttpConnectionManager* GetInstance();
+
+ class Connection : public NPT_HttpClient::Connection
+ {
+ public:
+ Connection(NPT_HttpConnectionManager& manager,
+ NPT_SocketReference& socket,
+ NPT_InputStreamReference input_stream,
+ NPT_OutputStreamReference output_stream);
+ ~Connection() override;
+
+ // NPT_HttpClient::Connection methods
+ NPT_InputStreamReference& GetInputStream() override { return m_InputStream; }
+ NPT_OutputStreamReference& GetOutputStream() override { return m_OutputStream; }
+ NPT_Result GetInfo(NPT_SocketInfo& info) override { return m_Socket->GetInfo(info); }
+ bool SupportsPersistence() override { return true; }
+ bool IsRecycled() override { return m_IsRecycled; }
+ NPT_Result Recycle() override;
+ NPT_Result Abort() override { return m_Socket->Cancel(); }
+
+ // members
+ NPT_HttpConnectionManager& m_Manager;
+ bool m_IsRecycled;
+ NPT_TimeStamp m_TimeStamp;
+ NPT_SocketReference m_Socket;
+ NPT_InputStreamReference m_InputStream;
+ NPT_OutputStreamReference m_OutputStream;
+ };
+
+ // destructor
+ ~NPT_HttpConnectionManager() override;
+
+ // methods
+ Connection* FindConnection(NPT_SocketAddress& address);
+ NPT_Result Recycle(Connection* connection);
+ NPT_Result Track(NPT_HttpClient* client, NPT_HttpClient::Connection* connection);
+ NPT_Result AbortConnections(NPT_HttpClient* client);
+
+ // class methods
+ static NPT_Result Untrack(NPT_HttpClient::Connection* connection);
+
+private:
+ typedef NPT_List<NPT_HttpClient::Connection*> ConnectionList;
+
+ // class members
+ static NPT_HttpConnectionManager* Instance;
+
+ // constructor
+ NPT_HttpConnectionManager();
+
+ // NPT_Thread methods
+ void Run() override;
+
+ // methods
+ NPT_Result UntrackConnection(NPT_HttpClient::Connection* connection);
+ NPT_Result Cleanup();
+
+ // members
+ NPT_Mutex m_Lock;
+ NPT_Cardinal m_MaxConnections;
+ NPT_Cardinal m_MaxConnectionAge;
+ NPT_SharedVariable m_Aborted;
+ NPT_List<Connection*> m_Connections;
+ NPT_Map<NPT_HttpClient*, ConnectionList> m_ClientConnections;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequestContext
++---------------------------------------------------------------------*/
+class NPT_HttpRequestContext
+{
+public:
+ // constructor
+ NPT_HttpRequestContext() {}
+ NPT_HttpRequestContext(const NPT_SocketAddress* local_address,
+ const NPT_SocketAddress* remote_address);
+
+ // methods
+ const NPT_SocketAddress& GetLocalAddress() const { return m_LocalAddress; }
+ const NPT_SocketAddress& GetRemoteAddress() const { return m_RemoteAddress; }
+ void SetLocalAddress(const NPT_SocketAddress& address) {
+ m_LocalAddress = address;
+ }
+ void SetRemoteAddress(const NPT_SocketAddress& address) {
+ m_RemoteAddress = address;
+ }
+
+private:
+ // members
+ NPT_SocketAddress m_LocalAddress;
+ NPT_SocketAddress m_RemoteAddress;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpRequestHandler
++---------------------------------------------------------------------*/
+class NPT_HttpRequestHandler
+{
+public:
+ NPT_IMPLEMENT_DYNAMIC_CAST(NPT_HttpRequestHandler)
+
+ // destructor
+ virtual ~NPT_HttpRequestHandler() {}
+
+ // methods
+ virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) = 0;
+
+ /**
+ * Override this method if you want to write the body yourself.
+ * The default implementation will simply write out the entity's
+ * input stream.
+ */
+ virtual NPT_Result SendResponseBody(const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ NPT_OutputStream& output);
+
+ /**
+ * A notification method called by the server upon completing the
+ * processing of a request.
+ */
+ virtual void Completed(NPT_Result /*result*/) {}
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpStaticRequestHandler
++---------------------------------------------------------------------*/
+class NPT_HttpStaticRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+ // constructors
+ NPT_HttpStaticRequestHandler(const char* document,
+ const char* mime_type = "text/html",
+ bool copy = true);
+ NPT_HttpStaticRequestHandler(const void* data,
+ NPT_Size size,
+ const char* mime_type = "text/html",
+ bool copy = true);
+
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+private:
+ NPT_String m_MimeType;
+ NPT_DataBuffer m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry
++---------------------------------------------------------------------*/
+typedef struct NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry {
+ const char* extension;
+ const char* mime_type;
+} NPT_HttpFileRequestHandler_FileTypeMapEntry;
+
+/*----------------------------------------------------------------------
+| NPT_HttpFileRequestHandler
++---------------------------------------------------------------------*/
+class NPT_HttpFileRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+ // constructors
+ NPT_HttpFileRequestHandler(const char* url_root,
+ const char* file_root,
+ bool auto_dir = false,
+ const char* auto_index = NULL);
+
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // class methods
+ static const char* GetDefaultContentType(const char* extension);
+
+ // accessors
+ NPT_Map<NPT_String,NPT_String>& GetFileTypeMap() { return m_FileTypeMap; }
+ void SetDefaultMimeType(const char* mime_type) {
+ m_DefaultMimeType = mime_type;
+ }
+ void SetUseDefaultFileTypeMap(bool use_default) {
+ m_UseDefaultFileTypeMap = use_default;
+ }
+
+ static NPT_Result SetupResponseBody(NPT_HttpResponse& response,
+ NPT_InputStreamReference& stream,
+ const NPT_String* range_spec = NULL);
+
+protected:
+ // methods
+ const char* GetContentType(const NPT_String& filename);
+
+private:
+ NPT_String m_UrlRoot;
+ NPT_String m_FileRoot;
+ NPT_Map<NPT_String, NPT_String> m_FileTypeMap;
+ NPT_String m_DefaultMimeType;
+ bool m_UseDefaultFileTypeMap;
+ bool m_AutoDir;
+ NPT_String m_AutoIndex;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpServer
++---------------------------------------------------------------------*/
+class NPT_HttpServer {
+public:
+ // types
+ struct Config {
+ NPT_Timeout m_ConnectionTimeout;
+ NPT_Timeout m_IoTimeout;
+ NPT_IpAddress m_ListenAddress;
+ NPT_UInt16 m_ListenPort;
+ bool m_ReuseAddress;
+ };
+
+ // constructors and destructor
+ NPT_HttpServer(NPT_UInt16 listen_port = NPT_HTTP_DEFAULT_PORT, bool cancellable = false);
+ NPT_HttpServer(NPT_IpAddress listen_address,
+ NPT_UInt16 listen_port = NPT_HTTP_DEFAULT_PORT,
+ bool cancellable = false);
+ virtual ~NPT_HttpServer();
+
+ // methods
+ NPT_Result SetConfig(const Config& config);
+ const Config& GetConfig() const { return m_Config; }
+ NPT_Result SetListenPort(NPT_UInt16 port, bool reuse_address = true);
+ NPT_Result SetTimeouts(NPT_Timeout connection_timeout, NPT_Timeout io_timeout);
+ NPT_Result SetServerHeader(const char* server_header);
+ NPT_Result Abort();
+ NPT_Result WaitForNewClient(NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output,
+ NPT_HttpRequestContext* context,
+ NPT_Flags socket_flags = 0);
+ NPT_Result Loop(bool cancellable_sockets=true);
+ NPT_UInt16 GetPort() { return m_BoundPort; }
+ void Terminate();
+
+ /**
+ * Add a request handler. By default the ownership of the handler is NOT transfered to this object,
+ * so the caller is responsible for the lifetime management of the handler object.
+ */
+ virtual NPT_Result AddRequestHandler(NPT_HttpRequestHandler* handler,
+ const char* path,
+ bool include_children = false,
+ bool transfer_ownership = false);
+ virtual NPT_HttpRequestHandler* FindRequestHandler(NPT_HttpRequest& request);
+ virtual NPT_List<NPT_HttpRequestHandler*> FindRequestHandlers(NPT_HttpRequest& request);
+
+ /**
+ * Parse the request from a new client, form a response, and send it back.
+ */
+ virtual NPT_Result RespondToClient(NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output,
+ const NPT_HttpRequestContext& context);
+
+protected:
+ // types
+ struct HandlerConfig {
+ HandlerConfig(NPT_HttpRequestHandler* handler,
+ const char* path,
+ bool include_children,
+ bool transfer_ownership = false);
+ ~HandlerConfig();
+
+ // methods
+ bool WillHandle(NPT_HttpRequest& request);
+
+ // members
+ NPT_HttpRequestHandler* m_Handler;
+ NPT_String m_Path;
+ bool m_IncludeChildren;
+ bool m_HandlerIsOwned;
+ };
+
+ // methods
+ NPT_Result Bind();
+
+ // members
+ NPT_TcpServerSocket m_Socket;
+ NPT_UInt16 m_BoundPort;
+ Config m_Config;
+ NPT_List<HandlerConfig*> m_RequestHandlers;
+ NPT_String m_ServerHeader;
+ bool m_Run;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpResponder
++---------------------------------------------------------------------*/
+class NPT_HttpResponder {
+public:
+ // types
+ struct Config {
+ NPT_Timeout m_IoTimeout;
+ };
+
+ // constructors and destructor
+ NPT_HttpResponder(NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output);
+ virtual ~NPT_HttpResponder();
+
+ // methods
+ NPT_Result SetConfig(const Config& config);
+ NPT_Result SetTimeout(NPT_Timeout io_timeout);
+ NPT_Result ParseRequest(NPT_HttpRequest*& request,
+ const NPT_SocketAddress* local_address = NULL);
+ NPT_Result SendResponseHeaders(NPT_HttpResponse& response);
+
+protected:
+ // members
+ Config m_Config;
+ NPT_BufferedInputStreamReference m_Input;
+ NPT_OutputStreamReference m_Output;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedInputStream
++---------------------------------------------------------------------*/
+class NPT_HttpChunkedInputStream : public NPT_InputStream
+{
+public:
+ // constructors and destructor
+ NPT_HttpChunkedInputStream(NPT_BufferedInputStreamReference& stream);
+ ~NPT_HttpChunkedInputStream() override;
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result Seek(NPT_Position offset) override;
+ NPT_Result Tell(NPT_Position& offset) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override;
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+protected:
+ // members
+ NPT_BufferedInputStreamReference m_Source;
+ NPT_UInt32 m_CurrentChunkSize;
+ bool m_Eos;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpChunkedOutputStream
++---------------------------------------------------------------------*/
+class NPT_HttpChunkedOutputStream : public NPT_OutputStream
+{
+public:
+ // constructors and destructor
+ NPT_HttpChunkedOutputStream(NPT_OutputStream& stream);
+ ~NPT_HttpChunkedOutputStream() override;
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written = NULL) override;
+ NPT_Result Seek(NPT_Position /*offset*/) override { return NPT_ERROR_NOT_SUPPORTED;}
+ NPT_Result Tell(NPT_Position& offset) override { return m_Stream.Tell(offset); }
+ NPT_Result Flush() override { return m_Stream.Flush(); }
+
+protected:
+ // members
+ NPT_OutputStream& m_Stream;
+};
+
+#endif // _NPT_HTTP_H_
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptInterfaces.h b/lib/libUPnP/Neptune/Source/Core/NptInterfaces.h
new file mode 100644
index 0000000..b0bb264
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptInterfaces.h
@@ -0,0 +1,115 @@
+/*****************************************************************
+|
+| Neptune - Interfaces
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_INTERFACES_H_
+#define _NPT_INTERFACES_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptCommon.h"
+#include "NptResults.h"
+#include "NptConfig.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_NO_SUCH_INTERFACE = NPT_ERROR_BASE_INTERFACES - 0;
+
+/*----------------------------------------------------------------------
+| NPT_InterfaceId
++---------------------------------------------------------------------*/
+class NPT_InterfaceId
+{
+ public:
+ // methods
+ bool operator==(const NPT_InterfaceId& id) const {
+ return ((id.m_Id == m_Id) && (id.m_Version == m_Version));
+ }
+
+ // members
+ unsigned long m_Id;
+ unsigned long m_Version;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Polymorphic
++---------------------------------------------------------------------*/
+class NPT_Polymorphic
+{
+public:
+ // destructor
+ virtual ~NPT_Polymorphic() {}
+
+ // methods
+ virtual NPT_Result GetInterface(const NPT_InterfaceId& id,
+ NPT_Interface*& iface) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Interruptible
++---------------------------------------------------------------------*/
+class NPT_Interruptible
+{
+public:
+ // destructor
+ virtual ~NPT_Interruptible() {}
+
+ // methods
+ virtual NPT_Result Interrupt() = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Configurable
++---------------------------------------------------------------------*/
+class NPT_Configurable
+{
+public:
+ // destructor
+ virtual ~NPT_Configurable() {}
+
+ // methods
+ virtual NPT_Result SetProperty(const char* /*name*/,
+ const char* /*value*/) {
+ return NPT_ERROR_NO_SUCH_PROPERTY;
+ }
+ virtual NPT_Result SetProperty(const char* /*name*/,
+ int /*value*/) {
+ return NPT_ERROR_NO_SUCH_PROPERTY;
+ }
+ virtual NPT_Result GetProperty(const char* /*name*/,
+ NPT_PropertyValue& /*value*/) {
+ return NPT_ERROR_NO_SUCH_PROPERTY;
+ }
+};
+
+#endif // _NPT_INTERFACES_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptJson.cpp b/lib/libUPnP/Neptune/Source/Core/NptJson.cpp
new file mode 100644
index 0000000..300e210
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptJson.cpp
@@ -0,0 +1,37 @@
+/*****************************************************************
+|
+| Neptune - JSON
+|
+| Copyright (c) 2002-2012, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptJson.h"
+#include "NptUtils.h"
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptJson.h b/lib/libUPnP/Neptune/Source/Core/NptJson.h
new file mode 100644
index 0000000..699feef
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptJson.h
@@ -0,0 +1,42 @@
+/*****************************************************************
+|
+| Neptune - JSON
+|
+| Copyright (c) 2002-2012, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_JSON_H_
+#define _NPT_JSON_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptStrings.h"
+
+
+#endif // _NPT_JSON_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptList.cpp b/lib/libUPnP/Neptune/Source/Core/NptList.cpp
new file mode 100644
index 0000000..8879756
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptList.cpp
@@ -0,0 +1,34 @@
+/*****************************************************************
+|
+| Neptune - Lists
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
diff --git a/lib/libUPnP/Neptune/Source/Core/NptList.h b/lib/libUPnP/Neptune/Source/Core/NptList.h
new file mode 100644
index 0000000..37d1802
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptList.h
@@ -0,0 +1,704 @@
+/*****************************************************************
+|
+| Neptune - Lists
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_LIST_H_
+#define _NPT_LIST_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptResults.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptCommon.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_LIST_EMPTY = NPT_ERROR_BASE_LIST - 0;
+const int NPT_ERROR_LIST_OPERATION_ABORTED = NPT_ERROR_BASE_LIST - 1;
+const int NPT_ERROR_LIST_OPERATION_CONTINUE = NPT_ERROR_BASE_LIST - 2;
+
+/*----------------------------------------------------------------------
+| NPT_List
++---------------------------------------------------------------------*/
+template <typename T>
+class NPT_List
+{
+protected:
+ class Item;
+
+public:
+ // types
+ typedef T Element;
+
+ class Iterator {
+ public:
+ Iterator() : m_Item(NULL) {}
+ explicit Iterator(Item* item) : m_Item(item) {}
+ Iterator(const Iterator& copy) : m_Item(copy.m_Item) {}
+ T& operator*() const { return m_Item->m_Data; }
+ T* operator->() const { return &m_Item->m_Data;}
+ Iterator& operator++() { // prefix
+ m_Item = m_Item->m_Next;
+ return (*this);
+ }
+ Iterator operator++(int) { // postfix
+ Iterator saved_this = *this;
+ m_Item = m_Item->m_Next;
+ return saved_this;
+ }
+ Iterator& operator--() { // prefix
+ m_Item = m_Item->m_Prev;
+ return (*this);
+ }
+ Iterator operator--(int) { // postfix
+ Iterator saved_this = *this;
+ m_Item = m_Item->m_Prev;
+ return saved_this;
+ }
+ operator bool() const {
+ return m_Item != NULL;
+ }
+ bool operator==(const Iterator& other) const {
+ return m_Item == other.m_Item;
+ }
+ bool operator!=(const Iterator& other) const {
+ return m_Item != other.m_Item;
+ }
+ void operator=(const Iterator& other) {
+ m_Item = other.m_Item;
+ }
+ void operator=(Item* item) {
+ m_Item = item;
+ }
+
+ private:
+ Item* m_Item;
+
+ // friends
+ friend class NPT_List<T>;
+ };
+
+ // methods
+ NPT_List<T>();
+ NPT_List<T>(const NPT_List<T>& list);
+ ~NPT_List<T>();
+ NPT_Result Add(const T& data);
+ NPT_Result Insert(const Iterator where, const T& data);
+ NPT_Result Remove(const T& data, bool all=false);
+ NPT_Result Erase(const Iterator position);
+ NPT_Result PopHead(T& data);
+ bool Contains(const T& data) const;
+ NPT_Result Clear();
+ NPT_Result Get(NPT_Ordinal index, T& data) const;
+ NPT_Result Get(NPT_Ordinal index, T*& data) const;
+ NPT_Cardinal GetItemCount() const { return m_ItemCount; }
+ Iterator GetFirstItem() const { return Iterator(m_Head); }
+ Iterator GetLastItem() const { return Iterator(m_Tail); }
+ Iterator GetItem(NPT_Ordinal index) const;
+
+ // list manipulation
+ NPT_Result Add(NPT_List<T>& list);
+ NPT_Result Remove(const NPT_List<T>& list, bool all=false);
+ NPT_Result Cut(NPT_Cardinal keep, NPT_List<T>& cut);
+
+ // item manipulation
+ NPT_Result Add(Item& item);
+ NPT_Result Detach(Item& item);
+ NPT_Result Insert(const Iterator where, Item& item);
+
+ // list operations
+ // keep these template members defined here because MSV6 does not let
+ // us define them later
+ template <typename X>
+ NPT_Result Apply(const X& function) const
+ {
+ Item* item = m_Head;
+ while (item) {
+ function(item->m_Data);
+ item = item->m_Next;
+ }
+
+ return NPT_SUCCESS;
+ }
+
+ template <typename X, typename P>
+ NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
+ {
+ Item* item = m_Head;
+ while (item) {
+ NPT_Result return_value;
+ if (predicate(function(item->m_Data), return_value)) {
+ if (match) *match = true;
+ return return_value;
+ }
+ item = item->m_Next;
+ }
+
+ if (match) *match = false;
+ return NPT_SUCCESS;
+ }
+
+ template <typename P>
+ Iterator Find(const P& predicate, NPT_Ordinal n=0) const
+ {
+ Item* item = m_Head;
+ while (item) {
+ if (predicate(item->m_Data)) {
+ if (n == 0) {
+ return Iterator(item);
+ }
+ --n;
+ }
+ item = item->m_Next;
+ }
+
+ return Iterator(NULL);
+ }
+
+ // Merge sort algorithm
+ // http://en.wikipedia.org/wiki/Mergesort
+ template <typename X>
+ NPT_Result Sort(const X& function)
+ {
+ if (GetItemCount() <= 1) return NPT_SUCCESS;
+
+ NPT_List<T> right;
+ NPT_CHECK(Cut(GetItemCount() >> 1, right));
+
+ // sort the left side
+ Sort(function);
+
+ // sort the right side
+ right.Sort(function);
+
+ // merge the two back inline
+ if (function(m_Tail->m_Data, right.m_Head->m_Data) > 0) {
+ Merge(right, function);
+ } else {
+ // append right
+ right.m_Head->m_Prev = m_Tail;
+ m_Tail->m_Next = right.m_Head;
+ m_Tail = right.m_Tail;
+ m_ItemCount += right.m_ItemCount;
+
+ right.m_ItemCount = 0;
+ right.m_Head = right.m_Tail = NULL;
+ }
+
+ return NPT_SUCCESS;
+ }
+
+ template <typename X>
+ NPT_Result Merge(NPT_List<T>& other, const X& function)
+ {
+ Iterator left = GetFirstItem();
+ Iterator right;
+ while (left && other.m_Head) {
+ if (function(*left, other.m_Head->m_Data) <= 0) {
+ ++left;
+ } else {
+ // remove head and insert it
+ Item* head = other.m_Head;
+ other.Detach(*head);
+ Insert(left, *head);
+ }
+ }
+
+ // add what's left of other if any
+ if (other.m_Head) {
+ other.m_Head->m_Prev = m_Tail;
+ if (m_Tail) m_Tail->m_Next = other.m_Head;
+ m_Tail = other.m_Tail;
+ if (!m_Head) m_Head = other.m_Head;
+ other.m_Head = other.m_Tail = NULL;
+ }
+ m_ItemCount += other.m_ItemCount;
+ other.m_ItemCount = 0;
+ return NPT_SUCCESS;
+ }
+
+ // operators
+ void operator=(const NPT_List<T>& other);
+ bool operator==(const NPT_List<T>& other) const;
+ bool operator!=(const NPT_List<T>& other) const;
+
+protected:
+ // types
+ class Item
+ {
+ public:
+ // methods
+ Item(const T& data) : m_Next(0), m_Prev(0), m_Data(data) {}
+
+ // members
+ Item* m_Next;
+ Item* m_Prev;
+ T m_Data;
+
+ // friends
+ //friend class NPT_List<T>;
+ //friend class NPT_List<T>::Iterator;
+ };
+
+ // members
+ NPT_Cardinal m_ItemCount;
+ Item* m_Head;
+ Item* m_Tail;
+};
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::NPT_List
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_List<T>::NPT_List() : m_ItemCount(0), m_Head(0), m_Tail(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::NPT_List
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_List<T>::NPT_List(const NPT_List<T>& list) : m_ItemCount(0), m_Head(0), m_Tail(0)
+{
+ *this = list;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::~NPT_List<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_List<T>::~NPT_List()
+{
+ Clear();
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::operator=
++---------------------------------------------------------------------*/
+template <typename T>
+void
+NPT_List<T>::operator=(const NPT_List<T>& list)
+{
+ // cleanup
+ Clear();
+
+ // copy the new list
+ Item* item = list.m_Head;
+ while (item) {
+ Add(item->m_Data);
+ item = item->m_Next;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::operator==
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_List<T>::operator==(const NPT_List<T>& other) const
+{
+ // quick test
+ if (m_ItemCount != other.m_ItemCount) return false;
+
+ // compare all elements one by one
+ Item* our_item = m_Head;
+ Item* their_item = other.m_Head;
+ while (our_item && their_item) {
+ if (our_item->m_Data != their_item->m_Data) return false;
+ our_item = our_item->m_Next;
+ their_item = their_item->m_Next;
+ }
+
+ return our_item == NULL && their_item == NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::operator!=
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+bool
+NPT_List<T>::operator!=(const NPT_List<T>& other) const
+{
+ return !(*this == other);
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Clear
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Clear()
+{
+ // delete all items
+ Item* item = m_Head;
+ while (item) {
+ Item* next = item->m_Next;
+ delete item;
+ item = next;
+ }
+
+ m_ItemCount = 0;
+ m_Head = NULL;
+ m_Tail = NULL;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Add(Item& item)
+{
+ // add element at the tail
+ if (m_Tail) {
+ item.m_Prev = m_Tail;
+ item.m_Next = NULL;
+ m_Tail->m_Next = &item;
+ m_Tail = &item;
+ } else {
+ m_Head = &item;
+ m_Tail = &item;
+ item.m_Next = NULL;
+ item.m_Prev = NULL;
+ }
+
+ // one more item in the list now
+ ++m_ItemCount;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Add(NPT_List<T>& list)
+{
+ // copy the new list
+ Item* item = list.m_Head;
+ while (item) {
+ Add(item->m_Data);
+ item = item->m_Next;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_List<T>::Add(const T& data)
+{
+ return Add(*new Item(data));
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::GetItem
++---------------------------------------------------------------------*/
+template <typename T>
+typename NPT_List<T>::Iterator
+NPT_List<T>::GetItem(NPT_Ordinal n) const
+{
+ Iterator result;
+ if (n >= m_ItemCount) return result;
+
+ result = m_Head;
+ for (unsigned int i=0; i<n; i++) {
+ ++result;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_List<T>::Insert(Iterator where, const T&data)
+{
+ return Insert(where, *new Item(data));
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Insert(Iterator where, Item& item)
+{
+ // insert the item in the list
+ Item* position = where.m_Item;
+ if (position) {
+ // insert at position
+ item.m_Next = position;
+ item.m_Prev = position->m_Prev;
+ position->m_Prev = &item;
+ if (item.m_Prev) {
+ item.m_Prev->m_Next = &item;
+ } else {
+ // this is the new head
+ m_Head = &item;
+ }
+
+ // one more item in the list now
+ ++m_ItemCount;
+ } else {
+ // insert at tail
+ return Add(item);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Erase
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Erase(Iterator position)
+{
+ if (!position) return NPT_ERROR_NO_SUCH_ITEM;
+ Detach(*position.m_Item);
+ delete position.m_Item;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Remove
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Remove(const T& data, bool all)
+{
+ Item* item = m_Head;
+ NPT_Cardinal matches = 0;
+
+ while (item) {
+ Item* next = item->m_Next;
+ if (item->m_Data == data) {
+ // we found a match
+ ++matches;
+
+ // detach item
+ Detach(*item);
+
+ // destroy the item
+ delete item;
+
+ if (!all) return NPT_SUCCESS;
+ }
+ item = next;
+ }
+
+ return matches?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Remove
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Remove(const NPT_List<T>& list, bool all)
+{
+ Item* item = list.m_Head;
+ while (item) {
+ Remove(item->m_Data, all);
+ item = item->m_Next;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Detach
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Detach(Item& item)
+{
+ // remove item
+ if (item.m_Prev) {
+ // item is not the head
+ if (item.m_Next) {
+ // item is not the tail
+ item.m_Next->m_Prev = item.m_Prev;
+ item.m_Prev->m_Next = item.m_Next;
+ } else {
+ // item is the tail
+ m_Tail = item.m_Prev;
+ m_Tail->m_Next = NULL;
+ }
+ } else {
+ // item is the head
+ m_Head = item.m_Next;
+ if (m_Head) {
+ // item is not the tail
+ m_Head->m_Prev = NULL;
+ } else {
+ // item is also the tail
+ m_Tail = NULL;
+ }
+ }
+
+ // one less item in the list now
+ --m_ItemCount;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Get
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Get(NPT_Ordinal index, T& data) const
+{
+ T* data_pointer;
+ NPT_CHECK(Get(index, data_pointer));
+ data = *data_pointer;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Get
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Get(NPT_Ordinal index, T*& data) const
+{
+ Item* item = m_Head;
+
+ if (index < m_ItemCount) {
+ while (index--) item = item->m_Next;
+ data = &item->m_Data;
+ return NPT_SUCCESS;
+ } else {
+ data = NULL;
+ return NPT_ERROR_NO_SUCH_ITEM;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::PopHead
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::PopHead(T& data)
+{
+ // check that we have an element
+ if (m_Head == NULL) return NPT_ERROR_LIST_EMPTY;
+
+ // copy the head item's data
+ data = m_Head->m_Data;
+
+ // discard the head item
+ Item* head = m_Head;
+ m_Head = m_Head->m_Next;
+ if (m_Head) {
+ m_Head->m_Prev = NULL;
+ } else {
+ m_Tail = NULL;
+ }
+ delete head;
+
+ // update the count
+ --m_ItemCount;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Contains
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_List<T>::Contains(const T& data) const
+{
+ Item* item = m_Head;
+ while (item) {
+ if (item->m_Data == data) return true;
+ item = item->m_Next;
+ }
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_List<T>::Cut
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Cut(NPT_Cardinal keep, NPT_List<T>& cut)
+{
+ cut.Clear();
+
+ // shortcut
+ if (keep >= GetItemCount()) return NPT_SUCCESS;
+
+ // update new counts first
+ cut.m_ItemCount = m_ItemCount-keep;
+ m_ItemCount = keep;
+
+ // look for the cut-point item
+ Item* item = m_Head;
+ while (keep--) { item = item->m_Next;}
+
+ // the cut list goes from the cut-point item to the tail
+ cut.m_Head = item;
+ cut.m_Tail = m_Tail;
+
+ // update the portion of the list we keep
+ if (item == m_Head) m_Head = NULL;
+ m_Tail = item->m_Prev;
+
+ // update the cut list
+ if (item->m_Prev) item->m_Prev->m_Next = NULL;
+ item->m_Prev = NULL;
+
+ return NPT_SUCCESS;
+}
+
+#endif // _NPT_LIST_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptLogging.cpp b/lib/libUPnP/Neptune/Source/Core/NptLogging.cpp
new file mode 100644
index 0000000..51d20e7
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptLogging.cpp
@@ -0,0 +1,1555 @@
+/*****************************************************************
+|
+| Neptune - Logging Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+/** @file
+* Implementation file for logging
+*/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <stdarg.h>
+
+#include "NptLogging.h"
+#include "NptList.h"
+#include "NptStreams.h"
+#include "NptSockets.h"
+#include "NptUtils.h"
+#include "NptFile.h"
+#include "NptSystem.h"
+#include "NptConsole.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+//NPT_SET_LOCAL_LOGGER("neptune.logging")
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+class NPT_LogConsoleHandler : public NPT_LogHandler {
+public:
+ // enums
+ enum {
+ OUTPUT_TO_CONSOLE = 1,
+ OUTPUT_TO_DEBUG = 2
+ };
+
+ // class methods
+ static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+ // methods
+ void Log(const NPT_LogRecord& record) override;
+
+private:
+ // members
+ NPT_UInt32 m_Outputs;
+ bool m_UseColors;
+ NPT_Flags m_FormatFilter;
+};
+
+class NPT_LogFileHandler : public NPT_LogHandler {
+public:
+ // class methods
+ static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+ // methods
+ void Log(const NPT_LogRecord& record) override;
+
+private:
+ NPT_Result Open(bool append = true);
+
+private:
+ // members
+ bool m_Flush;
+ bool m_Append;
+ NPT_String m_Filename;
+ NPT_Flags m_FormatFilter;
+ NPT_LargeSize m_MaxFilesize;
+ NPT_OutputStreamReference m_Stream;
+};
+
+class NPT_LogTcpHandler : public NPT_LogHandler {
+public:
+ // class methods
+ static void FormatRecord(const NPT_LogRecord& record, NPT_String& msg);
+ static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+ // methods
+ void Log(const NPT_LogRecord& record) override;
+
+private:
+ // constructor
+ NPT_LogTcpHandler() : m_Port(0) {}
+
+ // methods
+ NPT_Result Connect();
+
+ // members
+ NPT_String m_Host;
+ NPT_UInt16 m_Port;
+ NPT_OutputStreamReference m_Stream;
+};
+
+class NPT_LogUdpHandler : public NPT_LogHandler {
+public:
+ // class methods
+ static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+ // methods
+ void Log(const NPT_LogRecord& record) override;
+
+private:
+ // members
+ NPT_UdpSocket m_Socket;
+ NPT_SocketAddress m_Target;
+};
+
+class NPT_LogNullHandler : public NPT_LogHandler {
+public:
+ // class methods
+ static NPT_Result Create(NPT_LogHandler*& handler);
+
+ // methods
+ void Log(const NPT_LogRecord& record) override;
+};
+
+class NPT_LogCustomHandler : public NPT_LogHandler {
+public:
+ // class methods
+ static NPT_Result SetCustomHandlerFunction(CustomHandlerExternalFunction function);
+ static NPT_Result Create(NPT_LogHandler*& handler);
+
+ // methods
+ void Log(const NPT_LogRecord& record) override;
+
+private:
+ static CustomHandlerExternalFunction s_ExternalFunction;
+};
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_LOG_HEAP_BUFFER_INCREMENT 4096
+#define NPT_LOG_STACK_BUFFER_MAX_SIZE 512
+#define NPT_LOG_HEAP_BUFFER_MAX_SIZE 65536
+
+#if !defined(NPT_CONFIG_LOG_CONFIG_ENV)
+#define NPT_CONFIG_LOG_CONFIG_ENV "NEPTUNE_LOG_CONFIG"
+#endif
+
+#if !defined(NPT_CONFIG_DEFAULT_LOG_CONFIG_SOURCE)
+#define NPT_CONFIG_DEFAULT_LOG_CONFIG_SOURCE "file:neptune-logging.properties"
+#endif
+
+#if !defined(NPT_CONFIG_DEFAULT_LOG_LEVEL)
+#define NPT_CONFIG_DEFAULT_LOG_LEVEL NPT_LOG_LEVEL_OFF
+#endif
+#define NPT_LOG_ROOT_DEFAULT_HANDLER "ConsoleHandler"
+#if !defined(NPT_CONFIG_DEFAULT_FILE_HANDLER_FILENAME)
+#define NPT_CONFIG_DEFAULT_LOG_FILE_HANDLER_FILENAME "_neptune.log"
+#endif
+
+#define NPT_LOG_TCP_HANDLER_DEFAULT_PORT 7723
+#define NPT_LOG_TCP_HANDLER_DEFAULT_CONNECT_TIMEOUT 5000 /* 5 seconds */
+
+#define NPT_LOG_UDP_HANDLER_DEFAULT_PORT 7724
+
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__APPLE__)
+#define NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE false
+#else
+#define NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE true
+#endif
+
+#ifndef NPT_CONFIG_DEFAULT_LOG_CONSOLE_HANDLER_OUTPUTS
+#define NPT_CONFIG_DEFAULT_LOG_CONSOLE_HANDLER_OUTPUTS OUTPUT_TO_DEBUG
+#endif
+
+#define NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE 1000000
+
+#define NPT_LOG_FORMAT_FILTER_NO_SOURCE 1
+#define NPT_LOG_FORMAT_FILTER_NO_TIMESTAMP 2
+#define NPT_LOG_FORMAT_FILTER_NO_FUNCTION_NAME 4
+#define NPT_LOG_FORMAT_FILTER_NO_LOGGER_NAME 8
+#define NPT_LOG_FORMAT_FILTER_NO_SOURCEPATH 16
+#define NPT_LOG_FORMAT_FILTER_NO_THREAD_ID 32
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+static NPT_LogManager LogManager;
+
+/*----------------------------------------------------------------------
+| NPT_LogManagerAutoDisabler
++---------------------------------------------------------------------*/
+class NPT_LogManagerAutoDisabler
+{
+public:
+ NPT_LogManagerAutoDisabler() : m_WasEnabled(LogManager.IsEnabled()) {
+ LogManager.SetEnabled(false);
+ }
+ ~NPT_LogManagerAutoDisabler() {
+ LogManager.SetEnabled(m_WasEnabled);
+ }
+private:
+ bool m_WasEnabled;
+};
+
+/*----------------------------------------------------------------------
+| NPT_LogManagerAutoLocker
++---------------------------------------------------------------------*/
+class NPT_LogManagerAutoLocker
+{
+ public:
+ // methods
+ NPT_LogManagerAutoLocker(NPT_LogManager &manager) : m_Manager(manager) {
+ m_Manager.Lock();
+ }
+ ~NPT_LogManagerAutoLocker() {
+ m_Manager.Unlock();
+ }
+
+ private:
+ // members
+ NPT_LogManager& m_Manager;
+};
+
+/*----------------------------------------------------------------------
+| NPT_GetSystemLogConfig
++---------------------------------------------------------------------*/
+#if !defined(NPT_CONFIG_HAVE_SYSTEM_LOG_CONFIG)
+NPT_Result NPT_GetSystemLogConfig(NPT_String& /*config*/)
+{
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+/*----------------------------------------------------------------------
+| NPT_LogHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogHandler::Create(const char* logger_name,
+ const char* handler_name,
+ NPT_LogHandler*& handler)
+{
+ handler = NULL;
+
+ if (NPT_StringsEqual(handler_name, "NullHandler")) {
+ return NPT_LogNullHandler::Create(handler);
+ } else if (NPT_StringsEqual(handler_name, "FileHandler")) {
+ return NPT_LogFileHandler::Create(logger_name, handler);
+ } else if (NPT_StringsEqual(handler_name, "ConsoleHandler")) {
+ return NPT_LogConsoleHandler::Create(logger_name, handler);
+ } else if (NPT_StringsEqual(handler_name, "TcpHandler")) {
+ return NPT_LogTcpHandler::Create(logger_name, handler);
+ } else if (NPT_StringsEqual(handler_name, "UdpHandler")) {
+ return NPT_LogUdpHandler::Create(logger_name, handler);
+ } else if (NPT_StringsEqual(handler_name, "CustomHandler")) {
+ return NPT_LogCustomHandler::Create(handler);
+ }
+
+ return NPT_ERROR_NO_SUCH_CLASS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogHandler::SetCustomHandlerFunction
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogHandler::SetCustomHandlerFunction(CustomHandlerExternalFunction function)
+{
+ return NPT_LogCustomHandler::SetCustomHandlerFunction(function);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Log::GetLogLevel
++---------------------------------------------------------------------*/
+int
+NPT_Log::GetLogLevel(const char* name)
+{
+ if ( NPT_StringsEqual(name, "FATAL")) {
+ return NPT_LOG_LEVEL_FATAL;
+ } else if (NPT_StringsEqual(name, "SEVERE")) {
+ return NPT_LOG_LEVEL_SEVERE;
+ } else if (NPT_StringsEqual(name, "WARNING")) {
+ return NPT_LOG_LEVEL_WARNING;
+ } else if (NPT_StringsEqual(name, "INFO")) {
+ return NPT_LOG_LEVEL_INFO;
+ } else if (NPT_StringsEqual(name, "FINE")) {
+ return NPT_LOG_LEVEL_FINE;
+ } else if (NPT_StringsEqual(name, "FINER")) {
+ return NPT_LOG_LEVEL_FINER;
+ } else if (NPT_StringsEqual(name, "FINEST")) {
+ return NPT_LOG_LEVEL_FINEST;
+ } else if (NPT_StringsEqual(name, "ALL")) {
+ return NPT_LOG_LEVEL_ALL;
+ } else if (NPT_StringsEqual(name, "OFF")) {
+ return NPT_LOG_LEVEL_OFF;
+ } else {
+ return -1;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Log::GetLogLevelName
++---------------------------------------------------------------------*/
+const char*
+NPT_Log::GetLogLevelName(int level)
+{
+ switch (level) {
+ case NPT_LOG_LEVEL_FATAL: return "FATAL";
+ case NPT_LOG_LEVEL_SEVERE: return "SEVERE";
+ case NPT_LOG_LEVEL_WARNING: return "WARNING";
+ case NPT_LOG_LEVEL_INFO: return "INFO";
+ case NPT_LOG_LEVEL_FINE: return "FINE";
+ case NPT_LOG_LEVEL_FINER: return "FINER";
+ case NPT_LOG_LEVEL_FINEST: return "FINEST";
+ case NPT_LOG_LEVEL_OFF: return "OFF";
+ default: return "";
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Log::GetLogLevelAnsiColor
++---------------------------------------------------------------------*/
+const char*
+NPT_Log::GetLogLevelAnsiColor(int level)
+{
+ switch (level) {
+ case NPT_LOG_LEVEL_FATAL: return "31";
+ case NPT_LOG_LEVEL_SEVERE: return "31";
+ case NPT_LOG_LEVEL_WARNING: return "33";
+ case NPT_LOG_LEVEL_INFO: return "32";
+ case NPT_LOG_LEVEL_FINE: return "34";
+ case NPT_LOG_LEVEL_FINER: return "35";
+ case NPT_LOG_LEVEL_FINEST: return "36";
+ default: return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Log::FormatRecordToStream
++---------------------------------------------------------------------*/
+void
+NPT_Log::FormatRecordToStream(const NPT_LogRecord& record,
+ NPT_OutputStream& stream,
+ bool use_colors,
+ NPT_Flags format_filter)
+{
+ const char* level_name = GetLogLevelName(record.m_Level);
+ NPT_String level_string;
+
+ /* format and emit the record */
+ if (level_name[0] == '\0') {
+ level_string = NPT_String::FromInteger(record.m_Level);
+ level_name = level_string;
+ }
+ if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_SOURCE) == 0) {
+ unsigned int start = 0;
+ /* remove source file path if requested */
+ if (format_filter & NPT_LOG_FORMAT_FILTER_NO_SOURCEPATH) {
+ for (start = NPT_StringLength(record.m_SourceFile);
+ start;
+ --start) {
+ if (record.m_SourceFile[start-1] == '\\' ||
+ record.m_SourceFile[start-1] == '/') {
+ break;
+ }
+ }
+ }
+ stream.WriteString(record.m_SourceFile + start);
+ stream.Write("(", 1, NULL);
+ stream.WriteString(NPT_String::FromIntegerU(record.m_SourceLine));
+ stream.Write("): ", 3, NULL);
+ }
+ if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_LOGGER_NAME) == 0) {
+ stream.Write("[", 1, NULL);
+ stream.WriteString(record.m_LoggerName);
+ stream.Write("] ", 2, NULL);
+ }
+ if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_TIMESTAMP) == 0) {
+ NPT_String ts = NPT_DateTime(record.m_TimeStamp, true).ToString(NPT_DateTime::FORMAT_W3C,
+ NPT_DateTime::FLAG_EMIT_FRACTION |
+ NPT_DateTime::FLAG_EXTENDED_PRECISION);
+ stream.WriteString(ts.GetChars());
+ stream.Write(" ", 1);
+ }
+ if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_FUNCTION_NAME) == 0) {
+ stream.WriteFully("[",1);
+ if (record.m_SourceFunction) {
+ stream.WriteString(record.m_SourceFunction);
+ }
+ stream.WriteFully("] ",2);
+ }
+ if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_THREAD_ID) == 0) {
+ stream.Write("(", 1, NULL);
+ stream.WriteString(NPT_String::FromIntegerU(record.m_ThreadId));
+ stream.Write(") ", 2, NULL);
+ }
+ const char* ansi_color = NULL;
+ if (use_colors) {
+ ansi_color = GetLogLevelAnsiColor(record.m_Level);
+ if (ansi_color) {
+ stream.Write("\033[", 2, NULL);
+ stream.WriteString(ansi_color);
+ stream.Write(";1m", 3, NULL);
+ }
+ }
+ stream.WriteString(level_name);
+ if (use_colors && ansi_color) {
+ stream.Write("\033[0m", 4, NULL);
+ }
+ stream.Write(": ", 2, NULL);
+ stream.WriteString(record.m_Message);
+ stream.Write("\r\n", 2, NULL);
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::NPT_LogManager
++---------------------------------------------------------------------*/
+NPT_LogManager::NPT_LogManager() :
+ m_LockOwner(0),
+ m_LockRecursion(0),
+ m_Enabled(true),
+ m_Configured(false),
+ m_Root(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::~NPT_LogManager
++---------------------------------------------------------------------*/
+NPT_LogManager::~NPT_LogManager()
+{
+ /* destroy everything we've created */
+ for (NPT_List<NPT_Logger*>::Iterator i = m_Loggers.GetFirstItem();
+ i;
+ ++i) {
+ NPT_Logger* logger = *i;
+ delete logger;
+ }
+
+ /* destroy the root logger */
+ delete m_Root;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::GetDefault
++---------------------------------------------------------------------*/
+NPT_LogManager&
+NPT_LogManager::GetDefault()
+{
+ return LogManager;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::Lock
++---------------------------------------------------------------------*/
+void
+NPT_LogManager::Lock()
+{
+ NPT_Thread::ThreadId me = NPT_Thread::GetCurrentThreadId();
+ if (m_LockOwner != me) {
+ m_Lock.Lock();
+ m_LockOwner = me;
+ }
+ ++m_LockRecursion;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::Unlock
++---------------------------------------------------------------------*/
+void
+NPT_LogManager::Unlock()
+{
+ if (--m_LockRecursion == 0) {
+ m_LockOwner = (NPT_Thread::ThreadId)0;
+ m_Lock.Unlock();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::Configure
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::Configure(const char* config_sources)
+{
+ // exit if we're already initialized
+ if (m_Configured) return NPT_SUCCESS;
+
+ // prevent multiple threads from configuring at the same time
+ NPT_LogManagerAutoLocker lock(*this);
+ if (m_Configured) return NPT_SUCCESS;
+
+ // we need to be disabled while we configure ourselves
+ NPT_LogManagerAutoDisabler autodisabler;
+
+ // set some default config values
+ SetConfigValue(".handlers", NPT_LOG_ROOT_DEFAULT_HANDLER);
+
+ // see if the config sources have been set to non-default values
+ if (config_sources == NULL) {
+ config_sources = NPT_CONFIG_DEFAULT_LOG_CONFIG_SOURCE;
+ }
+ NPT_String config_sources_system;
+ if (NPT_SUCCEEDED(NPT_GetSystemLogConfig(config_sources_system))) {
+ config_sources = config_sources_system;
+ }
+ NPT_String config_sources_env;
+ if (NPT_SUCCEEDED(NPT_Environment::Get(NPT_CONFIG_LOG_CONFIG_ENV, config_sources_env))) {
+ config_sources = config_sources_env;
+ }
+
+ /* load all configs */
+ NPT_String config_source;
+ const char* cursor = config_sources;
+ const char* source = config_sources;
+ for (;;) {
+ if (*cursor == '\0' || *cursor == '|') {
+ if (cursor != source) {
+ config_source.Assign(source, (NPT_Size)(cursor-source));
+ config_source.Trim(" \t");
+ ParseConfigSource(config_source);
+ if (*cursor == '|') source = cursor+1;
+ }
+ if (*cursor == '\0') break;
+ }
+ cursor++;
+ }
+
+ /* create the root logger */
+ LogManager.m_Root = new NPT_Logger("", *this);
+ LogManager.m_Root->m_Level = NPT_CONFIG_DEFAULT_LOG_LEVEL;
+ LogManager.m_Root->m_LevelIsInherited = false;
+ ConfigureLogger(LogManager.m_Root);
+
+ // we're initialized now
+ m_Configured = true;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::ConfigValueIsBooleanTrue
++---------------------------------------------------------------------*/
+bool
+NPT_LogManager::ConfigValueIsBooleanTrue(NPT_String& value)
+{
+ return
+ value.Compare("true", true) == 0 ||
+ value.Compare("yes", true) == 0 ||
+ value.Compare("on", true) == 0 ||
+ value.Compare("1", true) == 0;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::ConfigValueIsBooleanFalse
++---------------------------------------------------------------------*/
+bool
+NPT_LogManager::ConfigValueIsBooleanFalse(NPT_String& value)
+{
+ return
+ value.Compare("false", true) == 0 ||
+ value.Compare("no", true) == 0 ||
+ value.Compare("off", true) == 0 ||
+ value.Compare("0", true) == 0;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::GetConfigValue
++---------------------------------------------------------------------*/
+NPT_String*
+NPT_LogManager::GetConfigValue(const char* prefix, const char* suffix)
+{
+ NPT_Size prefix_length = prefix?NPT_StringLength(prefix):0;
+ NPT_Size suffix_length = suffix?NPT_StringLength(suffix):0;
+ NPT_Size key_length = prefix_length+suffix_length;
+ for (NPT_List<NPT_LogConfigEntry>::Iterator i = LogManager.m_Config.GetFirstItem();
+ i;
+ ++i) {
+ NPT_LogConfigEntry& entry = *i;
+ if ((entry.m_Key.GetLength() == key_length) &&
+ (prefix == NULL || entry.m_Key.StartsWith(prefix)) &&
+ (suffix == NULL || entry.m_Key.EndsWith(suffix )) ) {
+ return &entry.m_Value;
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::SetConfigValue
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::SetConfigValue(const char* key, const char* value)
+{
+ NPT_String* value_string = GetConfigValue(key, NULL);
+ if (value_string) {
+ /* the key already exists, replace the value */
+ *value_string = value;
+ } else {
+ /* the value does not already exist, create a new one */
+ NPT_CHECK(LogManager.m_Config.Add(NPT_LogConfigEntry(key, value)));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::ParseConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ParseConfig(const char* config,
+ NPT_Size config_size)
+{
+ const char* cursor = config;
+ const char* line = config;
+ const char* separator = NULL;
+ NPT_String key;
+ NPT_String value;
+
+ /* parse all entries */
+ while (cursor <= config+config_size) {
+ /* separators are newlines, ';' or end of buffer */
+ if ( cursor == config+config_size ||
+ *cursor == '\n' ||
+ *cursor == '\r' ||
+ *cursor == ';') {
+ /* newline or end of buffer */
+ if (separator && line[0] != '#') {
+ /* we have a property */
+ key.Assign(line, (NPT_Size)(separator-line));
+ value.Assign(line+(separator+1-line), (NPT_Size)(cursor-(separator+1)));
+ key.Trim(" \t");
+ value.Trim(" \t");
+
+ SetConfigValue((const char*)key, (const char*)value);
+ }
+ line = cursor+1;
+ separator = NULL;
+ } else if (*cursor == '=' && separator == NULL) {
+ separator = cursor;
+ }
+ cursor++;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::ParseConfigFile
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ParseConfigFile(const char* filename)
+{
+ NPT_Result result;
+
+ /* load the file */
+ NPT_DataBuffer buffer;
+ result = NPT_File::Load(filename, buffer);
+ if (NPT_FAILED(result)) return result;
+
+ /* parse the config */
+ return ParseConfig((const char*)buffer.GetData(), buffer.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::ParseConfigSource
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ParseConfigSource(NPT_String& source)
+{
+ if (source.StartsWith("file:")) {
+ /* file source */
+ ParseConfigFile(source.GetChars()+5);
+ } else if (source.StartsWith("plist:")) {
+ /* property list source */
+ ParseConfig(source.GetChars()+6, source.GetLength()-6);
+ } else if (source.StartsWith("http:port=")) {
+ /* http configurator */
+ unsigned int port = 0;
+ NPT_Result result = NPT_ParseInteger(source.GetChars()+10, port, true);
+ if (NPT_FAILED(result)) return result;
+ new NPT_HttpLoggerConfigurator(port);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::HaveLoggerConfig
++---------------------------------------------------------------------*/
+bool
+NPT_LogManager::HaveLoggerConfig(const char* name)
+{
+ NPT_Size name_length = NPT_StringLength(name);
+ for (NPT_List<NPT_LogConfigEntry>::Iterator i = m_Config.GetFirstItem();
+ i;
+ ++i) {
+ NPT_LogConfigEntry& entry = *i;
+ if (entry.m_Key.StartsWith(name)) {
+ const char* suffix = entry.m_Key.GetChars()+name_length;
+ if (NPT_StringsEqual(suffix, ".level") ||
+ NPT_StringsEqual(suffix, ".handlers") ||
+ NPT_StringsEqual(suffix, ".forward")) {
+ return true;
+ }
+ }
+ }
+
+ /* no config found */
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::ConfigureLogger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ConfigureLogger(NPT_Logger* logger)
+{
+ /* configure the level */
+ NPT_String* level_value = GetConfigValue(logger->m_Name,".level");
+ if (level_value) {
+ NPT_Int32 value;
+ /* try a symbolic name */
+ value = NPT_Log::GetLogLevel(*level_value);
+ if (value < 0) {
+ /* try a numeric value */
+ if (NPT_FAILED(level_value->ToInteger(value, false))) {
+ value = -1;
+ }
+ }
+ if (value >= 0) {
+ logger->m_Level = value;
+ logger->m_LevelIsInherited = false;
+ }
+ }
+
+ /* remove any existing handlers */
+ logger->DeleteHandlers();
+
+ /* configure the handlers */
+ NPT_String* handlers = GetConfigValue(logger->m_Name,".handlers");
+ if (handlers) {
+ const char* handlers_list = handlers->GetChars();
+ const char* cursor = handlers_list;
+ const char* name_start = handlers_list;
+ NPT_String handler_name;
+ NPT_LogHandler* handler;
+ for (;;) {
+ if (*cursor == '\0' || *cursor == ',') {
+ if (cursor != name_start) {
+ handler_name.Assign(name_start, (NPT_Size)(cursor-name_start));
+ handler_name.Trim(" \t");
+
+ /* create a handler */
+ if (NPT_SUCCEEDED(
+ NPT_LogHandler::Create(logger->m_Name, handler_name, handler))) {
+ logger->AddHandler(handler);
+ }
+
+ }
+ if (*cursor == '\0') break;
+ name_start = cursor+1;
+ }
+ ++cursor;
+ }
+ }
+
+ /* configure the forwarding */
+ NPT_String* forward = GetConfigValue(logger->m_Name,".forward");
+ if (forward && !ConfigValueIsBooleanTrue(*forward)) {
+ logger->m_ForwardToParent = false;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::FindLogger
++---------------------------------------------------------------------*/
+NPT_Logger*
+NPT_LogManager::FindLogger(const char* name)
+{
+ for (NPT_List<NPT_Logger*>::Iterator i = LogManager.m_Loggers.GetFirstItem();
+ i;
+ ++i) {
+ NPT_Logger* logger = *i;
+ if (logger->m_Name == name) {
+ return logger;
+ }
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogManager::GetLogger
++---------------------------------------------------------------------*/
+NPT_Logger*
+NPT_LogManager::GetLogger(const char* name)
+{
+ // exit now if the log manager is disabled
+ if (!LogManager.m_Enabled) return NULL;
+
+ /* check that the manager is initialized */
+ if (!LogManager.m_Configured) {
+ /* init the manager */
+ LogManager.Configure();
+ NPT_ASSERT(LogManager.m_Configured);
+ }
+
+ // auto lock until we return from this method
+ NPT_LogManagerAutoLocker lock(LogManager);
+
+ /* check if this logger is already configured */
+ NPT_Logger* logger = LogManager.FindLogger(name);
+ if (logger) return logger;
+
+ /* create a new logger */
+ logger = new NPT_Logger(name, LogManager);
+ if (logger == NULL) return NULL;
+
+ /* configure the logger */
+ LogManager.ConfigureLogger(logger);
+
+ /* find which parent to attach to */
+ NPT_Logger* parent = LogManager.m_Root;
+ NPT_String parent_name = name;
+ for (;;) {
+ NPT_Logger* candidate_parent;
+
+ /* find the last dot */
+ int dot = parent_name.ReverseFind('.');
+ if (dot < 0) break;
+ parent_name.SetLength(dot);
+
+ /* see if the parent exists */
+ candidate_parent = LogManager.FindLogger(parent_name);
+ if (candidate_parent) {
+ parent = candidate_parent;
+ break;
+ }
+
+ /* this parent name does not exist, see if we need to create it */
+ if (LogManager.HaveLoggerConfig(parent_name)) {
+ parent = GetLogger(parent_name);
+ break;
+ }
+ }
+
+ /* attach to the parent */
+ logger->SetParent(parent);
+
+ /* add this logger to the list */
+ LogManager.m_Loggers.Add(logger);
+
+ return logger;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Logger::NPT_Logger
++---------------------------------------------------------------------*/
+NPT_Logger::NPT_Logger(const char* name, NPT_LogManager& manager) :
+ m_Manager(manager),
+ m_Name(name),
+ m_Level(NPT_LOG_LEVEL_OFF),
+ m_LevelIsInherited(true),
+ m_ForwardToParent(true),
+ m_Parent(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_Logger::~NPT_Logger
++---------------------------------------------------------------------*/
+NPT_Logger::~NPT_Logger()
+{
+ /* remove external handlers before cleaning up */
+ m_Handlers.Remove(m_ExternalHandlers, true);
+
+ /* delete all handlers */
+ m_Handlers.Apply(NPT_ObjectDeleter<NPT_LogHandler>());
+}
+
+/*----------------------------------------------------------------------
+| NPT_Logger::DeleteHandlers
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Logger::DeleteHandlers()
+{
+ /* remove external handlers before cleaning up */
+ m_Handlers.Remove(m_ExternalHandlers, true);
+
+ /* delete all handlers and empty the list */
+ if (m_Handlers.GetItemCount()) {
+ m_Handlers.Apply(NPT_ObjectDeleter<NPT_LogHandler>());
+ m_Handlers.Clear();
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Logger::Log
++---------------------------------------------------------------------*/
+void
+NPT_Logger::Log(int level,
+ const char* source_file,
+ unsigned int source_line,
+ const char* source_function,
+ const char* msg,
+ ...)
+{
+ // this is a no-op if the log manager is disabled
+ if (!LogManager.IsEnabled()) return;
+
+ /* check the log level (in case filtering has not already been done) */
+ if (level < m_Level) return;
+
+ /* format the message */
+ char buffer[NPT_LOG_STACK_BUFFER_MAX_SIZE];
+ NPT_Size buffer_size = sizeof(buffer);
+ char* message = buffer;
+ int result;
+ va_list args;
+ for(;;) {
+ /* try to format the message (it might not fit) */
+ va_start(args, msg);
+ result = NPT_FormatStringVN(message, buffer_size-1, msg, args);
+ va_end(args);
+ if (result >= (int)(buffer_size-1)) result = -1;
+ message[buffer_size-1] = 0; /* force a NULL termination */
+ if (result >= 0) break;
+
+ /* the buffer was too small, try something bigger */
+ buffer_size = (buffer_size+NPT_LOG_HEAP_BUFFER_INCREMENT)*2;
+ if (buffer_size > NPT_LOG_HEAP_BUFFER_MAX_SIZE) break;
+ if (message != buffer) delete[] message;
+ message = new char[buffer_size];
+ if (message == NULL) return;
+ }
+
+ /* the message is formatted, publish it to the handlers */
+ NPT_LogRecord record;
+ NPT_Logger* logger = this;
+
+ /* setup the log record */
+ record.m_LoggerName = logger->m_Name,
+ record.m_Level = level;
+ record.m_Message = message;
+ record.m_SourceFile = source_file;
+ record.m_SourceLine = source_line;
+ record.m_SourceFunction = source_function;
+ NPT_System::GetCurrentTimeStamp(record.m_TimeStamp);
+ record.m_ThreadId = (NPT_UInt64)NPT_Thread::GetCurrentThreadId();
+
+ /* call all handlers for this logger and parents */
+ m_Manager.Lock();
+ m_Manager.SetEnabled(false); // prevent recursion
+ while (logger) {
+ /* call all handlers for the current logger */
+ for (NPT_List<NPT_LogHandler*>::Iterator i = logger->m_Handlers.GetFirstItem();
+ i;
+ ++i) {
+ NPT_LogHandler* handler = *i;
+ handler->Log(record);
+ }
+
+ /* forward to the parent unless this logger does not forward */
+ if (logger->m_ForwardToParent) {
+ logger = logger->m_Parent;
+ } else {
+ break;
+ }
+ }
+ m_Manager.SetEnabled(true);
+ m_Manager.Unlock();
+
+ /* free anything we may have allocated */
+ if (message != buffer) delete[] message;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Logger::AddHandler
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Logger::AddHandler(NPT_LogHandler* handler, bool transfer_ownership /* = true */)
+{
+ /* check parameters */
+ if (handler == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ /* keep track of what handlers we won't cleanup */
+ if (!transfer_ownership) m_ExternalHandlers.Add(handler);
+
+ return m_Handlers.Add(handler);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Logger::SetParent
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Logger::SetParent(NPT_Logger* parent)
+{
+ /* set our new parent */
+ m_Parent = parent;
+
+ /* find the first ancestor with its own log level */
+ NPT_Logger* logger = this;
+ while (logger->m_LevelIsInherited && logger->m_Parent) {
+ logger = logger->m_Parent;
+ }
+ if (logger != this) m_Level = logger->m_Level;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogNullHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogNullHandler::Create(NPT_LogHandler*& handler)
+{
+ handler = new NPT_LogNullHandler();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogNullHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogNullHandler::Log(const NPT_LogRecord& /*record*/)
+{
+}
+
+
+NPT_LogHandler::CustomHandlerExternalFunction NPT_LogCustomHandler::s_ExternalFunction = NULL;
+/*----------------------------------------------------------------------
+| NPT_LogCustomHandler::SetCustomHandlerFunction
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogCustomHandler::SetCustomHandlerFunction(CustomHandlerExternalFunction function)
+{
+ s_ExternalFunction = function;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogCustomHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogCustomHandler::Create(NPT_LogHandler*& handler)
+{
+ /* allocate a new object */
+ NPT_LogCustomHandler* instance = new NPT_LogCustomHandler();
+ handler = instance;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogCustomHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogCustomHandler::Log(const NPT_LogRecord& record)
+{
+ if (s_ExternalFunction) {
+ (*s_ExternalFunction)(&record);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogConsoleHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogConsoleHandler::Create(const char* logger_name,
+ NPT_LogHandler*& handler)
+{
+ /* compute a prefix for the configuration of this handler */
+ NPT_String logger_prefix = logger_name;
+ logger_prefix += ".ConsoleHandler";
+
+ /* allocate a new object */
+ NPT_LogConsoleHandler* instance = new NPT_LogConsoleHandler();
+ handler = instance;
+
+ /* configure the object */
+ NPT_String* colors;
+ instance->m_UseColors = NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE;
+ colors = LogManager.GetConfigValue(logger_prefix,".colors");
+ if (colors) {
+ if (NPT_LogManager::ConfigValueIsBooleanTrue(*colors)) {
+ instance->m_UseColors = true;
+ } else if (NPT_LogManager::ConfigValueIsBooleanFalse(*colors)) {
+ instance->m_UseColors = false;
+ }
+ }
+
+ NPT_String* outputs;
+ instance->m_Outputs = NPT_CONFIG_DEFAULT_LOG_CONSOLE_HANDLER_OUTPUTS;
+ outputs = LogManager.GetConfigValue(logger_prefix,".outputs");
+ if (outputs) {
+ outputs->ToInteger(instance->m_Outputs, true);
+ }
+
+ NPT_String* filter;
+ instance->m_FormatFilter = 0;
+ filter = LogManager.GetConfigValue(logger_prefix,".filter");
+ if (filter) {
+ filter->ToInteger(instance->m_FormatFilter, true);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogConsoleHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogConsoleHandler::Log(const NPT_LogRecord& record)
+{
+ NPT_MemoryStream memory_stream(4096);
+
+ NPT_Log::FormatRecordToStream(record, memory_stream, m_UseColors, m_FormatFilter);
+ memory_stream.Write("\0", 1);
+ if (m_Outputs & OUTPUT_TO_CONSOLE) {
+ NPT_Console::Output((const char*)memory_stream.GetData());
+ }
+ if (m_Outputs & OUTPUT_TO_DEBUG) {
+ NPT_DebugOutput((const char*)memory_stream.GetData());
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogFileHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogFileHandler::Log(const NPT_LogRecord& record)
+{
+ if (m_MaxFilesize > 0) {
+ /* get current file size */
+ NPT_LargeSize size;
+ NPT_File::GetSize(m_Filename, size);
+
+ /* time to recycle ? */
+ if (size > m_MaxFilesize) {
+ /* release stream to force a reopen later
+ and to be able to rename file */
+ m_Stream = NULL;
+
+ /* rename file using current time */
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ NPT_String suffix = NPT_DateTime(now, true).ToString(NPT_DateTime::FORMAT_W3C);
+ suffix.Replace(':', '_');
+ NPT_String new_name = NPT_FilePath::Create(
+ NPT_FilePath::DirName(m_Filename),
+ NPT_FilePath::BaseName(m_Filename, false) +
+ "-" +
+ suffix +
+ NPT_FilePath::FileExtension(m_Filename));
+
+ NPT_File::Rename(m_Filename, new_name);
+ }
+ }
+
+ /* try to reopen the file if it failed to open
+ previously or if we rotated it */
+ if (m_Stream.IsNull()) {
+ Open(m_Append);
+ }
+
+ if (m_Stream.AsPointer()) {
+ NPT_Log::FormatRecordToStream(record, *m_Stream, false, m_FormatFilter);
+ if (m_Flush) m_Stream->Flush();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogFileHandler::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogFileHandler::Open(bool append /* = true */)
+{
+ /* reset stream just in case */
+ m_Stream = NULL;
+
+ /* open the log file */
+ NPT_File file(m_Filename);
+ NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_CREATE |
+ NPT_FILE_OPEN_MODE_READ |
+ NPT_FILE_OPEN_MODE_WRITE |
+ (append?NPT_FILE_OPEN_MODE_APPEND:NPT_FILE_OPEN_MODE_TRUNCATE));
+ if (NPT_FAILED(result)) return result;
+
+ NPT_CHECK(file.GetOutputStream(m_Stream));
+ /* seek to end */
+ if (append) {
+ NPT_LargeSize size;
+ NPT_CHECK(NPT_File::GetSize(m_Filename, size));
+ NPT_CHECK(m_Stream->Seek(size));
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogFileHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogFileHandler::Create(const char* logger_name,
+ NPT_LogHandler*& handler)
+{
+ /* compute a prefix for the configuration of this handler */
+ NPT_String logger_prefix = logger_name;
+ logger_prefix += ".FileHandler";
+
+ /* allocate a new object */
+ NPT_LogFileHandler* instance = new NPT_LogFileHandler();
+ handler = instance;
+
+ /* filename */
+ NPT_String* filename_conf = LogManager.GetConfigValue(logger_prefix, ".filename");
+ if (filename_conf) {
+ instance->m_Filename = *filename_conf;
+ } else if (logger_name[0]) {
+ NPT_String filename_synth = logger_name;
+ filename_synth += ".log";
+ instance->m_Filename = filename_synth;
+ } else {
+ /* default name for the root logger */
+ instance->m_Filename = NPT_CONFIG_DEFAULT_LOG_FILE_HANDLER_FILENAME;
+ }
+
+ /* always flush flag */
+ NPT_String* flush = LogManager.GetConfigValue(logger_prefix, ".flush");
+ if (flush && NPT_LogManager::ConfigValueIsBooleanTrue(*flush)) {
+ instance->m_Flush = true;
+ } else {
+ instance->m_Flush = false;
+ }
+
+ /* append mode */
+ instance->m_Append = true;
+ NPT_String* append_mode = LogManager.GetConfigValue(logger_prefix, ".append");
+ if (append_mode && NPT_LogManager::ConfigValueIsBooleanFalse(*append_mode)) {
+ instance->m_Append = false;
+ }
+
+ /* filter */
+ NPT_String* filter;
+ instance->m_FormatFilter = 0;
+ filter = LogManager.GetConfigValue(logger_prefix,".filter");
+ if (filter) {
+ filter->ToInteger(instance->m_FormatFilter, true);
+ }
+
+ /* recycle */
+ NPT_String* recycle;
+ instance->m_MaxFilesize = 0;
+ recycle = LogManager.GetConfigValue(logger_prefix,".recycle");
+ if (recycle) {
+ NPT_ParseInteger64(*recycle, instance->m_MaxFilesize, true);
+ if (instance->m_MaxFilesize < NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE) {
+ instance->m_MaxFilesize = NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE;
+ }
+ }
+
+ /* open the log file */
+ return instance->Open(instance->m_Append);
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogTcpHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogTcpHandler::Create(const char* logger_name, NPT_LogHandler*& handler)
+{
+ /* compute a prefix for the configuration of this handler */
+ NPT_String logger_prefix = logger_name;
+ logger_prefix += ".TcpHandler";
+
+ /* allocate a new object */
+ NPT_LogTcpHandler* instance = new NPT_LogTcpHandler();
+ handler = instance;
+
+ /* configure the object */
+ const NPT_String* hostname = LogManager.GetConfigValue(logger_prefix, ".hostname");
+ if (hostname) {
+ instance->m_Host = *hostname;
+ } else {
+ /* default hostname */
+ instance->m_Host = "localhost";
+ }
+ const NPT_String* port = LogManager.GetConfigValue(logger_prefix, ".port");
+ if (port) {
+ NPT_UInt32 port_int;
+ if (NPT_SUCCEEDED(port->ToInteger(port_int, true))) {
+ instance->m_Port = (NPT_UInt16)port_int;
+ } else {
+ instance->m_Port = NPT_LOG_TCP_HANDLER_DEFAULT_PORT;
+ }
+ } else {
+ /* default port */
+ instance->m_Port = NPT_LOG_TCP_HANDLER_DEFAULT_PORT;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogTcpHandler::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogTcpHandler::Connect()
+{
+ /* create a socket */
+ NPT_TcpClientSocket tcp_socket;
+
+ /* connect to the host */
+ NPT_IpAddress ip_address;
+ NPT_CHECK(ip_address.ResolveName(m_Host));
+ NPT_Result result = tcp_socket.Connect(NPT_SocketAddress(ip_address, m_Port),
+ NPT_LOG_TCP_HANDLER_DEFAULT_CONNECT_TIMEOUT);
+ if (NPT_FAILED(result)) {
+ return result;
+ }
+
+ /* get the stream */
+ return tcp_socket.GetOutputStream(m_Stream);
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogTcpHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogTcpHandler::FormatRecord(const NPT_LogRecord& record, NPT_String& msg)
+{
+ /* format the record */
+ const char* level_name = NPT_Log::GetLogLevelName(record.m_Level);
+ NPT_String level_string;
+
+ /* format and emit the record */
+ if (level_name[0] == '\0') {
+ level_string = NPT_String::FromIntegerU(record.m_Level);
+ level_name = level_string;
+ }
+ msg.Reserve(2048);
+ msg += "Logger: ";
+ msg += record.m_LoggerName;
+ msg += "\r\nLevel: ";
+ msg += level_name;
+ msg += "\r\nSource-File: ";
+ msg += record.m_SourceFile;
+ msg += "\r\nSource-Function: ";
+ msg += record.m_SourceFunction;
+ msg += "\r\nSource-Line: ";
+ msg += NPT_String::FromIntegerU(record.m_SourceLine);
+ msg += "\r\nThread-Id: ";
+ msg += NPT_String::FromIntegerU(record.m_ThreadId);
+ msg += "\r\nTimeStamp: ";
+ msg += NPT_DateTime(record.m_TimeStamp, true).ToString(NPT_DateTime::FORMAT_W3C,
+ NPT_DateTime::FLAG_EMIT_FRACTION |
+ NPT_DateTime::FLAG_EXTENDED_PRECISION);
+ msg += "\r\nContent-Length: ";
+ msg += NPT_String::FromIntegerU(NPT_StringLength(record.m_Message));
+ msg += "\r\n\r\n";
+ msg += record.m_Message;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogTcpHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogTcpHandler::Log(const NPT_LogRecord& record)
+{
+ // ensure we're connected
+ if (m_Stream.IsNull()) {
+ if (NPT_FAILED(Connect())) return;
+ }
+
+ // format the record
+ NPT_String msg;
+ FormatRecord(record, msg);
+
+ // log, and disconnect if this fails
+ if (NPT_FAILED(m_Stream->WriteString(msg))) {
+ m_Stream = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogUdpHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogUdpHandler::Create(const char* logger_name, NPT_LogHandler*& handler)
+{
+ /* compute a prefix for the configuration of this handler */
+ NPT_String logger_prefix = logger_name;
+ logger_prefix += ".UdpHandler";
+
+ /* allocate a new object */
+ NPT_LogUdpHandler* instance = new NPT_LogUdpHandler();
+ handler = instance;
+
+ /* configure the object */
+ const char* hostname = "localhost";
+ const NPT_String* hostname_prop = LogManager.GetConfigValue(logger_prefix, ".hostname");
+ if (hostname_prop) {
+ hostname = hostname_prop->GetChars();
+ }
+ NPT_UInt32 port = NPT_LOG_UDP_HANDLER_DEFAULT_PORT;
+ const NPT_String* port_prop = LogManager.GetConfigValue(logger_prefix, ".port");
+ if (port_prop) {
+ if (NPT_FAILED(port_prop->ToInteger(port, true))) {
+ port = NPT_LOG_UDP_HANDLER_DEFAULT_PORT;
+ }
+ }
+
+ // resolve the target hostname
+ NPT_IpAddress target_ip;
+ target_ip.ResolveName(hostname);
+ instance->m_Target.SetIpAddress(target_ip);
+ instance->m_Target.SetPort(port);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_LogUdpHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogUdpHandler::Log(const NPT_LogRecord& record)
+{
+ // format the record
+ NPT_String msg;
+ NPT_LogTcpHandler::FormatRecord(record, msg);
+
+ // send it in a datagram
+ NPT_DataBuffer buffer(msg.GetChars(), msg.GetLength()+1, false);
+ m_Socket.Send(buffer, &m_Target);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpLoggerConfigurator::NPT_HttpLoggerConfigurator
++---------------------------------------------------------------------*/
+NPT_HttpLoggerConfigurator::NPT_HttpLoggerConfigurator(NPT_UInt16 port, bool detached) :
+ NPT_Thread(detached)
+{
+ // create the server
+ m_Server = new NPT_HttpServer(port);
+
+ // attach a handler to response to the requests
+ m_Server->AddRequestHandler(this, "/", true);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpLoggerConfigurator::~NPT_HttpLoggerConfigurator
++---------------------------------------------------------------------*/
+NPT_HttpLoggerConfigurator::~NPT_HttpLoggerConfigurator()
+{
+ // TODO: send a command to the server to tell it to abort
+
+ // cleanup
+ delete m_Server;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpLoggerConfigurator::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpLoggerConfigurator::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& /*context*/,
+ NPT_HttpResponse& response)
+{
+ // we only support GET here
+ if (request.GetMethod() != NPT_HTTP_METHOD_GET) return NPT_ERROR_HTTP_METHOD_NOT_SUPPORTED;
+
+ // construct the response message
+ NPT_String msg;
+
+ msg = "<ul>";
+ NPT_List<NPT_LogConfigEntry>& config = LogManager.GetConfig();
+ NPT_List<NPT_LogConfigEntry>::Iterator cit = config.GetFirstItem();
+ for (; cit; ++cit) {
+ NPT_LogConfigEntry& entry = (*cit);
+ msg += "<li>";
+ msg += entry.m_Key;
+ msg += "=";
+ msg += entry.m_Value;
+ msg += "</li>";
+ }
+ msg += "</ul>";
+
+ msg += "<ul>";
+ NPT_List<NPT_Logger*>& loggers = LogManager.GetLoggers();
+ NPT_List<NPT_Logger*>::Iterator lit = loggers.GetFirstItem();
+ for (;lit;++lit) {
+ NPT_Logger* logger = (*lit);
+ msg += "<li>";
+ msg += logger->GetName();
+ msg += ", level=";
+ msg += NPT_String::FromInteger(logger->GetLevel());
+
+ NPT_List<NPT_LogHandler*>& handlers = logger->GetHandlers();
+ NPT_List<NPT_LogHandler*>::Iterator hit = handlers.GetFirstItem();
+ msg += ", handlers=";
+ for (;hit;++hit) {
+ NPT_LogHandler* handler = (*hit);
+ msg += handler->ToString();
+ }
+ msg += "</li>";
+ }
+ msg += "</ul>";
+
+ // setup the response body
+ NPT_HttpEntity* entity = response.GetEntity();
+ entity->SetContentType("text/html");
+ entity->SetInputStream(msg);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpLoggerConfigurator::Run
++---------------------------------------------------------------------*/
+void
+NPT_HttpLoggerConfigurator::Run()
+{
+ for (;;) {
+ NPT_Result result;
+ result = m_Server->Loop();
+ if (NPT_FAILED(result)) {
+ break;
+ }
+ }
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptLogging.h b/lib/libUPnP/Neptune/Source/Core/NptLogging.h
new file mode 100644
index 0000000..cbd98ca
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptLogging.h
@@ -0,0 +1,524 @@
+/*****************************************************************
+|
+| Neptune - Logging Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+/** @file
+* Header file for logging
+*/
+
+#ifndef _NPT_LOGGING_H_
+#define _NPT_LOGGING_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptTime.h"
+#include "NptStrings.h"
+#include "NptList.h"
+#include "NptStreams.h"
+#include "NptThreads.h"
+#include "NptHttp.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class NPT_LogManager;
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+class NPT_LogRecord {
+public:
+ const char* m_LoggerName;
+ int m_Level;
+ const char* m_Message;
+ NPT_TimeStamp m_TimeStamp;
+ const char* m_SourceFile;
+ unsigned int m_SourceLine;
+ const char* m_SourceFunction;
+ NPT_UInt64 m_ThreadId;
+};
+
+class NPT_LogHandler {
+public:
+ typedef void(*CustomHandlerExternalFunction)(const NPT_LogRecord* record);
+
+ // class methods
+ static NPT_Result SetCustomHandlerFunction(CustomHandlerExternalFunction function);
+ static NPT_Result Create(const char* logger_name,
+ const char* handler_name,
+ NPT_LogHandler*& handler);
+
+ // methods
+ virtual ~NPT_LogHandler() {}
+ virtual void Log(const NPT_LogRecord& record) = 0;
+ virtual NPT_String ToString() { return ""; }
+};
+
+class NPT_Logger {
+public:
+ // methods
+ NPT_Logger(const char* name, NPT_LogManager& manager);
+ ~NPT_Logger();
+ void Log(int level,
+ const char* source_file,
+ unsigned int source_line,
+ const char* source_function,
+ const char* msg,
+ ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 6, 7)))
+#endif
+ ;
+
+ NPT_Result AddHandler(NPT_LogHandler* handler, bool transfer_ownership = true);
+ NPT_Result DeleteHandlers();
+ NPT_Result SetParent(NPT_Logger* parent);
+ const NPT_String& GetName() const { return m_Name; }
+ int GetLevel() const { return m_Level; }
+ bool GetForwardToParent() const { return m_ForwardToParent; }
+ NPT_List<NPT_LogHandler*>& GetHandlers() { return m_Handlers; }
+
+private:
+ // members
+ NPT_LogManager& m_Manager;
+ NPT_String m_Name;
+ int m_Level;
+ bool m_LevelIsInherited;
+ bool m_ForwardToParent;
+ NPT_Logger* m_Parent;
+ NPT_List<NPT_LogHandler*> m_Handlers;
+ NPT_List<NPT_LogHandler*> m_ExternalHandlers;
+
+ // friends
+ friend class NPT_LogManager;
+};
+
+typedef struct {
+ NPT_Logger* logger;
+ const char* name;
+} NPT_LoggerReference;
+
+class NPT_Log {
+public:
+ // class methods
+ static int GetLogLevel(const char* name);
+ static const char* GetLogLevelName(int level);
+ static const char* GetLogLevelAnsiColor(int level);
+ static void FormatRecordToStream(const NPT_LogRecord& record,
+ NPT_OutputStream& stream,
+ bool use_colors,
+ NPT_Flags format_filter);
+};
+
+class NPT_LogConfigEntry {
+public:
+ NPT_LogConfigEntry(const char* key, const char* value) :
+ m_Key(key), m_Value(value) {}
+ NPT_String m_Key;
+ NPT_String m_Value;
+};
+
+class NPT_LogManager {
+public:
+ // class methods
+ static NPT_LogManager& GetDefault();
+ static bool ConfigValueIsBooleanTrue(NPT_String& value);
+ static bool ConfigValueIsBooleanFalse(NPT_String& value);
+ static NPT_Logger* GetLogger(const char* name);
+
+ // methods
+ NPT_LogManager();
+ ~NPT_LogManager();
+ NPT_Result Configure(const char* config_sources = NULL);
+ NPT_String* GetConfigValue(const char* prefix, const char* suffix);
+ NPT_List<NPT_Logger*>& GetLoggers() { return m_Loggers; }
+ NPT_List<NPT_LogConfigEntry>& GetConfig() { return m_Config; }
+ void SetEnabled(bool enabled) { m_Enabled = enabled; }
+ bool IsEnabled() { return m_Enabled; }
+ void Lock();
+ void Unlock();
+
+private:
+ // methods
+ NPT_Result SetConfigValue(const char* key, const char* value);
+ NPT_Result ParseConfig(const char* config, NPT_Size config_size);
+ NPT_Result ParseConfigSource(NPT_String& source);
+ NPT_Result ParseConfigFile(const char* filename);
+ bool HaveLoggerConfig(const char* name);
+ NPT_Logger* FindLogger(const char* name);
+ NPT_Result ConfigureLogger(NPT_Logger* logger);
+
+ // members
+ NPT_Mutex m_Lock;
+ NPT_Thread::ThreadId m_LockOwner;
+ unsigned int m_LockRecursion;
+ bool m_Enabled;
+ bool m_Configured;
+ NPT_List<NPT_LogConfigEntry> m_Config;
+ NPT_List<NPT_Logger*> m_Loggers;
+ NPT_Logger* m_Root;
+};
+
+const unsigned short NPT_HTTP_LOGGER_CONFIGURATOR_DEFAULT_PORT = 6378;
+class NPT_HttpLoggerConfigurator : NPT_HttpRequestHandler, public NPT_Thread {
+public:
+ // constructor and destructor
+ NPT_HttpLoggerConfigurator(NPT_UInt16 port = NPT_HTTP_LOGGER_CONFIGURATOR_DEFAULT_PORT,
+ bool detached = true);
+ ~NPT_HttpLoggerConfigurator() override;
+
+ // NPT_Runnable (NPT_Thread) methods
+ void Run() override;
+
+private:
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // members
+ NPT_HttpServer* m_Server;
+};
+
+NPT_Result NPT_GetSystemLogConfig(NPT_String& config);
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_LOG_LEVEL_FATAL 700
+#define NPT_LOG_LEVEL_SEVERE 600
+#define NPT_LOG_LEVEL_WARNING 500
+#define NPT_LOG_LEVEL_INFO 400
+#define NPT_LOG_LEVEL_FINE 300
+#define NPT_LOG_LEVEL_FINER 200
+#define NPT_LOG_LEVEL_FINEST 100
+
+#define NPT_LOG_LEVEL_OFF 32767
+#define NPT_LOG_LEVEL_ALL 0
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define NPT_LOG_GET_LOGGER(_logger) \
+ if ((_logger).logger == NULL) { \
+ (_logger).logger = NPT_LogManager::GetLogger((_logger).name); \
+ }
+
+#if defined(NPT_CONFIG_ENABLE_LOGGING)
+
+#define NPT_DEFINE_LOGGER(_logger, _name) static volatile NPT_LoggerReference _logger = { NULL, (_name) };
+
+#define NPT_LOG_X(_logger, _level, _argsx) \
+do { \
+ NPT_LOG_GET_LOGGER((_logger)) \
+ if ((_logger).logger && (_level) >= (_logger).logger->GetLevel()) { \
+ (_logger).logger->Log _argsx; \
+ } \
+} while(0)
+
+#define NPT_CHECK_LL(_logger, _level, _result) do { \
+ NPT_Result _x = (_result); \
+ if (_x != NPT_SUCCESS) { \
+ NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"NPT_CHECK failed, result=%d (%s) [%s]", _x, NPT_ResultText(_x), #_result)); \
+ return _x; \
+ } \
+} while(0)
+
+#define NPT_CHECK_LABEL_LL(_logger, _level, _result, _label) do { \
+ NPT_Result _x = (_result); \
+ if (_x != NPT_SUCCESS) { \
+ NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"NPT_CHECK failed, result=%d (%s) [%s]", _x, NPT_ResultText(_x), #_result)); \
+ goto _label; \
+ } \
+} while(0)
+#define NPT_CHECK_POINTER_LL(_logger, _level, _p) do { \
+ if ((_p) == NULL) { \
+ NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"@@@ NULL pointer parameter")); \
+ return NPT_ERROR_INVALID_PARAMETERS; \
+ } \
+} while(0)
+#define NPT_CHECK_POINTER_LABEL_LL(_logger, _level, _p, _label) do { \
+ if ((_p) == NULL) { \
+ NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"@@@ NULL pointer parameter")); \
+ goto _label; \
+ } \
+} while(0)
+
+#else /* NPT_CONFIG_ENABLE_LOGGING */
+
+#define NPT_DEFINE_LOGGER(_logger, _name)
+#define NPT_LOG_X(_logger, _level, _argsx)
+#define NPT_CHECK_LL(_logger, _level, _result) NPT_CHECK(_result)
+#define NPT_CHECK_LABEL_LL(_logger, _level, _result, _label) NPT_CHECK_LABEL((_result), _label)
+#define NPT_CHECK_POINTER_LL(_logger, _level, _p) NPT_CHECK_POINTER((_p))
+#define NPT_CHECK_POINTER_LABEL_LL(_logger, _level, _p, _label) NPT_CHECK_POINTER_LABEL((_p), _label)
+
+#endif /* NPT_CONFIG_ENABLE_LOGGING */
+
+#define NPT_SET_LOCAL_LOGGER(_name) NPT_DEFINE_LOGGER(_NPT_LocalLogger, (_name))
+#define NPT_CHECK_L(_level, _result) NPT_CHECK_LL(_NPT_LocalLogger, (_level), (_result))
+#define NPT_CHECK_LABEL_L(_level, _result, _label) NPT_CHECK_LABEL_LL(_NPT_LocalLogger, (_level), NULL, (_result), _label)
+
+/* NOTE: the following are machine-generated, do not edit */
+#define NPT_LOG_LL(_logger,_level,_msg) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg)))
+#define NPT_LOG(_level,_msg) NPT_LOG_LL((_NPT_LocalLogger),(_level),(_msg))
+#define NPT_LOG_L(_logger,_level,_msg) NPT_LOG_LL((_logger),(_level),(_msg))
+#define NPT_LOG_LL1(_logger,_level,_msg,_arg1) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1)))
+#define NPT_LOG_1(_level,_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),(_level),(_msg),(_arg1))
+#define NPT_LOG_L1(_logger,_level,_msg,_arg1) NPT_LOG_LL1((_logger),(_level),(_msg),(_arg1))
+#define NPT_LOG_LL2(_logger,_level,_msg,_arg1,_arg2) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2)))
+#define NPT_LOG_2(_level,_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2))
+#define NPT_LOG_L2(_logger,_level,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),(_level),(_msg),(_arg1),(_arg2))
+#define NPT_LOG_LL3(_logger,_level,_msg,_arg1,_arg2,_arg3) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3)))
+#define NPT_LOG_3(_level,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_L3(_logger,_level,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_LL4(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4)))
+#define NPT_LOG_4(_level,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_L4(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_LL5(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5)))
+#define NPT_LOG_5(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_L5(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_LL6(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6)))
+#define NPT_LOG_6(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_L6(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_LL7(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7)))
+#define NPT_LOG_7(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_L7(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_LL8(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8)))
+#define NPT_LOG_8(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_L8(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_LL9(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9)))
+#define NPT_LOG_9(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_L9(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+
+#define NPT_LOG_FATAL(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg))
+#define NPT_LOG_FATAL_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FATAL,(_msg))
+#define NPT_LOG_FATAL_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1))
+#define NPT_LOG_FATAL_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1))
+#define NPT_LOG_FATAL_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FATAL_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FATAL_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FATAL_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FATAL_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FATAL_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FATAL_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FATAL_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FATAL_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FATAL_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FATAL_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FATAL_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FATAL_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FATAL_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FATAL_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FATAL_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_SEVERE(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg))
+#define NPT_LOG_SEVERE_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_SEVERE,(_msg))
+#define NPT_LOG_SEVERE_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1))
+#define NPT_LOG_SEVERE_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1))
+#define NPT_LOG_SEVERE_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_SEVERE_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_SEVERE_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_SEVERE_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_SEVERE_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_SEVERE_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_SEVERE_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_SEVERE_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_SEVERE_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_SEVERE_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_SEVERE_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_SEVERE_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_SEVERE_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_SEVERE_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_SEVERE_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_SEVERE_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_WARNING(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg))
+#define NPT_LOG_WARNING_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_WARNING,(_msg))
+#define NPT_LOG_WARNING_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1))
+#define NPT_LOG_WARNING_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1))
+#define NPT_LOG_WARNING_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_WARNING_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_WARNING_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_WARNING_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_WARNING_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_WARNING_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_WARNING_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_WARNING_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_WARNING_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_WARNING_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_WARNING_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_WARNING_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_WARNING_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_WARNING_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_WARNING_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_WARNING_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_INFO(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg))
+#define NPT_LOG_INFO_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_INFO,(_msg))
+#define NPT_LOG_INFO_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1))
+#define NPT_LOG_INFO_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1))
+#define NPT_LOG_INFO_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_INFO_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_INFO_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_INFO_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_INFO_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_INFO_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_INFO_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_INFO_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_INFO_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_INFO_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_INFO_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_INFO_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_INFO_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_INFO_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_INFO_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_INFO_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINE(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg))
+#define NPT_LOG_FINE_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FINE,(_msg))
+#define NPT_LOG_FINE_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1))
+#define NPT_LOG_FINE_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1))
+#define NPT_LOG_FINE_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINE_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINE_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINE_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINE_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINE_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINE_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINE_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINE_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINE_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINE_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINE_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINE_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINE_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINE_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINE_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINER(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg))
+#define NPT_LOG_FINER_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FINER,(_msg))
+#define NPT_LOG_FINER_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1))
+#define NPT_LOG_FINER_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1))
+#define NPT_LOG_FINER_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINER_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINER_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINER_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINER_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINER_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINER_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINER_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINER_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINER_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINER_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINER_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINER_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINER_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINER_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINER_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINEST(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg))
+#define NPT_LOG_FINEST_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FINEST,(_msg))
+#define NPT_LOG_FINEST_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1))
+#define NPT_LOG_FINEST_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1))
+#define NPT_LOG_FINEST_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINEST_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINEST_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINEST_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINEST_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINEST_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINEST_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINEST_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINEST_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINEST_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINEST_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINEST_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINEST_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINEST_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINEST_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINEST_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+
+#define NPT_CHECK_FATAL(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_result))
+#define NPT_CHECK_FATAL_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FATAL,(_result))
+#define NPT_CHECK_SEVERE(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_result))
+#define NPT_CHECK_SEVERE_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_SEVERE,(_result))
+#define NPT_CHECK_WARNING(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_result))
+#define NPT_CHECK_WARNING_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_WARNING,(_result))
+#define NPT_CHECK_INFO(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_result))
+#define NPT_CHECK_INFO_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_INFO,(_result))
+#define NPT_CHECK_FINE(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_result))
+#define NPT_CHECK_FINE_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FINE,(_result))
+#define NPT_CHECK_FINER(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_result))
+#define NPT_CHECK_FINER_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FINER,(_result))
+#define NPT_CHECK_FINEST(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_result))
+#define NPT_CHECK_FINEST_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FINEST,(_result))
+
+#define NPT_CHECK_LABEL_FATAL(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_result),_label)
+#define NPT_CHECK_LABEL_FATAL_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FATAL,(_result),_label)
+#define NPT_CHECK_LABEL_SEVERE(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_result),_label)
+#define NPT_CHECK_LABEL_SEVERE_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_SEVERE,(_result),_label)
+#define NPT_CHECK_LABEL_WARNING(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_result),_label)
+#define NPT_CHECK_LABEL_WARNING_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_WARNING,(_result),_label)
+#define NPT_CHECK_LABEL_INFO(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_result),_label)
+#define NPT_CHECK_LABEL_INFO_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_INFO,(_result),_label)
+#define NPT_CHECK_LABEL_FINE(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_result),_label)
+#define NPT_CHECK_LABEL_FINE_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FINE,(_result),_label)
+#define NPT_CHECK_LABEL_FINER(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_result),_label)
+#define NPT_CHECK_LABEL_FINER_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FINER,(_result),_label)
+#define NPT_CHECK_LABEL_FINEST(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_result),_label)
+#define NPT_CHECK_LABEL_FINEST_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FINEST,(_result),_label)
+
+#define NPT_CHECK_POINTER_FATAL(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_p))
+#define NPT_CHECK_POINTER_FATAL_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FATAL,(_p))
+#define NPT_CHECK_POINTER_SEVERE(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_p))
+#define NPT_CHECK_POINTER_SEVERE_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_SEVERE,(_p))
+#define NPT_CHECK_POINTER_WARNING(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_p))
+#define NPT_CHECK_POINTER_WARNING_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_WARNING,(_p))
+#define NPT_CHECK_POINTER_INFO(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_p))
+#define NPT_CHECK_POINTER_INFO_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_INFO,(_p))
+#define NPT_CHECK_POINTER_FINE(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_p))
+#define NPT_CHECK_POINTER_FINE_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FINE,(_p))
+#define NPT_CHECK_POINTER_FINER(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_p))
+#define NPT_CHECK_POINTER_FINER_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FINER,(_p))
+#define NPT_CHECK_POINTER_FINEST(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_p))
+#define NPT_CHECK_POINTER_FINEST_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FINEST,(_p))
+
+#define NPT_CHECK_POINTER_LABEL_FATAL(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FATAL_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FATAL,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_SEVERE(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_SEVERE_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_SEVERE,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_WARNING(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_WARNING_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_WARNING,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_INFO(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_INFO_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_INFO,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FINE(_p, _label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FINE_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FINE,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FINER(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FINER_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FINER,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FINEST(_p,_label) NNPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_p),_label)
+#define NPT_CHECK_POINTER_LABEL_FINEST_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FINEST,(_p),_label)
+
+#endif /* _NPT_LOGGING_H_ */
diff --git a/lib/libUPnP/Neptune/Source/Core/NptMap.h b/lib/libUPnP/Neptune/Source/Core/NptMap.h
new file mode 100644
index 0000000..75acbbe
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptMap.h
@@ -0,0 +1,807 @@
+/*****************************************************************
+|
+| Neptune - Maps
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_MAP_H_
+#define _NPT_MAP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+#include "NptList.h"
+#include "NptHash.h"
+
+/*----------------------------------------------------------------------
+| NPT_Map
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+class NPT_Map
+{
+public:
+ // types
+ class Entry {
+ public:
+ // constructor
+ Entry(const K& key, const V& value) : m_Key(key), m_Value(value) {}
+ Entry(const K& key) : m_Key(key), m_Value() {}
+
+ // accessors
+ const K& GetKey() const { return m_Key; }
+ const V& GetValue() const { return m_Value; }
+
+ // operators
+ bool operator==(const Entry& other) const {
+ return m_Key == other.m_Key && m_Value == other.m_Value;
+ }
+
+ protected:
+ // methods
+ void SetValue(const V& value) { m_Value = value; }
+
+ // members
+ K m_Key;
+ V m_Value;
+
+ // friends
+ friend class NPT_Map<K,V>;
+ };
+
+ // constructors
+ NPT_Map<K,V>() {}
+ NPT_Map<K,V>(const NPT_Map<K,V>& copy);
+
+ // destructor
+ ~NPT_Map<K,V>();
+
+ // methods
+ NPT_Result Put(const K& key, const V& value);
+ NPT_Result Get(const K& key, V*& value) const; // WARNING: the second parameter is a POINTER on the value type!!!
+ bool HasKey(const K& key) const { return GetEntry(key) != NULL; }
+ bool HasValue(const V& value) const;
+ NPT_Result Erase(const K& key);
+ NPT_Cardinal GetEntryCount() const { return m_Entries.GetItemCount(); }
+ const NPT_List<Entry*>& GetEntries() const { return m_Entries; }
+ NPT_Result Clear();
+
+ // operators
+ V& operator[](const K& key);
+ const NPT_Map<K,V>& operator=(const NPT_Map<K,V>& copy);
+ bool operator==(const NPT_Map<K,V>& other) const;
+ bool operator!=(const NPT_Map<K,V>& other) const;
+
+private:
+ // types
+ typedef typename NPT_List<Entry*>::Iterator ListIterator;
+
+ // methods
+ Entry* GetEntry(const K& key) const;
+
+ // members
+ NPT_List<Entry*> m_Entries;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::NPT_Map<K,V>
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Map<K,V>::NPT_Map(const NPT_Map<K,V>& copy)
+{
+ *this = copy;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::~NPT_Map<K,V>
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Map<K,V>::~NPT_Map()
+{
+ // call Clear to ensure we delete all entry objects
+ Clear();
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::Clear
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Result
+NPT_Map<K,V>::Clear()
+{
+ m_Entries.Apply(NPT_ObjectDeleter<Entry>());
+ m_Entries.Clear();
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::GetEntry
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+typename NPT_Map<K,V>::Entry*
+NPT_Map<K,V>::GetEntry(const K& key) const
+{
+ typename NPT_List<Entry*>::Iterator entry = m_Entries.GetFirstItem();
+ while (entry) {
+ if ((*entry)->GetKey() == key) {
+ return *entry;
+ }
+ ++entry;
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::Put
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Result
+NPT_Map<K,V>::Put(const K& key, const V& value)
+{
+ Entry* entry = GetEntry(key);
+ if (entry == NULL) {
+ // no existing entry for that key, create one
+ m_Entries.Add(new Entry(key, value));
+ } else {
+ // replace the existing entry for that key
+ entry->SetValue(value);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::Get
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Result
+NPT_Map<K,V>::Get(const K& key, V*& value) const
+{
+ Entry* entry = GetEntry(key);
+ if (entry == NULL) {
+ // no existing entry for that key
+ value = NULL;
+ return NPT_ERROR_NO_SUCH_ITEM;
+ } else {
+ // found an entry with that key
+ value = &entry->m_Value;
+ return NPT_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::HasValue
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+bool
+NPT_Map<K,V>::HasValue(const V& value) const
+{
+ ListIterator entry = m_Entries.GetFirstItem();
+ while (entry) {
+ if (value == (*entry)->m_Value) {
+ return true;
+ }
+ ++entry;
+ }
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::operator=
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+const NPT_Map<K,V>&
+NPT_Map<K,V>::operator=(const NPT_Map<K,V>& copy)
+{
+ // do nothing if we're assigning to ourselves
+ if (this == &copy) return copy;
+
+ // destroy all entries
+ Clear();
+
+ // copy all entries one by one
+ ListIterator entry = copy.m_Entries.GetFirstItem();
+ while (entry) {
+ m_Entries.Add(new Entry((*entry)->GetKey(), (*entry)->GetValue()));
+ ++entry;
+ }
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::Erase
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Result
+NPT_Map<K,V>::Erase(const K& key)
+{
+ ListIterator entry = m_Entries.GetFirstItem();
+ while (entry) {
+ if ((*entry)->GetKey() == key) {
+ delete *entry; // do this before removing the entry from the
+ // list, because Erase() will invalidate the
+ // iterator item
+ m_Entries.Erase(entry);
+ return NPT_SUCCESS;
+ }
+ ++entry;
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::operator==
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+bool
+NPT_Map<K,V>::operator==(const NPT_Map<K,V>& other) const
+{
+ // quick test
+ if (m_Entries.GetItemCount() != other.m_Entries.GetItemCount()) return false;
+
+ // compare all entries to all other entries
+ ListIterator entry = m_Entries.GetFirstItem();
+ while (entry) {
+ V* value;
+ if (NPT_SUCCEEDED(other.Get((*entry)->m_Key, value))) {
+ // the other map has an entry for this key, check the value
+ if (!(*value == (*entry)->m_Value)) return false;
+ } else {
+ // the other map does not have an entry for this key
+ return false;
+ }
+ ++entry;
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::operator!=
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+bool
+NPT_Map<K,V>::operator!=(const NPT_Map<K,V>& other) const
+{
+ return !(*this == other);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Map<K,V>::operator[]
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+V&
+NPT_Map<K,V>::operator[](const K& key)
+{
+ Entry* entry = GetEntry(key);
+ if (entry == NULL) {
+ // create a new "default" entry for this key
+ entry = new Entry(key);
+ m_Entries.Add(entry);
+ }
+
+ return entry->m_Value;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF = NPT_Hash<K> >
+class NPT_HashMap
+{
+public:
+ // types
+ class Entry {
+ public:
+ // constructor
+ Entry(NPT_UInt32 hash_value, const K& key, const V& value) : m_HashValue(hash_value), m_Key(key), m_Value(value) {}
+ Entry(NPT_UInt32 hash_value, const K& key) : m_HashValue(hash_value), m_Key(key), m_Value() {}
+
+ // accessors
+ const K& GetKey() const { return m_Key; }
+ const V& GetValue() const { return m_Value; }
+ NPT_UInt32 GetHashValue() const { return m_HashValue; }
+
+ // operators
+ bool operator==(const Entry& other) const {
+ return m_HashValue == other.m_HashValue && m_Key == other.m_Key && m_Value == other.m_Value;
+ }
+
+ protected:
+ // methods
+ void SetValue(const V& value) { m_Value = value; }
+
+ // members
+ NPT_UInt32 m_HashValue;
+ K m_Key;
+ V m_Value;
+
+ // friends
+ friend class NPT_HashMap<K,V,HF>;
+ };
+
+ class Iterator {
+ public:
+ Iterator() : m_Entry(NULL), m_Map(NULL) {}
+ Iterator(Entry** entry, const NPT_HashMap<K,V,HF>* map) : m_Entry(entry), m_Map(map) {}
+ Iterator(const Iterator& copy) : m_Entry(copy.m_Entry), m_Map(copy.m_Map) {}
+ const Entry& operator*() const { return **m_Entry; }
+ Iterator& operator++() { // prefix
+ if (m_Map && m_Entry) {
+ do {
+ ++m_Entry;
+ if (m_Entry >= &m_Map->m_Buckets[1<<m_Map->m_BucketCountLog]) {
+ m_Entry = NULL;
+ } else {
+ if (*m_Entry) break;
+ }
+ } while (m_Entry);
+ }
+ return (*this);
+ }
+ Iterator operator++(int) { // postfix
+ Iterator saved_this = *this;
+ ++(*this);
+ return saved_this;
+ }
+ operator bool() const {
+ return m_Entry != NULL;
+ }
+ bool operator==(const Iterator& other) const {
+ return m_Map == other.m_Map && m_Entry == other.m_Entry;
+ }
+ bool operator!=(const Iterator& other) const {
+ return !(*this == other);
+ }
+ void operator=(const Iterator& other) {
+ m_Entry = other.m_Entry;
+ m_Map = other.m_Map;
+ }
+
+ private:
+ // friends
+ friend class NPT_HashMap<K,V,HF>;
+
+ // members
+ Entry** m_Entry;
+ const NPT_HashMap<K,V,HF>* m_Map;
+ };
+
+ // constructors
+ NPT_HashMap<K,V,HF>();
+ NPT_HashMap<K,V,HF>(const HF& hasher);
+ NPT_HashMap<K,V,HF>(const NPT_HashMap<K,V,HF>& copy);
+
+ // destructor
+ ~NPT_HashMap<K,V,HF>();
+
+ // methods
+ NPT_Result Put(const K& key, const V& value);
+ NPT_Result Get(const K& key, V*& value) const; // WARNING: the second parameter is a POINTER on the value type!!!
+ bool HasKey(const K& key) const { return GetEntry(key) != NULL; }
+ bool HasValue(const V& value) const;
+ NPT_Result Erase(const K& key);
+ NPT_Cardinal GetEntryCount() const { return m_EntryCount; }
+ Iterator GetEntries() const;
+ NPT_Result Clear();
+
+ // list operations
+ // keep these template members defined here because MSV6 does not let
+ // us define them later
+ template <typename X>
+ NPT_Result Apply(const X& function) const
+ {
+ for (int i=0; i<(1<<m_BucketCountLog); i++) {
+ if (m_Buckets[i]) {
+ function(m_Buckets[i]);
+ }
+ }
+ return NPT_SUCCESS;
+ }
+
+ // operators
+ V& operator[](const K& key);
+ const NPT_HashMap<K,V,HF>& operator=(const NPT_HashMap<K,V,HF>& copy);
+ bool operator==(const NPT_HashMap<K,V,HF>& other) const;
+ bool operator!=(const NPT_HashMap<K,V,HF>& other) const;
+
+private:
+ // methods
+ Entry* GetEntry(const K& key, NPT_UInt32* position=NULL) const;
+ NPT_Result AddEntry(Entry* entry);
+ void AllocateBuckets(unsigned int count_log);
+ void AdjustBuckets(NPT_Cardinal entry_count, bool allow_shrink=false);
+
+ // members
+ HF m_Hasher;
+ Entry** m_Buckets;
+ NPT_Cardinal m_BucketCountLog;
+ NPT_Cardinal m_EntryCount;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V>::NPT_HashMap
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_HashMap<K,V,HF>::NPT_HashMap() :
+ m_Buckets(NULL),
+ m_EntryCount(0)
+{
+ AllocateBuckets(4);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V>::NPT_HashMap
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_HashMap<K,V,HF>::NPT_HashMap(const HF& hasher) :
+ m_Hasher(hasher),
+ m_Buckets(NULL),
+ m_EntryCount(0)
+{
+ AllocateBuckets(4);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V>::NPT_HashMap
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_HashMap<K,V,HF>::NPT_HashMap(const NPT_HashMap<K,V,HF>& copy) :
+ m_Buckets(NULL),
+ m_BucketCountLog(0),
+ m_EntryCount(0)
+{
+ *this = copy;
+}
+
+/*----------------------------------------------------------------------
+| NPT_MapMap<K,V,HF>::NPT_HashMap
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_HashMap<K,V,HF>::~NPT_HashMap()
+{
+ for (int i=0; i<(1<<m_BucketCountLog); i++) {
+ delete m_Buckets[i];
+ }
+ delete[] m_Buckets;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::AllocateBuckets
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+void
+NPT_HashMap<K,V,HF>::AllocateBuckets(unsigned int count_log)
+{
+ m_Buckets = new Entry*[1<<count_log];
+ m_BucketCountLog = count_log;
+ for (int i=0; i<(1<<count_log); i++) {
+ m_Buckets[i] = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::AdjustBuckets
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+void
+NPT_HashMap<K,V,HF>::AdjustBuckets(NPT_Cardinal entry_count, bool allow_shrink)
+{
+ Entry** buckets = NULL;
+ unsigned int bucket_count = 1<<m_BucketCountLog;
+ if (2*entry_count >= bucket_count) {
+ // we need to grow
+ buckets = m_Buckets;
+ AllocateBuckets(m_BucketCountLog+1);
+ } else if (allow_shrink && (5*entry_count < bucket_count) && m_BucketCountLog > 4) {
+ // we need to shrink
+ buckets = m_Buckets;
+ AllocateBuckets(m_BucketCountLog-1);
+ }
+ if (buckets) {
+ m_EntryCount = 0;
+ for (unsigned int i=0; i<bucket_count; i++) {
+ if (buckets[i]) AddEntry(buckets[i]);
+ }
+ delete[] buckets;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::Clear
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_Result
+NPT_HashMap<K,V,HF>::Clear()
+{
+ if (m_Buckets) {
+ for (int i=0; i<(1<<m_BucketCountLog); i++) {
+ delete m_Buckets[i];
+ }
+ delete[] m_Buckets;
+ }
+ m_EntryCount = 0;
+ AllocateBuckets(4);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::GetEntries
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+typename NPT_HashMap<K,V,HF>::Iterator
+NPT_HashMap<K,V,HF>::GetEntries() const
+{
+ for (int i=0; i<(1<<m_BucketCountLog); i++) {
+ if (m_Buckets[i]) {
+ return Iterator(&m_Buckets[i], this);
+ }
+ }
+ return Iterator(NULL, this);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::GetEntry
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+typename NPT_HashMap<K,V,HF>::Entry*
+NPT_HashMap<K,V,HF>::GetEntry(const K& key, NPT_UInt32* position) const
+{
+ NPT_UInt32 hash_value = m_Hasher(key);
+ NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
+ NPT_UInt32 cursor = hash_value & mask;
+ while (m_Buckets[cursor]) {
+ Entry* entry = m_Buckets[cursor];
+ if (entry->m_HashValue == hash_value &&
+ entry->m_Key == key) {
+ if (position) *position = cursor;
+ return entry;
+ }
+ cursor = (cursor + 1) & mask;
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::AddEntry
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_Result
+NPT_HashMap<K,V,HF>::AddEntry(Entry* entry)
+{
+ AdjustBuckets(m_EntryCount+1);
+
+ NPT_UInt32 hash_value = entry->m_HashValue;
+ NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
+ NPT_UInt32 cursor = hash_value & mask;
+ while (m_Buckets[cursor]) {
+ cursor = (cursor + 1) & mask;
+ }
+ m_Buckets[cursor] = entry;
+ ++m_EntryCount;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::Put
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_Result
+NPT_HashMap<K,V,HF>::Put(const K& key, const V& value)
+{
+ Entry* entry = GetEntry(key);
+ if (entry == NULL) {
+ // no existing entry for that key, create one
+ return AddEntry(new Entry(m_Hasher(key), key, value));
+ } else {
+ // replace the existing entry for that key
+ entry->SetValue(value);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::Get
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_Result
+NPT_HashMap<K,V,HF>::Get(const K& key, V*& value) const
+{
+ Entry* entry = GetEntry(key);
+ if (entry == NULL) {
+ // no existing entry for that key
+ value = NULL;
+ return NPT_ERROR_NO_SUCH_ITEM;
+ } else {
+ // found an entry with that key
+ value = &entry->m_Value;
+ return NPT_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::HasValue
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+bool
+NPT_HashMap<K,V,HF>::HasValue(const V& value) const
+{
+ for (int i=0; i<(1<<m_BucketCountLog); i++) {
+ if (m_Buckets[i] && m_Buckets[i]->m_Value == value) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::Erase
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+NPT_Result
+NPT_HashMap<K,V,HF>::Erase(const K& key)
+{
+ NPT_UInt32 position;
+ Entry* entry = GetEntry(key, &position);
+ if (entry == NULL) {
+ return NPT_ERROR_NO_SUCH_ITEM;
+ }
+
+ // mark the bucket as unoccupied
+ m_Buckets[position] = NULL;
+
+ // look for buckets that need to be relocated:
+ // there should be no empty bucket between an entry's ideal hash bucket
+ // and its actual bucket.
+ NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
+ for (NPT_UInt32 cursor = (position+1) & mask; m_Buckets[cursor]; cursor = (cursor + 1) & mask) {
+ NPT_UInt32 target = m_Buckets[cursor]->m_HashValue & mask;
+ // check if target is between position and cursor (modulo the bucket array size)
+ // | position.target.cursor |
+ // |....cursor position.target.| or |.target..cursor position...|
+ if ( (position <= cursor) ?
+ ((position < target) && (target <= cursor)) :
+ ((position < target) || (target <= cursor)) ) {
+ continue;
+ }
+
+ // move the bucket back
+ m_Buckets[position] = m_Buckets[cursor];
+ m_Buckets[cursor] = NULL;
+ position = cursor;
+ }
+
+ // cleanup and adjust the counter and buckets
+ delete entry;
+ --m_EntryCount;
+ AdjustBuckets(m_EntryCount, true);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::operator=
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+const NPT_HashMap<K,V,HF>&
+NPT_HashMap<K,V,HF>::operator=(const NPT_HashMap<K,V,HF>& copy)
+{
+ // do nothing if we're assigning to ourselves
+ if (this == &copy) return copy;
+
+ // destroy all entries
+ Clear();
+
+ // prepare to receive all the entries
+ AdjustBuckets(copy.m_EntryCount);
+
+ // copy all entries
+ for (int i=0; i<1<<copy.m_BucketCountLog; i++) {
+ if (copy.m_Buckets[i]) {
+ AddEntry(new Entry(m_Hasher(copy.m_Buckets[i]->GetKey()),
+ copy.m_Buckets[i]->GetKey(),
+ copy.m_Buckets[i]->GetValue()));
+ }
+ }
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::operator==
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+bool
+NPT_HashMap<K,V,HF>::operator==(const NPT_HashMap<K,V,HF>& other) const
+{
+ // quick check
+ if (m_EntryCount != other.m_EntryCount) return false;
+
+ // compare all entries to all other entries
+ for (int i=0; i<(1<<m_BucketCountLog); i++) {
+ Entry* entry = m_Buckets[i];
+ if (entry == NULL) continue;
+ Entry* other_entry = other.GetEntry(entry->m_Key);
+ if (other_entry == NULL || !(other_entry->m_Value == entry->m_Value)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V,HF>::operator!=
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+bool
+NPT_HashMap<K,V,HF>::operator!=(const NPT_HashMap<K,V,HF>& other) const
+{
+ return !(*this == other);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HashMap<K,V>::operator[]
++---------------------------------------------------------------------*/
+template <typename K, typename V, typename HF>
+V&
+NPT_HashMap<K,V,HF>::operator[](const K& key)
+{
+ Entry* entry = GetEntry(key);
+ if (entry == NULL) {
+ // create a new "default" entry for this key
+ entry = new Entry(m_Hasher(key), key);
+ AddEntry(entry);
+ }
+
+ return entry->m_Value;
+}
+
+/*----------------------------------------------------------------------
+| NPT_MapEntryValueDeleter
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_MapEntryValueDeleter {
+public:
+ void operator()(T* entry) const {
+ delete entry->GetValue();
+ }
+};
+
+#endif // _NPT_MAP_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptMessaging.cpp b/lib/libUPnP/Neptune/Source/Core/NptMessaging.cpp
new file mode 100644
index 0000000..cffe1d1
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptMessaging.cpp
@@ -0,0 +1,127 @@
+/*****************************************************************
+|
+| Neptune - Messaging System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptMessaging.h"
+#include "NptDynamicCast.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_DEFINE_DYNAMIC_CAST_ANCHOR(NPT_MessageHandler)
+const NPT_Message::Type NPT_Message::MessageType = "Generic Message";
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandler::HandleMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MessageHandler::HandleMessage(NPT_Message* message)
+{
+ return message->Dispatch(this);
+}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::NPT_MessageHandlerProxy
++---------------------------------------------------------------------*/
+NPT_DEFINE_DYNAMIC_CAST_ANCHOR(NPT_MessageHandlerProxy)
+NPT_MessageHandlerProxy::NPT_MessageHandlerProxy(NPT_MessageHandler* handler) :
+ m_Handler(handler),
+ m_ReferenceCount(1)
+{}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::NPT_MessageHandlerProxy
++---------------------------------------------------------------------*/
+NPT_MessageHandlerProxy::~NPT_MessageHandlerProxy()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::OnMessage
++---------------------------------------------------------------------*/
+void
+NPT_MessageHandlerProxy::OnMessage(NPT_Message* message)
+{
+ m_Lock.Lock();
+ if (m_Handler) m_Handler->OnMessage(message);
+ m_Lock.Unlock();
+}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::HandleMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MessageHandlerProxy::HandleMessage(NPT_Message* message)
+{
+ NPT_Result result = NPT_SUCCESS;
+ m_Lock.Lock();
+ if (m_Handler) result = m_Handler->HandleMessage(message);
+ m_Lock.Unlock();
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::DetachHandler
++---------------------------------------------------------------------*/
+void
+NPT_MessageHandlerProxy::DetachHandler()
+{
+ m_Lock.Lock();
+ m_Handler = NULL;
+ m_Lock.Unlock();
+}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::AddReference
++---------------------------------------------------------------------*/
+void
+NPT_MessageHandlerProxy::AddReference()
+{
+ m_Lock.Lock();
+ ++m_ReferenceCount;
+ m_Lock.Unlock();
+}
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy::Release
++---------------------------------------------------------------------*/
+void
+NPT_MessageHandlerProxy::Release()
+{
+ m_Lock.Lock();
+ bool must_delete = (--m_ReferenceCount == 0);
+ m_Lock.Unlock();
+
+ if (must_delete) delete this;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptMessaging.h b/lib/libUPnP/Neptune/Source/Core/NptMessaging.h
new file mode 100644
index 0000000..3da21a0
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptMessaging.h
@@ -0,0 +1,230 @@
+/*****************************************************************
+|
+| Neptune - Messaging System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_MESSAGING_H_
+#define _NPT_MESSAGING_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConstants.h"
+#include "NptTypes.h"
+#include "NptResults.h"
+#include "NptList.h"
+#include "NptThreads.h"
+#include "NptDynamicCast.h"
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+class NPT_Message;
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandler
++---------------------------------------------------------------------*/
+class NPT_MessageHandler
+{
+public:
+ NPT_IMPLEMENT_DYNAMIC_CAST(NPT_MessageHandler)
+
+ // methods
+ virtual ~NPT_MessageHandler() {}
+
+ // default message handler
+ virtual void OnMessage(NPT_Message*) {}
+
+ // this method is a central point of handling for received messages.
+ // it can be overloaded by subclasses that wish to process all
+ // incoming messages
+ virtual NPT_Result HandleMessage(NPT_Message* message);
+};
+
+/*----------------------------------------------------------------------
+| NPT_MessageHandlerProxy
++---------------------------------------------------------------------*/
+class NPT_MessageHandlerProxy : public NPT_MessageHandler
+{
+public:
+ NPT_IMPLEMENT_DYNAMIC_CAST_D(NPT_MessageHandlerProxy, NPT_MessageHandler)
+
+ /**
+ * Create a proxy for a message handler.
+ * All calls to HandleMessage() and OnMessage() on the proxy
+ * are automatically forwarded to the handler.
+ * This class is useful in cases where a handler is passed
+ * asynchronously (for example in a message queue) and one wishes
+ * to guarantee right away that no more calls to the handler will be
+ * made (because, for example, the handler needs to be deleted).
+ *
+ * The proxy object keeps a pointer to the handler, but does not own it.
+ */
+ NPT_MessageHandlerProxy(NPT_MessageHandler* handler);
+
+ // destructor
+ ~NPT_MessageHandlerProxy() override;
+
+ // NPT_MessageHandler methods
+ void OnMessage(NPT_Message*) override;
+ NPT_Result HandleMessage(NPT_Message* message) override;
+
+ /**
+ * Detach the proxy from the handler implementation.
+ * After this call returns, calls will no longer be
+ * forwarded to the handler object. It is then safe, for example,
+ * to delete the handler.
+ */
+ void DetachHandler();
+
+ /**
+ * Increment the reference count
+ */
+ void AddReference();
+
+ /**
+ * Decrement the reference count and delete if 0
+ */
+ void Release();
+
+private:
+ // members
+ NPT_MessageHandler* m_Handler;
+ NPT_Cardinal m_ReferenceCount;
+ NPT_Mutex m_Lock;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Messsage
++---------------------------------------------------------------------*/
+class NPT_Message
+{
+public:
+ // types
+ typedef const char* Type;
+
+ // static members
+ static Type const MessageType;
+
+ // methods
+ virtual ~NPT_Message() {}
+ virtual Type GetType() { return MessageType; }
+ virtual NPT_Result Dispatch(NPT_MessageHandler* handler) {
+ return DefaultDeliver(handler);
+ }
+ // this method should really be called 'Deliver', but this would
+ // cause a problem when subclasses overload it
+ virtual NPT_Result DefaultDeliver(NPT_MessageHandler* handler) {
+ handler->OnMessage(this);
+ return NPT_SUCCESS;
+ }
+};
+
+/*----------------------------------------------------------------------
+| NPT_TerminateMesssage
++---------------------------------------------------------------------*/
+class NPT_TerminateMessage : public NPT_Message
+{
+public:
+ // methods
+ NPT_Result Dispatch(NPT_MessageHandler* /*handler*/) override {
+ return NPT_ERROR_TERMINATED;
+ }
+};
+
+/*----------------------------------------------------------------------
+| NPT_MessageQueue
++---------------------------------------------------------------------*/
+class NPT_MessageQueue
+{
+public:
+ // methods
+ virtual ~NPT_MessageQueue() {}
+ virtual NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+ virtual NPT_Result QueueMessage(NPT_Message* message,
+ NPT_MessageHandler* handler) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_MessageReceiver
++---------------------------------------------------------------------*/
+class NPT_MessageReceiver
+{
+public:
+ // methods
+ NPT_MessageReceiver() : m_Queue(NULL), m_Handler(NULL) {}
+ NPT_MessageReceiver(NPT_MessageHandler* handler) :
+ m_Queue(NULL), m_Handler(handler) {}
+ NPT_MessageReceiver(NPT_MessageQueue* queue) :
+ m_Queue(queue), m_Handler(NULL) {}
+ NPT_MessageReceiver(NPT_MessageHandler* handler,
+ NPT_MessageQueue* queue) :
+ m_Queue(queue), m_Handler(handler) {}
+ virtual ~NPT_MessageReceiver() {}
+ NPT_Result SetQueue(NPT_MessageQueue* queue) {
+ m_Queue = queue;
+ return NPT_SUCCESS;
+ }
+ NPT_Result SetHandler(NPT_MessageHandler* handler) {
+ m_Handler = handler;
+ return NPT_SUCCESS;
+ }
+ virtual NPT_Result PostMessage(NPT_Message* message) {
+ if (m_Queue) {
+ return m_Queue->QueueMessage(message, m_Handler);
+ } else {
+ return NPT_FAILURE;
+ }
+ }
+
+protected:
+ // members
+ NPT_MessageQueue* m_Queue;
+ NPT_MessageHandler* m_Handler;
+};
+
+/*----------------------------------------------------------------------
+| NPT_MessageBroadcaster
++---------------------------------------------------------------------*/
+class NPT_MessageBroadcaster
+{
+public:
+ // methods
+ NPT_MessageBroadcaster(NPT_Message* message) : m_Message(message) {}
+ NPT_Result operator()(NPT_MessageReceiver*& receiver) const {
+ receiver->PostMessage(m_Message);
+ return NPT_SUCCESS;
+ }
+
+private:
+ // members
+ NPT_Message* m_Message;
+};
+
+#endif // _NPT_MESSAGING_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptNetwork.cpp b/lib/libUPnP/Neptune/Source/Core/NptNetwork.cpp
new file mode 100644
index 0000000..1b8bde7
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptNetwork.cpp
@@ -0,0 +1,438 @@
+/*****************************************************************
+|
+| Neptune - Network
+|
+| Copyright (c) 2002-2016, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptSockets.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress() :
+ m_Type(IPV4),
+ m_ScopeId(0)
+{
+ NPT_SetMemory(m_Address, 0, sizeof(m_Address));
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress(Type type) :
+ m_Type(type),
+ m_ScopeId(0)
+{
+ NPT_SetMemory(m_Address, 0, sizeof(m_Address));
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress(unsigned long address) :
+ m_Type(IPV4),
+ m_ScopeId(0)
+{
+ Set(address);
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress(unsigned char a,
+ unsigned char b,
+ unsigned char c,
+ unsigned char d) :
+ m_Type(IPV4),
+ m_ScopeId(0)
+{
+ NPT_SetMemory(&m_Address[0], 0, sizeof(m_Address));
+ m_Address[0] = a;
+ m_Address[1] = b;
+ m_Address[2] = c;
+ m_Address[3] = d;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress(Type type, const unsigned char* address, unsigned int size, NPT_UInt32 scope_id) :
+ m_Type(type),
+ m_ScopeId(scope_id)
+{
+ if (type == IPV6 && size == 16) {
+ NPT_CopyMemory(&m_Address[0], address, 16);
+ } else if (type == IPV4 && size == 4) {
+ NPT_CopyMemory(&m_Address[0], address, 4);
+ NPT_SetMemory(&m_Address[4], 0, 12);
+ m_ScopeId = 0;
+ } else {
+ NPT_SetMemory(&m_Address[0], 0, 16);
+ m_ScopeId = 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::AsLong
++---------------------------------------------------------------------*/
+unsigned long
+NPT_IpAddress::AsLong() const
+{
+ return
+ (((unsigned long)m_Address[0])<<24) |
+ (((unsigned long)m_Address[1])<<16) |
+ (((unsigned long)m_Address[2])<< 8) |
+ (((unsigned long)m_Address[3]));
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::AsBytes
++---------------------------------------------------------------------*/
+const unsigned char*
+NPT_IpAddress::AsBytes() const
+{
+ return m_Address;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::Set
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_IpAddress::Set(const unsigned char bytes[4])
+{
+ m_Type = IPV4;
+ m_Address[0] = bytes[0];
+ m_Address[1] = bytes[1];
+ m_Address[2] = bytes[2];
+ m_Address[3] = bytes[3];
+ NPT_SetMemory(&m_Address[4], 0, sizeof(m_Address)-4);
+ m_ScopeId = 0; // always 0 for IPv4
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::Set
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_IpAddress::Set(unsigned long address)
+{
+ m_Type = IPV4;
+ m_Address[0] = (unsigned char)((address >> 24) & 0xFF);
+ m_Address[1] = (unsigned char)((address >> 16) & 0xFF);
+ m_Address[2] = (unsigned char)((address >> 8) & 0xFF);
+ m_Address[3] = (unsigned char)((address ) & 0xFF);
+ NPT_SetMemory(&m_Address[4], 0, sizeof(m_Address)-4);
+ m_ScopeId = 0; // always 0 for IPv4
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::Set
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_IpAddress::Set(const unsigned char* bytes, unsigned int size, NPT_UInt32 scope_id)
+{
+ NPT_SetMemory(&m_Address[0], 0, sizeof(m_Address));
+ if (size == 4) {
+ m_Type = IPV4;
+ NPT_CopyMemory(&m_Address[0], bytes, 4);
+ m_ScopeId = 0; // always 0 for IPv4
+ } else if (size == 16) {
+ m_Type = IPV6;
+ NPT_CopyMemory(&m_Address[0], bytes, 16);
+ m_ScopeId = scope_id;
+ } else {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::operator==
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::operator==(const NPT_IpAddress& other) const
+{
+ unsigned int bytes_to_check = (m_Type == IPV4)?4:16;
+ for (unsigned int i=0; i<bytes_to_check; i++) {
+ if (m_Address[i] != other.m_Address[i]) {
+ return false;
+ }
+ }
+ return m_Type == other.m_Type;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::ToUrlHost
++---------------------------------------------------------------------*/
+NPT_String
+NPT_IpAddress::ToUrlHost() const
+{
+ if (m_Type == IPV6) {
+ NPT_String result = "[";
+ result += ToString();
+ return result+"]";
+ } else {
+ return ToString();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsUnspecified
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsUnspecified() const
+{
+ for (unsigned int i=0; i<(unsigned int)(m_Type==IPV4?4:16); i++) {
+ if (m_Address[i]) return false;
+ }
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsLooppack
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsLooppack() const
+{
+ if (m_Type == IPV4) {
+ return m_Address[0] == 127 &&
+ m_Address[1] == 0 &&
+ m_Address[2] == 0 &&
+ m_Address[3] == 1;
+ } else {
+ return m_Address[ 0] == 0 &&
+ m_Address[ 1] == 0 &&
+ m_Address[ 2] == 0 &&
+ m_Address[ 3] == 0 &&
+ m_Address[ 4] == 0 &&
+ m_Address[ 5] == 0 &&
+ m_Address[ 6] == 0 &&
+ m_Address[ 7] == 0 &&
+ m_Address[ 8] == 0 &&
+ m_Address[ 9] == 0 &&
+ m_Address[10] == 0 &&
+ m_Address[11] == 0 &&
+ m_Address[12] == 0 &&
+ m_Address[13] == 0 &&
+ m_Address[14] == 0 &&
+ m_Address[15] == 1;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsV4Compatible
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsV4Compatible() const
+{
+ if (m_Type == IPV4) return true;
+ return m_Address[ 0] == 0 &&
+ m_Address[ 1] == 0 &&
+ m_Address[ 2] == 0 &&
+ m_Address[ 3] == 0 &&
+ m_Address[ 4] == 0 &&
+ m_Address[ 5] == 0 &&
+ m_Address[ 6] == 0 &&
+ m_Address[ 7] == 0 &&
+ m_Address[ 8] == 0 &&
+ m_Address[ 9] == 0 &&
+ m_Address[10] == 0 &&
+ m_Address[11] == 0 &&
+ !(m_Address[12] == 0 &&
+ m_Address[13] == 0 &&
+ m_Address[14] == 0 &&
+ m_Address[15] == 0) &&
+ !(m_Address[12] == 0 &&
+ m_Address[13] == 0 &&
+ m_Address[14] == 0 &&
+ m_Address[15] == 1);
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsV4Mapped
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsV4Mapped() const
+{
+ if (m_Type == IPV4) return false;
+ return m_Address[ 0] == 0 &&
+ m_Address[ 1] == 0 &&
+ m_Address[ 2] == 0 &&
+ m_Address[ 3] == 0 &&
+ m_Address[ 4] == 0 &&
+ m_Address[ 5] == 0 &&
+ m_Address[ 6] == 0 &&
+ m_Address[ 7] == 0 &&
+ m_Address[ 8] == 0 &&
+ m_Address[ 9] == 0 &&
+ m_Address[10] == 0xFF &&
+ m_Address[11] == 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsLinkLocal
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsLinkLocal() const
+{
+ if (m_Type == IPV4) {
+ return m_Address[0] == 169 && m_Address[1] == 254;
+ } else {
+ return m_Address[0] == 0xFE && ((m_Address[1]&0xC0) == 0x80);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsSiteLocal
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsSiteLocal() const
+{
+ if (m_Type == IPV4) return false;
+ return m_Address[0] == 0xFE && ((m_Address[1]&0xC0) == 0xC0);
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsUniqueLocal
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsUniqueLocal() const
+{
+ if (m_Type == IPV4) {
+ return (m_Address[0] == 10) ||
+ (m_Address[0] == 172 && (m_Address[1]&0xF0) == 16) ||
+ (m_Address[0] == 192 && m_Address[1] == 168);
+ } else {
+ return ((m_Address[0] & 0xFE) == 0xFC);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress::IsMulticast
++---------------------------------------------------------------------*/
+bool
+NPT_IpAddress::IsMulticast() const
+{
+ if (m_Type == IPV4) {
+ return (m_Address[0] & 0xF0) == 224;
+ } else {
+ return m_Address[0] == 0xFF;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_MacAddress::NPT_MacAddress
++---------------------------------------------------------------------*/
+NPT_MacAddress::NPT_MacAddress(Type type,
+ const unsigned char* address,
+ unsigned int length)
+{
+ SetAddress(type, address, length);
+}
+
+/*----------------------------------------------------------------------
+| NPT_MacAddress::SetAddress
++---------------------------------------------------------------------*/
+void
+NPT_MacAddress::SetAddress(Type type,
+ const unsigned char* address,
+ unsigned int length)
+{
+ m_Type = type;
+ if (length > NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH) {
+ length = NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH;
+ }
+ m_Length = length;
+ for (unsigned int i=0; i<length; i++) {
+ m_Address[i] = address[i];
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_MacAddress::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_MacAddress::ToString() const
+{
+ NPT_String result;
+
+ if (m_Length) {
+ char s[3*NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH];
+ const char hex[17] = "0123456789abcdef";
+ for (unsigned int i=0; i<m_Length; i++) {
+ s[i*3 ] = hex[m_Address[i]>>4];
+ s[i*3+1] = hex[m_Address[i]&0xf];
+ s[i*3+2] = ':';
+ }
+ s[3*m_Length-1] = '\0';
+ result = s;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_NetworkInterface::NPT_NetworkInterface
++---------------------------------------------------------------------*/
+NPT_NetworkInterface::NPT_NetworkInterface(const char* name,
+ const NPT_MacAddress& mac,
+ NPT_Flags flags) :
+ m_Name(name),
+ m_MacAddress(mac),
+ m_Flags(flags)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_NetworkInterface::NPT_NetworkInterface
++---------------------------------------------------------------------*/
+NPT_NetworkInterface::NPT_NetworkInterface(const char* name,
+ NPT_Flags flags) :
+ m_Name(name),
+ m_Flags(flags)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_NetworkInterface::AddAddress
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::AddAddress(const NPT_NetworkInterfaceAddress& address)
+{
+ return m_Addresses.Add(address);
+}
+
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptNetwork.h b/lib/libUPnP/Neptune/Source/Core/NptNetwork.h
new file mode 100644
index 0000000..fb37f44
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptNetwork.h
@@ -0,0 +1,277 @@
+/*****************************************************************
+|
+| Neptune - Network
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_NETWORK_H_
+#define _NPT_NETWORK_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH = 8;
+
+/*----------------------------------------------------------------------
+| flags
++---------------------------------------------------------------------*/
+#define NPT_NETWORK_INTERFACE_FLAG_LOOPBACK 0x01
+#define NPT_NETWORK_INTERFACE_FLAG_PROMISCUOUS 0x02
+#define NPT_NETWORK_INTERFACE_FLAG_BROADCAST 0x04
+#define NPT_NETWORK_INTERFACE_FLAG_MULTICAST 0x08
+#define NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT 0x10
+
+/*----------------------------------------------------------------------
+| workarounds
++---------------------------------------------------------------------*/
+#if defined(_WIN32)
+#if defined(SetPort)
+#undef SetPort
+#endif
+#endif
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef unsigned int NPT_IpPort;
+
+/*----------------------------------------------------------------------
+| NPT_IpAddress
++---------------------------------------------------------------------*/
+class NPT_IpAddress
+{
+public:
+ // constants
+ typedef enum {
+ IPV4,
+ IPV6
+ } Type;
+
+ // class members
+ static const NPT_IpAddress Any;
+ static const NPT_IpAddress Loopback;
+
+ // constructors and destructor
+ NPT_IpAddress();
+ NPT_IpAddress(Type type);
+ NPT_IpAddress(unsigned long address);
+ NPT_IpAddress(unsigned char a, unsigned char b, unsigned char c, unsigned char d);
+ NPT_IpAddress(Type type, const unsigned char* address, unsigned int size, NPT_UInt32 scope_id = 0);
+
+ // accessors
+ Type GetType() const { return m_Type; }
+ NPT_UInt32 GetScopeId() const { return m_ScopeId; }
+
+ // methods
+ NPT_Result ResolveName(const char* name,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+ NPT_Result Parse(const char* name);
+ NPT_Result Set(unsigned long address);
+ NPT_Result Set(const unsigned char bytes[4]);
+ NPT_Result Set(const unsigned char* bytes, unsigned int size, NPT_UInt32 scope_id = 0);
+ const unsigned char* AsBytes() const;
+ unsigned long AsLong() const;
+ NPT_String ToString() const;
+ NPT_String ToUrlHost() const;
+
+ // address properties
+ bool IsUnspecified() const;
+ bool IsLooppack() const;
+ bool IsV4Compatible() const;
+ bool IsV4Mapped() const;
+ bool IsLinkLocal() const;
+ bool IsSiteLocal() const;
+ bool IsUniqueLocal() const;
+ bool IsMulticast() const;
+
+ // operators
+ bool operator==(const NPT_IpAddress& other) const;
+
+ // FIXME: temporary
+ NPT_String m_HostName;
+
+private:
+ // members
+ Type m_Type;
+ unsigned char m_Address[16];
+ NPT_UInt32 m_ScopeId; // IPv6 only
+};
+
+/*----------------------------------------------------------------------
+| NPT_MacAddress
++---------------------------------------------------------------------*/
+class NPT_MacAddress
+{
+public:
+ // typedef enum
+ typedef enum {
+ TYPE_UNKNOWN,
+ TYPE_LOOPBACK,
+ TYPE_ETHERNET,
+ TYPE_PPP,
+ TYPE_IEEE_802_11
+ } Type;
+
+ // constructors and destructor
+ NPT_MacAddress() : m_Type(TYPE_UNKNOWN), m_Length(0) {}
+ NPT_MacAddress(Type type,
+ const unsigned char* addr,
+ unsigned int length);
+
+ // methods
+ void SetAddress(Type type, const unsigned char* addr,
+ unsigned int length);
+ Type GetType() const { return m_Type; }
+ const unsigned char* GetAddress() const { return m_Address; }
+ unsigned int GetLength() const { return m_Length; }
+ NPT_String ToString() const;
+
+private:
+ // members
+ Type m_Type;
+ unsigned char m_Address[NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH];
+ unsigned int m_Length;
+};
+
+/*----------------------------------------------------------------------
+| NPT_NetworkInterfaceAddress
++---------------------------------------------------------------------*/
+class NPT_NetworkInterfaceAddress
+{
+public:
+ // constructors and destructor
+ NPT_NetworkInterfaceAddress(const NPT_IpAddress& primary,
+ const NPT_IpAddress& broadcast,
+ const NPT_IpAddress& destination,
+ const NPT_IpAddress& netmask) :
+ m_PrimaryAddress(primary),
+ m_BroadcastAddress(broadcast),
+ m_DestinationAddress(destination),
+ m_NetMask(netmask) {}
+
+ // methods
+ const NPT_IpAddress& GetPrimaryAddress() const {
+ return m_PrimaryAddress;
+ }
+ const NPT_IpAddress& GetBroadcastAddress() const {
+ return m_BroadcastAddress;
+ }
+ const NPT_IpAddress& GetDestinationAddress() const {
+ return m_DestinationAddress;
+ }
+ const NPT_IpAddress& GetNetMask() const {
+ return m_NetMask;
+ }
+
+ bool IsAddressInNetwork(const NPT_IpAddress& address) {
+ if (m_PrimaryAddress.AsLong() == address.AsLong()) return true;
+ if (m_NetMask.AsLong() == 0) return false;
+ return (m_PrimaryAddress.AsLong() & m_NetMask.AsLong()) == (address.AsLong() & m_NetMask.AsLong());
+ }
+
+private:
+ // members
+ NPT_IpAddress m_PrimaryAddress;
+ NPT_IpAddress m_BroadcastAddress;
+ NPT_IpAddress m_DestinationAddress;
+ NPT_IpAddress m_NetMask;
+};
+
+/*----------------------------------------------------------------------
+| NPT_NetworkInterface
++---------------------------------------------------------------------*/
+class NPT_NetworkInterface
+{
+public:
+ // class methods
+ static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces);
+
+ // constructors and destructor
+ NPT_NetworkInterface(const char* name,
+ const NPT_MacAddress& mac,
+ NPT_Flags flags);
+ NPT_NetworkInterface(const char* name,
+ NPT_Flags flags);
+ ~NPT_NetworkInterface() {}
+
+ // methods
+ NPT_Result AddAddress(const NPT_NetworkInterfaceAddress& address);
+ const NPT_String& GetName() const {
+ return m_Name;
+ }
+ const NPT_MacAddress& GetMacAddress() const {
+ return m_MacAddress;
+ }
+ void SetMacAddress(NPT_MacAddress::Type type,
+ const unsigned char* addr,
+ unsigned int length) {
+ m_MacAddress.SetAddress(type, addr, length);
+ }
+ NPT_Flags GetFlags() const { return m_Flags; }
+ const NPT_List<NPT_NetworkInterfaceAddress>& GetAddresses() const {
+ return m_Addresses;
+ }
+
+ bool IsAddressInNetwork(const NPT_IpAddress& address) {
+ NPT_List<NPT_NetworkInterfaceAddress>::Iterator iter = m_Addresses.GetFirstItem();
+ while (iter) {
+ if ((*iter).IsAddressInNetwork(address)) return true;
+ ++iter;
+ }
+ return false;
+ }
+
+private:
+ // members
+ NPT_String m_Name;
+ NPT_MacAddress m_MacAddress;
+ NPT_Flags m_Flags;
+ NPT_List<NPT_NetworkInterfaceAddress> m_Addresses;
+};
+
+/*----------------------------------------------------------------------
+| NPT_NetworkNameResolver
++---------------------------------------------------------------------*/
+class NPT_NetworkNameResolver
+{
+public:
+ // class methods
+ static NPT_Result Resolve(const char* name,
+ NPT_List<NPT_IpAddress>& addresses,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+};
+
+#endif // _NPT_NETWORK_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptQueue.cpp b/lib/libUPnP/Neptune/Source/Core/NptQueue.cpp
new file mode 100644
index 0000000..bd68ad2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptQueue.cpp
@@ -0,0 +1,36 @@
+/*****************************************************************
+|
+| Neptune - Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptQueue.h"
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptQueue.h b/lib/libUPnP/Neptune/Source/Core/NptQueue.h
new file mode 100644
index 0000000..ecfe1a9
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptQueue.h
@@ -0,0 +1,94 @@
+/*****************************************************************
+|
+| Neptune - Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_QUEUE_H_
+#define _NPT_QUEUE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+| NPT_QueueItem
++---------------------------------------------------------------------*/
+class NPT_QueueItem;
+
+/*----------------------------------------------------------------------
+| NPT_GenericQueue
++---------------------------------------------------------------------*/
+class NPT_GenericQueue
+{
+ public:
+ // class methods
+ static NPT_GenericQueue* CreateInstance(NPT_Cardinal max_items = 0);
+
+ // methods
+ virtual ~NPT_GenericQueue() {}
+ virtual NPT_Result Push(NPT_QueueItem* item,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+ virtual NPT_Result Pop(NPT_QueueItem*& item,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+ virtual NPT_Result Peek(NPT_QueueItem*& item,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+ protected:
+ // methods
+ NPT_GenericQueue() {}
+};
+
+/*----------------------------------------------------------------------
+| NPT_Queue
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_Queue
+{
+ public:
+ // methods
+ NPT_Queue(NPT_Cardinal max_items = 0) :
+ m_Delegate(NPT_GenericQueue::CreateInstance(max_items)) {}
+ virtual ~NPT_Queue<T>() { delete m_Delegate; }
+ virtual NPT_Result Push(T* item, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+ return m_Delegate->Push(reinterpret_cast<NPT_QueueItem*>(item), timeout);
+ }
+ virtual NPT_Result Pop(T*& item, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+ return m_Delegate->Pop(reinterpret_cast<NPT_QueueItem*&>(item), timeout);
+ }
+ virtual NPT_Result Peek(T*& item, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+ return m_Delegate->Peek(reinterpret_cast<NPT_QueueItem*&>(item), timeout);
+ }
+
+ protected:
+ // members
+ NPT_GenericQueue* m_Delegate;
+};
+
+#endif // _NPT_QUEUE_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptReferences.h b/lib/libUPnP/Neptune/Source/Core/NptReferences.h
new file mode 100644
index 0000000..c8e1f5a
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptReferences.h
@@ -0,0 +1,173 @@
+/*****************************************************************
+|
+| Neptune - References
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_REFERENCES_H_
+#define _NPT_REFERENCES_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConstants.h"
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+| NPT_Reference
++---------------------------------------------------------------------*/
+template <typename T>
+class NPT_Reference
+{
+public:
+ // constructors and destructor
+ NPT_Reference() : m_Object(NULL), m_Counter(NULL), m_Mutex(NULL), m_ThreadSafe(true) {}
+ explicit NPT_Reference(T* object, bool thread_safe = true) :
+ m_Object(object),
+ m_Counter(object?new NPT_Cardinal(1):NULL),
+ m_Mutex((object && thread_safe)?new NPT_Mutex():NULL),
+ m_ThreadSafe(thread_safe) {}
+
+ NPT_Reference(const NPT_Reference<T>& ref) :
+ m_Object(ref.m_Object), m_Counter(ref.m_Counter), m_Mutex(ref.m_Mutex), m_ThreadSafe(ref.m_ThreadSafe) {
+ if (m_Mutex) m_Mutex->Lock();
+ if (m_Counter) ++(*m_Counter);
+ if (m_Mutex) m_Mutex->Unlock();
+ }
+
+ // this methods should be private, but this causes a problem on some
+ // compilers, because we need this function in order to implement
+ // the cast operator operator NPT_Reference<U>() below, which would
+ // have to be marked as a friend, and friend declarations with the
+ // same class name confuses some compilers
+ NPT_Reference(T* object, NPT_Cardinal* counter, NPT_Mutex* mutex, bool thread_safe) :
+ m_Object(object), m_Counter(counter), m_Mutex(mutex), m_ThreadSafe(thread_safe) {
+ if (m_Mutex) m_Mutex->Lock();
+ if (m_Counter) ++(*m_Counter);
+ if (m_Mutex) m_Mutex->Unlock();
+ }
+
+ ~NPT_Reference() {
+ Release();
+ }
+
+ // overloaded operators
+ NPT_Reference<T>& operator=(const NPT_Reference<T>& ref) {
+ if (this != &ref) {
+ Release();
+ m_Object = ref.m_Object;
+ m_Counter = ref.m_Counter;
+ m_Mutex = ref.m_Mutex;
+ m_ThreadSafe = ref.m_ThreadSafe;
+
+ if (m_Mutex) m_Mutex->Lock();
+ if (m_Counter) ++(*m_Counter);
+ if (m_Mutex) m_Mutex->Unlock();
+ }
+ return *this;
+ }
+ NPT_Reference<T>& operator=(T* object) {
+ Release();
+ m_Object = object;
+ m_Counter = object?new NPT_Cardinal(1):NULL;
+ m_Mutex = (object && m_ThreadSafe)?new NPT_Mutex():NULL;
+ return *this;
+ }
+ T& operator*() const { return *m_Object; }
+ T* operator->() const { return m_Object; }
+
+ bool operator==(const NPT_Reference<T>& ref) const {
+ return m_Object == ref.m_Object;
+ }
+ bool operator!=(const NPT_Reference<T>& ref) const {
+ return m_Object != ref.m_Object;
+ }
+
+ // overloaded cast operators
+ template <typename U> operator NPT_Reference<U>() {
+ return NPT_Reference<U>(m_Object, m_Counter, m_Mutex, m_ThreadSafe);
+ }
+
+ // methods
+ /**
+ * Returns the naked pointer value.
+ */
+ T* AsPointer() const { return m_Object; }
+
+ /**
+ * Returns the reference counter value.
+ */
+ NPT_Cardinal GetCounter() const { return *m_Counter; }
+
+ /**
+ * Returns whether this references a NULL object.
+ */
+ bool IsNull() const { return m_Object == NULL; }
+
+ /**
+ * Detach the reference from the shared object.
+ * The reference count is decremented, but the object is not deleted if the
+ * reference count becomes 0.
+ * After the method returns, this reference does not point to any shared object.
+ */
+ void Detach() {
+ Release(true);
+ }
+
+private:
+ // methods
+ void Release(bool detach_only = false) {
+ bool last_reference = false;
+ if (m_Mutex) m_Mutex->Lock();
+
+ if (m_Counter && --(*m_Counter) == 0) {
+ delete m_Counter;
+ if (!detach_only) delete m_Object;
+ last_reference = true;
+ }
+
+ m_Counter = NULL;
+ m_Object = NULL;
+
+ if (m_Mutex) {
+ NPT_Mutex* mutex = m_Mutex;
+ m_Mutex = NULL;
+ mutex->Unlock();
+ if (last_reference) delete mutex;
+ }
+
+ }
+
+ // members
+ T* m_Object;
+ NPT_Cardinal* m_Counter;
+ NPT_Mutex* m_Mutex;
+ bool m_ThreadSafe;
+};
+
+#endif // _NPT_REFERENCES_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptResults.cpp b/lib/libUPnP/Neptune/Source/Core/NptResults.cpp
new file mode 100644
index 0000000..cf87793
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptResults.cpp
@@ -0,0 +1,153 @@
+/*****************************************************************
+|
+| Neptune - Result Code Map
+|
+| This file is automatically generated by a script, do not edit!
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| NPT_ResultText
++---------------------------------------------------------------------*/
+const char*
+NPT_ResultText(NPT_Result result)
+{
+ switch (result) {
+ case NPT_SUCCESS: return "SUCCESS";
+ case NPT_FAILURE: return "FAILURE";
+
+ case NPT_ERROR_INVALID_PARAMETERS: return "NPT_ERROR_INVALID_PARAMETERS";
+ case NPT_ERROR_PERMISSION_DENIED: return "NPT_ERROR_PERMISSION_DENIED";
+ case NPT_ERROR_OUT_OF_MEMORY: return "NPT_ERROR_OUT_OF_MEMORY";
+ case NPT_ERROR_NO_SUCH_NAME: return "NPT_ERROR_NO_SUCH_NAME";
+ case NPT_ERROR_NO_SUCH_PROPERTY: return "NPT_ERROR_NO_SUCH_PROPERTY";
+ case NPT_ERROR_NO_SUCH_ITEM: return "NPT_ERROR_NO_SUCH_ITEM";
+ case NPT_ERROR_NO_SUCH_CLASS: return "NPT_ERROR_NO_SUCH_CLASS";
+ case NPT_ERROR_OVERFLOW: return "NPT_ERROR_OVERFLOW";
+ case NPT_ERROR_INTERNAL: return "NPT_ERROR_INTERNAL";
+ case NPT_ERROR_INVALID_STATE: return "NPT_ERROR_INVALID_STATE";
+ case NPT_ERROR_INVALID_FORMAT: return "NPT_ERROR_INVALID_FORMAT";
+ case NPT_ERROR_INVALID_SYNTAX: return "NPT_ERROR_INVALID_SYNTAX";
+ case NPT_ERROR_NOT_IMPLEMENTED: return "NPT_ERROR_NOT_IMPLEMENTED";
+ case NPT_ERROR_NOT_SUPPORTED: return "NPT_ERROR_NOT_SUPPORTED";
+ case NPT_ERROR_TIMEOUT: return "NPT_ERROR_TIMEOUT";
+ case NPT_ERROR_WOULD_BLOCK: return "NPT_ERROR_WOULD_BLOCK";
+ case NPT_ERROR_TERMINATED: return "NPT_ERROR_TERMINATED";
+ case NPT_ERROR_OUT_OF_RANGE: return "NPT_ERROR_OUT_OF_RANGE";
+ case NPT_ERROR_OUT_OF_RESOURCES: return "NPT_ERROR_OUT_OF_RESOURCES";
+ case NPT_ERROR_NOT_ENOUGH_SPACE: return "NPT_ERROR_NOT_ENOUGH_SPACE";
+ case NPT_ERROR_INTERRUPTED: return "NPT_ERROR_INTERRUPTED";
+ case NPT_ERROR_CANCELLED: return "NPT_ERROR_CANCELLED";
+ case NPT_ERROR_LIST_EMPTY: return "NPT_ERROR_LIST_EMPTY";
+ case NPT_ERROR_LIST_OPERATION_ABORTED: return "NPT_ERROR_LIST_OPERATION_ABORTED";
+ case NPT_ERROR_LIST_OPERATION_CONTINUE: return "NPT_ERROR_LIST_OPERATION_CONTINUE";
+ case NPT_ERROR_NO_SUCH_FILE: return "NPT_ERROR_NO_SUCH_FILE";
+ case NPT_ERROR_FILE_NOT_OPEN: return "NPT_ERROR_FILE_NOT_OPEN";
+ case NPT_ERROR_FILE_BUSY: return "NPT_ERROR_FILE_BUSY";
+ case NPT_ERROR_FILE_ALREADY_OPEN: return "NPT_ERROR_FILE_ALREADY_OPEN";
+ case NPT_ERROR_FILE_NOT_READABLE: return "NPT_ERROR_FILE_NOT_READABLE";
+ case NPT_ERROR_FILE_NOT_WRITABLE: return "NPT_ERROR_FILE_NOT_WRITABLE";
+ case NPT_ERROR_FILE_NOT_DIRECTORY: return "NPT_ERROR_FILE_NOT_DIRECTORY";
+ case NPT_ERROR_FILE_ALREADY_EXISTS: return "NPT_ERROR_FILE_ALREADY_EXISTS";
+ case NPT_ERROR_FILE_NOT_ENOUGH_SPACE: return "NPT_ERROR_FILE_NOT_ENOUGH_SPACE";
+ case NPT_ERROR_DIRECTORY_NOT_EMPTY: return "NPT_ERROR_DIRECTORY_NOT_EMPTY";
+ case NPT_ERROR_READ_FAILED: return "NPT_ERROR_READ_FAILED";
+ case NPT_ERROR_WRITE_FAILED: return "NPT_ERROR_WRITE_FAILED";
+ case NPT_ERROR_EOS: return "NPT_ERROR_EOS";
+ case NPT_ERROR_CONNECTION_RESET: return "NPT_ERROR_CONNECTION_RESET";
+ case NPT_ERROR_CONNECTION_ABORTED: return "NPT_ERROR_CONNECTION_ABORTED";
+ case NPT_ERROR_CONNECTION_REFUSED: return "NPT_ERROR_CONNECTION_REFUSED";
+ case NPT_ERROR_CONNECTION_FAILED: return "NPT_ERROR_CONNECTION_FAILED";
+ case NPT_ERROR_HOST_UNKNOWN: return "NPT_ERROR_HOST_UNKNOWN";
+ case NPT_ERROR_SOCKET_FAILED: return "NPT_ERROR_SOCKET_FAILED";
+ case NPT_ERROR_GETSOCKOPT_FAILED: return "NPT_ERROR_GETSOCKOPT_FAILED";
+ case NPT_ERROR_SETSOCKOPT_FAILED: return "NPT_ERROR_SETSOCKOPT_FAILED";
+ case NPT_ERROR_SOCKET_CONTROL_FAILED: return "NPT_ERROR_SOCKET_CONTROL_FAILED";
+ case NPT_ERROR_BIND_FAILED: return "NPT_ERROR_BIND_FAILED";
+ case NPT_ERROR_LISTEN_FAILED: return "NPT_ERROR_LISTEN_FAILED";
+ case NPT_ERROR_ACCEPT_FAILED: return "NPT_ERROR_ACCEPT_FAILED";
+ case NPT_ERROR_ADDRESS_IN_USE: return "NPT_ERROR_ADDRESS_IN_USE";
+ case NPT_ERROR_NETWORK_DOWN: return "NPT_ERROR_NETWORK_DOWN";
+ case NPT_ERROR_NETWORK_UNREACHABLE: return "NPT_ERROR_NETWORK_UNREACHABLE";
+ case NPT_ERROR_HOST_UNREACHABLE: return "NPT_ERROR_HOST_UNREACHABLE";
+ case NPT_ERROR_NO_SUCH_INTERFACE: return "NPT_ERROR_NO_SUCH_INTERFACE";
+ case NPT_ERROR_XML_INVALID_NESTING: return "NPT_ERROR_XML_INVALID_NESTING";
+ case NPT_ERROR_XML_TAG_MISMATCH: return "NPT_ERROR_XML_TAG_MISMATCH";
+ case NPT_ERROR_HTTP_INVALID_RESPONSE_LINE: return "NPT_ERROR_HTTP_INVALID_RESPONSE_LINE";
+ case NPT_ERROR_HTTP_INVALID_REQUEST_LINE: return "NPT_ERROR_HTTP_INVALID_REQUEST_LINE";
+ case NPT_ERROR_HTTP_NO_PROXY: return "NPT_ERROR_HTTP_NO_PROXY";
+ case NPT_ERROR_HTTP_INVALID_REQUEST: return "NPT_ERROR_HTTP_INVALID_REQUEST";
+ case NPT_ERROR_HTTP_METHOD_NOT_SUPPORTED: return "NPT_ERROR_HTTP_METHOD_NOT_SUPPORTED";
+ case NPT_ERROR_HTTP_TOO_MANY_REDIRECTS: return "NPT_ERROR_HTTP_TOO_MANY_REDIRECTS";
+ case NPT_ERROR_HTTP_TOO_MANY_RECONNECTS: return "NPT_ERROR_HTTP_TOO_MANY_RECONNECTS";
+ case NPT_ERROR_HTTP_CANNOT_RESEND_BODY: return "NPT_ERROR_HTTP_CANNOT_RESEND_BODY";
+ case NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN: return "NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN";
+ case NPT_ERROR_CALLBACK_NOTHING_PENDING: return "NPT_ERROR_CALLBACK_NOTHING_PENDING";
+ case NPT_ERROR_NO_SUCH_SERIAL_PORT: return "NPT_ERROR_NO_SUCH_SERIAL_PORT";
+ case NPT_ERROR_SERIAL_PORT_NOT_OPEN: return "NPT_ERROR_SERIAL_PORT_NOT_OPEN";
+ case NPT_ERROR_SERIAL_PORT_ALREADY_OPEN: return "NPT_ERROR_SERIAL_PORT_ALREADY_OPEN";
+ case NPT_ERROR_SERIAL_PORT_BUSY: return "NPT_ERROR_SERIAL_PORT_BUSY";
+ case NPT_ERROR_INVALID_PASSWORD: return "NPT_ERROR_INVALID_PASSWORD";
+ case NPT_ERROR_TLS_INVALID_HANDSHAKE: return "NPT_ERROR_TLS_INVALID_HANDSHAKE";
+ case NPT_ERROR_TLS_INVALID_PROTOCOL_MESSAGE: return "NPT_ERROR_TLS_INVALID_PROTOCOL_MESSAGE";
+ case NPT_ERROR_TLS_INVALID_HMAC: return "NPT_ERROR_TLS_INVALID_HMAC";
+ case NPT_ERROR_TLS_INVALID_VERSION: return "NPT_ERROR_TLS_INVALID_VERSION";
+ case NPT_ERROR_TLS_INVALID_SESSION: return "NPT_ERROR_TLS_INVALID_SESSION";
+ case NPT_ERROR_TLS_NO_CIPHER: return "NPT_ERROR_TLS_NO_CIPHER";
+ case NPT_ERROR_TLS_BAD_CERTIFICATE: return "NPT_ERROR_TLS_BAD_CERTIFICATE";
+ case NPT_ERROR_TLS_INVALID_KEY: return "NPT_ERROR_TLS_INVALID_KEY";
+ case NPT_ERROR_TLS_NO_CLIENT_RENEGOTIATION: return "NPT_ERROR_TLS_NO_CLIENT_RENEGOTIATION";
+ case NPT_ERROR_TLS_INVALID_FINISHED_MESSAGE: return "NPT_ERROR_TLS_INVALID_FINISHED_MESSAGE";
+ case NPT_ERROR_TLS_NO_CERTIFICATE_DEFINED: return "NPT_ERROR_TLS_NO_CERTIFICATE_DEFINED";
+ case NPT_ERROR_TLS_ALERT_HANDSHAKE_FAILED: return "NPT_ERROR_TLS_ALERT_HANDSHAKE_FAILED";
+ case NPT_ERROR_TLS_ALERT_BAD_CERTIFICATE: return "NPT_ERROR_TLS_ALERT_BAD_CERTIFICATE";
+ case NPT_ERROR_TLS_ALERT_INVALID_VERSION: return "NPT_ERROR_TLS_ALERT_INVALID_VERSION";
+ case NPT_ERROR_TLS_ALERT_BAD_RECORD_MAC: return "NPT_ERROR_TLS_ALERT_BAD_RECORD_MAC";
+ case NPT_ERROR_TLS_ALERT_DECODE_ERROR: return "NPT_ERROR_TLS_ALERT_DECODE_ERROR";
+ case NPT_ERROR_TLS_ALERT_DECRYPT_ERROR: return "NPT_ERROR_TLS_ALERT_DECRYPT_ERROR";
+ case NPT_ERROR_TLS_ALERT_ILLEGAL_PARAMETER: return "NPT_ERROR_TLS_ALERT_ILLEGAL_PARAMETER";
+ case NPT_ERROR_TLS_ALERT_UNEXPECTED_MESSAGE: return "NPT_ERROR_TLS_ALERT_UNEXPECTED_MESSAGE";
+ case NPT_ERROR_TLS_CERTIFICATE_FAILURE: return "NPT_ERROR_TLS_CERTIFICATE_FAILURE";
+ case NPT_ERROR_TLS_CERTIFICATE_NO_TRUST_ANCHOR: return "NPT_ERROR_TLS_CERTIFICATE_NO_TRUST_ANCHOR";
+ case NPT_ERROR_TLS_CERTIFICATE_BAD_SIGNATURE: return "NPT_ERROR_TLS_CERTIFICATE_BAD_SIGNATURE";
+ case NPT_ERROR_TLS_CERTIFICATE_NOT_YET_VALID: return "NPT_ERROR_TLS_CERTIFICATE_NOT_YET_VALID";
+ case NPT_ERROR_TLS_CERTIFICATE_EXPIRED: return "NPT_ERROR_TLS_CERTIFICATE_EXPIRED";
+ case NPT_ERROR_TLS_CERTIFICATE_SELF_SIGNED: return "NPT_ERROR_TLS_CERTIFICATE_SELF_SIGNED";
+ case NPT_ERROR_TLS_CERTIFICATE_INVALID_CHAIN: return "NPT_ERROR_TLS_CERTIFICATE_INVALID_CHAIN";
+ case NPT_ERROR_TLS_CERTIFICATE_UNSUPPORTED_DIGEST: return "NPT_ERROR_TLS_CERTIFICATE_UNSUPPORTED_DIGEST";
+ case NPT_ERROR_TLS_CERTIFICATE_INVALID_PRIVATE_KEY: return "NPT_ERROR_TLS_CERTIFICATE_INVALID_PRIVATE_KEY";
+ case NPT_ERROR_TLS_DNS_NAME_MISMATCH: return "NPT_ERROR_TLS_DNS_NAME_MISMATCH";
+
+ default: return "UNKNOWN";
+ }
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptResults.h b/lib/libUPnP/Neptune/Source/Core/NptResults.h
new file mode 100644
index 0000000..274c545
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptResults.h
@@ -0,0 +1,163 @@
+/*****************************************************************
+|
+| Neptune - Result Codes
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_RESULTS_H_
+#define _NPT_RESULTS_H_
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#if defined(NPT_DEBUG)
+#include "NptDebug.h"
+#define NPT_CHECK(_x) \
+do { \
+ NPT_Result _result = (_x); \
+ if (_result != NPT_SUCCESS) { \
+ NPT_Debug("%s(%d): @@@ NPT_CHECK failed, result=%d (%s)\n", __FILE__, __LINE__, _result, NPT_ResultText(_result)); \
+ return _result; \
+ } \
+} while(0)
+#define NPT_CHECK_POINTER(_p) \
+do { \
+ if ((_p) == NULL) { \
+ NPT_Debug("%s(%d): @@@ NULL pointer parameter\n", __FILE__, __LINE__); \
+ return NPT_ERROR_INVALID_PARAMETERS; \
+ } \
+} while(0)
+#define NPT_CHECK_LABEL(_x, label) \
+do { \
+ NPT_Result _result = (_x); \
+ if (_result != NPT_SUCCESS) { \
+ NPT_Debug("%s(%d): @@@ NPT_CHECK failed, result=%d (%s)\n", __FILE__, __LINE__, _result, NPT_ResultText(_result)); \
+ goto label; \
+ } \
+} while(0)
+#define NPT_CHECK_POINTER_LABEL(_p, label) \
+do { \
+ if (_p == NULL) { \
+ NPT_Debug("%s(%d): @@@ NULL pointer parameter\n", __FILE__, __LINE__); \
+ goto label; \
+ } \
+} while(0)
+#else
+#define NPT_CHECK(_x) \
+do { \
+ NPT_Result _result = (_x); \
+ if (_result != NPT_SUCCESS) { \
+ return _result; \
+ } \
+} while(0)
+#define NPT_CHECK_POINTER(_p) \
+do { \
+ if ((_p) == NULL) return NPT_ERROR_INVALID_PARAMETERS; \
+} while(0)
+#define NPT_CHECK_LABEL(_x, label) \
+do { \
+ NPT_Result _result = (_x); \
+ if (_result != NPT_SUCCESS) { \
+ goto label; \
+ } \
+} while(0)
+#define NPT_CHECK_POINTER_LABEL(_p, label) \
+do { \
+ if ((_p) == NULL) { \
+ goto label; \
+ } \
+} while(0)
+#endif
+
+#define NPT_FAILED(result) ((result) != NPT_SUCCESS)
+#define NPT_SUCCEEDED(result) ((result) == NPT_SUCCESS)
+
+/*----------------------------------------------------------------------
+| result codes
++---------------------------------------------------------------------*/
+/** Result indicating that the operation or call succeeded */
+#define NPT_SUCCESS 0
+
+/** Result indicating an unspecififed failure condition */
+#define NPT_FAILURE (-1)
+
+#if !defined(NPT_ERROR_BASE)
+#define NPT_ERROR_BASE -20000
+#endif
+
+// error bases
+const int NPT_ERROR_BASE_GENERAL = NPT_ERROR_BASE-0;
+const int NPT_ERROR_BASE_LIST = NPT_ERROR_BASE-100;
+const int NPT_ERROR_BASE_FILE = NPT_ERROR_BASE-200;
+const int NPT_ERROR_BASE_IO = NPT_ERROR_BASE-300;
+const int NPT_ERROR_BASE_SOCKET = NPT_ERROR_BASE-400;
+const int NPT_ERROR_BASE_INTERFACES = NPT_ERROR_BASE-500;
+const int NPT_ERROR_BASE_XML = NPT_ERROR_BASE-600;
+const int NPT_ERROR_BASE_UNIX = NPT_ERROR_BASE-700;
+const int NPT_ERROR_BASE_HTTP = NPT_ERROR_BASE-800;
+const int NPT_ERROR_BASE_THREADS = NPT_ERROR_BASE-900;
+const int NPT_ERROR_BASE_SERIAL_PORT = NPT_ERROR_BASE-1000;
+const int NPT_ERROR_BASE_TLS = NPT_ERROR_BASE-1100;
+
+// general errors
+const int NPT_ERROR_INVALID_PARAMETERS = NPT_ERROR_BASE_GENERAL - 0;
+const int NPT_ERROR_PERMISSION_DENIED = NPT_ERROR_BASE_GENERAL - 1;
+const int NPT_ERROR_OUT_OF_MEMORY = NPT_ERROR_BASE_GENERAL - 2;
+const int NPT_ERROR_NO_SUCH_NAME = NPT_ERROR_BASE_GENERAL - 3;
+const int NPT_ERROR_NO_SUCH_PROPERTY = NPT_ERROR_BASE_GENERAL - 4;
+const int NPT_ERROR_NO_SUCH_ITEM = NPT_ERROR_BASE_GENERAL - 5;
+const int NPT_ERROR_NO_SUCH_CLASS = NPT_ERROR_BASE_GENERAL - 6;
+const int NPT_ERROR_OVERFLOW = NPT_ERROR_BASE_GENERAL - 7;
+const int NPT_ERROR_INTERNAL = NPT_ERROR_BASE_GENERAL - 8;
+const int NPT_ERROR_INVALID_STATE = NPT_ERROR_BASE_GENERAL - 9;
+const int NPT_ERROR_INVALID_FORMAT = NPT_ERROR_BASE_GENERAL - 10;
+const int NPT_ERROR_INVALID_SYNTAX = NPT_ERROR_BASE_GENERAL - 11;
+const int NPT_ERROR_NOT_IMPLEMENTED = NPT_ERROR_BASE_GENERAL - 12;
+const int NPT_ERROR_NOT_SUPPORTED = NPT_ERROR_BASE_GENERAL - 13;
+const int NPT_ERROR_TIMEOUT = NPT_ERROR_BASE_GENERAL - 14;
+const int NPT_ERROR_WOULD_BLOCK = NPT_ERROR_BASE_GENERAL - 15;
+const int NPT_ERROR_TERMINATED = NPT_ERROR_BASE_GENERAL - 16;
+const int NPT_ERROR_OUT_OF_RANGE = NPT_ERROR_BASE_GENERAL - 17;
+const int NPT_ERROR_OUT_OF_RESOURCES = NPT_ERROR_BASE_GENERAL - 18;
+const int NPT_ERROR_NOT_ENOUGH_SPACE = NPT_ERROR_BASE_GENERAL - 19;
+const int NPT_ERROR_INTERRUPTED = NPT_ERROR_BASE_GENERAL - 20;
+const int NPT_ERROR_CANCELLED = NPT_ERROR_BASE_GENERAL - 21;
+
+/* standard error codes */
+/* these are special codes to convey an errno */
+/* the error code is (SHI_ERROR_BASE_ERRNO - errno) */
+/* where errno is the positive integer from errno.h */
+const int NPT_ERROR_BASE_ERRNO = NPT_ERROR_BASE-2000;
+#define NPT_ERROR_ERRNO(e) (NPT_ERROR_BASE_ERRNO - (e))
+
+/*----------------------------------------------------------------------
+| functions
++---------------------------------------------------------------------*/
+const char* NPT_ResultText(int result);
+
+#endif // _NPT_RESULTS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptRingBuffer.cpp b/lib/libUPnP/Neptune/Source/Core/NptRingBuffer.cpp
new file mode 100644
index 0000000..798176d
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptRingBuffer.cpp
@@ -0,0 +1,269 @@
+/*****************************************************************
+|
+| Neptune - Ring Buffer
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptRingBuffer.h"
+#include "NptResults.h"
+#include "NptUtils.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::NPT_RingBuffer
++---------------------------------------------------------------------*/
+NPT_RingBuffer::NPT_RingBuffer(NPT_Size size) :
+ m_BufferIsLocal(true),
+ m_Closed(false)
+{
+ m_Data.start = new unsigned char[size];
+ m_Data.end = m_Data.start + size;
+
+ m_In = m_Out = m_Data.start;
+}
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::NPT_RingBuffer
++---------------------------------------------------------------------*/
+NPT_RingBuffer::NPT_RingBuffer(void* buffer, NPT_Size size) :
+ m_BufferIsLocal(false),
+ m_Closed(false)
+{
+ m_Data.start = (unsigned char*)buffer;
+ m_Data.end = m_Data.start + size;
+
+ m_In = m_Out = m_Data.start;
+}
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::~NPT_RingBuffer
++---------------------------------------------------------------------*/
+NPT_RingBuffer::~NPT_RingBuffer()
+{
+ if (m_BufferIsLocal) delete[] m_Data.start;
+}
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::GetContiguousSpace
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetContiguousSpace() const
+{
+ return
+ (m_In < m_Out) ?
+ (NPT_Size)(m_Out - m_In - 1) :
+ ((m_Out == m_Data.start) ?
+ (NPT_Size)(m_Data.end - m_In - 1) :
+ (NPT_Size)(m_Data.end - m_In));
+}
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::GetSpace
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetSpace() const
+{
+ return
+ (m_In < m_Out) ?
+ (NPT_Size)(m_Out - m_In - 1) :
+ (NPT_Size)(m_Data.end - m_In + m_Out - m_Data.start - 1);
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::Write
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Write(const void* buffer, NPT_Size byte_count)
+{
+ if (m_Closed) return NPT_ERROR_WRITE_FAILED;
+
+ if (byte_count == 0) return NPT_SUCCESS;
+ if (m_In < m_Out) {
+ if (buffer) NPT_CopyMemory(m_In, buffer, byte_count);
+ m_In += byte_count;
+ if (m_In == m_Data.end) m_In = m_Data.start;
+ } else {
+ unsigned int chunk = (unsigned int)(m_Data.end - m_In);
+ if (chunk >= byte_count) chunk = byte_count;
+
+ if (buffer) NPT_CopyMemory(m_In, buffer, chunk);
+ m_In += chunk;
+ if (m_In == m_Data.end) m_In = m_Data.start;
+ if (chunk != byte_count) {
+ if (buffer) {
+ NPT_CopyMemory(m_In,
+ ((const char*)buffer)+chunk,
+ byte_count-chunk);
+ }
+ m_In += byte_count-chunk;
+ if (m_In == m_Data.end) m_In = m_Data.start;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::GetContiguousAvailable
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetContiguousAvailable() const
+{
+ return
+ (m_Out <= m_In) ?
+ (NPT_Size)(m_In-m_Out) :
+ (NPT_Size)(m_Data.end - m_Out);
+}
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetAvailable() const
+{
+ return
+ (m_Out <= m_In) ?
+ (NPT_Size)(m_In-m_Out) :
+ (NPT_Size)(m_Data.end - m_Out + m_In - m_Data.start);
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::Read
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Read(void* buffer, NPT_Size byte_count)
+{
+ if (m_Closed) return NPT_ERROR_READ_FAILED;
+
+ if (byte_count == 0) return NPT_SUCCESS;
+ if (m_In > m_Out) {
+ if (buffer) NPT_CopyMemory(buffer, m_Out, byte_count);
+ m_Out += byte_count;
+ if (m_Out == m_Data.end) m_Out = m_Data.start;
+ } else {
+ unsigned int chunk = (unsigned int)(m_Data.end - m_Out);
+ if (chunk >= byte_count) chunk = byte_count;
+
+ if (buffer) NPT_CopyMemory(buffer, m_Out, chunk);
+ m_Out += chunk;
+ if (m_Out == m_Data.end) m_Out = m_Data.start;
+ if (chunk != byte_count) {
+ if (buffer) {
+ NPT_CopyMemory(((char*)buffer)+chunk, m_Out, byte_count-chunk);
+ }
+ m_Out += byte_count-chunk;
+ if (m_Out == m_Data.end) m_Out = m_Data.start;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::ReadByte
++----------------------------------------------------------------------*/
+unsigned char
+NPT_RingBuffer::ReadByte()
+{
+ unsigned char result = *m_Out++;
+ if (m_Out == m_Data.end) m_Out = m_Data.start;
+ return result;
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::PeekByte
++----------------------------------------------------------------------*/
+unsigned char
+NPT_RingBuffer::PeekByte(NPT_Position offset)
+{
+ unsigned char *where;
+
+ where = m_Out+offset;
+ if (where >= m_Data.end) where -= (m_Data.end - m_Data.start);
+
+ return *where;
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::MoveIn
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::MoveIn(NPT_Position offset)
+{
+ int fold;
+
+ m_In += offset;
+ fold = (int)(m_In - m_Data.end);
+ if (fold >= 0) {
+ m_In = m_Data.start + fold;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::MoveOut
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::MoveOut(NPT_Position offset)
+{
+ int fold;
+
+ m_Out += offset;
+ fold = (int)(m_Out - m_Data.end);
+ if (fold >= 0) {
+ m_Out = m_Data.start + fold;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::Flush
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Flush()
+{
+ m_In = m_Out = m_Data.start;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+| NPT_RingBuffer::Close
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Close()
+{
+ m_Closed = true;
+ return NPT_SUCCESS;
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptRingBuffer.h b/lib/libUPnP/Neptune/Source/Core/NptRingBuffer.h
new file mode 100644
index 0000000..971e4a5
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptRingBuffer.h
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+| Neptune - Ring Buffer
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_RING_BUFFER_H_
+#define _NPT_RING_BUFFER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptReferences.h"
+
+/*----------------------------------------------------------------------
+| NPT_RingBuffer
++---------------------------------------------------------------------*/
+class NPT_RingBuffer
+{
+ public:
+ // methods
+ NPT_RingBuffer(NPT_Size size);
+ NPT_RingBuffer(void* buffer, NPT_Size size);
+ virtual ~NPT_RingBuffer();
+ NPT_Size GetSpace() const;
+ NPT_Size GetContiguousSpace() const;
+ NPT_Result Write(const void* buffer, NPT_Size byte_count);
+ NPT_Size GetAvailable() const;
+ NPT_Size GetContiguousAvailable() const;
+ NPT_Result Read(void* buffer, NPT_Size byte_count);
+ unsigned char ReadByte();
+ unsigned char PeekByte(NPT_Position offset);
+ NPT_Result MoveIn(NPT_Position offset);
+ NPT_Result MoveOut(NPT_Position offset);
+ NPT_Result Flush();
+ NPT_Result Close();
+ bool IsClosed() { return m_Closed; }
+
+ // accessors
+ unsigned char* GetWritePointer() { return m_In; }
+ unsigned char* GetReadPointer() { return m_Out;}
+
+ private:
+ // members
+ struct {
+ unsigned char* start;
+ unsigned char* end;
+ } m_Data;
+ unsigned char* m_In;
+ unsigned char* m_Out;
+ bool m_BufferIsLocal;
+ bool m_Closed;
+};
+
+typedef NPT_Reference<NPT_RingBuffer> NPT_RingBufferReference;
+
+#endif // _NPT_RING_BUFFER_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSelectableMessageQueue.h b/lib/libUPnP/Neptune/Source/Core/NptSelectableMessageQueue.h
new file mode 100644
index 0000000..56b55d0
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSelectableMessageQueue.h
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+| Neptune - Selectable Message Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SELECTABLE_MESSAGE_QUEUE_H_
+#define _NPT_SELECTABLE_MESSAGE_QUEUE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptMessaging.h"
+#include "NptSimpleMessageQueue.h"
+
+/*----------------------------------------------------------------------
+| NPT_SelectableMessageQueue
++---------------------------------------------------------------------*/
+class NPT_SelectableMessageQueue : public NPT_SimpleMessageQueue
+{
+public:
+ // methods
+ NPT_SelectableMessageQueue();
+ ~NPT_SelectableMessageQueue() override;
+
+ // NPT_MessageQueue methods
+ NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override;
+ NPT_Result QueueMessage(NPT_Message* message,
+ NPT_MessageHandler* handler) override;
+
+ // methods
+ int GetEventFd() { return m_Pipe[0]; }
+
+private:
+ // methods
+ NPT_Result FlushEvent();
+
+ // members
+ int m_Pipe[2];
+};
+
+
+#endif /* _NPT_SELECTABLE_MESSAGE_QUEUE_H_ */
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSerialPort.h b/lib/libUPnP/Neptune/Source/Core/NptSerialPort.h
new file mode 100644
index 0000000..b543c11
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSerialPort.h
@@ -0,0 +1,119 @@
+/*****************************************************************
+|
+| Neptune - Serial Ports
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SERIAL_PORT_H_
+#define _NPT_SERIAL_PORT_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_NO_SUCH_SERIAL_PORT = NPT_ERROR_BASE_SERIAL_PORT - 0;
+const int NPT_ERROR_SERIAL_PORT_NOT_OPEN = NPT_ERROR_BASE_SERIAL_PORT - 1;
+const int NPT_ERROR_SERIAL_PORT_ALREADY_OPEN = NPT_ERROR_BASE_SERIAL_PORT - 2;
+const int NPT_ERROR_SERIAL_PORT_BUSY = NPT_ERROR_BASE_SERIAL_PORT - 3;
+
+typedef enum {
+ NPT_SERIAL_PORT_PARITY_NONE,
+ NPT_SERIAL_PORT_PARITY_EVEN,
+ NPT_SERIAL_PORT_PARITY_ODD,
+ NPT_SERIAL_PORT_PARITY_MARK
+} NPT_SerialPortParity;
+
+typedef enum {
+ NPT_SERIAL_PORT_STOP_BITS_1,
+ NPT_SERIAL_PORT_STOP_BITS_1_5,
+ NPT_SERIAL_PORT_STOP_BITS_2
+} NPT_SerialPortStopBits;
+
+typedef enum {
+ NPT_SERIAL_PORT_FLOW_CONTROL_NONE,
+ NPT_SERIAL_PORT_FLOW_CONTROL_HARDWARE,
+ NPT_SERIAL_PORT_FLOW_CONTROL_XON_XOFF
+} NPT_SerialPortFlowControl;
+
+/*----------------------------------------------------------------------
+| NPT_SerialPortInterface
++---------------------------------------------------------------------*/
+class NPT_SerialPortInterface
+{
+public:
+ // constructors and destructor
+ virtual ~NPT_SerialPortInterface() {}
+
+ // methods
+ virtual NPT_Result Open(unsigned int speed,
+ NPT_SerialPortStopBits stop_bits,
+ NPT_SerialPortFlowControl flow_control,
+ NPT_SerialPortParity parity) = 0;
+ virtual NPT_Result Close() = 0;
+ virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream) = 0;
+ virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_SerialPort
++---------------------------------------------------------------------*/
+class NPT_SerialPort : public NPT_SerialPortInterface
+{
+public:
+ // constructors and destructor
+ NPT_SerialPort(const char* name);
+ ~NPT_SerialPort() override { delete m_Delegate; }
+
+ // NPT_SerialPortInterface methods
+ NPT_Result Open(unsigned int speed,
+ NPT_SerialPortStopBits stop_bits = NPT_SERIAL_PORT_STOP_BITS_1,
+ NPT_SerialPortFlowControl flow_control = NPT_SERIAL_PORT_FLOW_CONTROL_NONE,
+ NPT_SerialPortParity parity = NPT_SERIAL_PORT_PARITY_NONE) override {
+ return m_Delegate->Open(speed, stop_bits, flow_control, parity);
+ }
+ NPT_Result Close() override {
+ return m_Delegate->Close();
+ }
+ NPT_Result GetInputStream(NPT_InputStreamReference& stream) override {
+ return m_Delegate->GetInputStream(stream);
+ }
+ NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) override {
+ return m_Delegate->GetOutputStream(stream);
+ }
+
+protected:
+ // members
+ NPT_SerialPortInterface* m_Delegate;
+};
+
+#endif // _NPT_SERIAL_PORT_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.cpp b/lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.cpp
new file mode 100644
index 0000000..ef2298b
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.cpp
@@ -0,0 +1,128 @@
+/*****************************************************************
+|
+| Neptune - Simple Message Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptSimpleMessageQueue.h"
+#include "NptDebug.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.message-queue")
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageCapsule
++---------------------------------------------------------------------*/
+struct NPT_SimpleMessageCapsule
+{
+ NPT_SimpleMessageCapsule(NPT_Message* message,
+ NPT_MessageHandler* handler);
+ ~NPT_SimpleMessageCapsule();
+ NPT_Message* m_Message;
+ NPT_MessageHandler* m_Handler;
+ NPT_MessageHandlerProxy* m_Proxy;
+};
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageCapsule::NPT_SimpleMessageCapsule
++---------------------------------------------------------------------*/
+NPT_SimpleMessageCapsule::NPT_SimpleMessageCapsule(NPT_Message* message,
+ NPT_MessageHandler* handler) :
+ m_Message(message),
+ m_Handler(handler),
+ m_Proxy(NPT_DYNAMIC_CAST(NPT_MessageHandlerProxy, handler))
+{
+ if (m_Proxy) m_Proxy->AddReference();
+}
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageCapsule::~NPT_SimpleMessageCapsule
++---------------------------------------------------------------------*/
+NPT_SimpleMessageCapsule::~NPT_SimpleMessageCapsule()
+{
+ if (m_Proxy) m_Proxy->Release();
+}
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageQueue::NPT_SimpleMessageQueue
++---------------------------------------------------------------------*/
+NPT_SimpleMessageQueue::NPT_SimpleMessageQueue()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageQueue::~NPT_SimpleMessageQueue
++---------------------------------------------------------------------*/
+NPT_SimpleMessageQueue::~NPT_SimpleMessageQueue()
+{
+ // empty the queue
+ // TBD
+}
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageQueue::QueueMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SimpleMessageQueue::QueueMessage(NPT_Message* message,
+ NPT_MessageHandler* handler)
+{
+ // push the message on the queue, with the handler reference
+ NPT_SimpleMessageCapsule* capsule = new NPT_SimpleMessageCapsule(message, handler);
+ NPT_Result result = m_Queue.Push(capsule);
+ if (NPT_FAILED(result)) delete capsule;
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageQueue::PumpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SimpleMessageQueue::PumpMessage(NPT_Timeout timeout /* = NPT_TIMEOUT_INFINITE */)
+{
+ NPT_SimpleMessageCapsule* capsule;
+
+ NPT_LOG_FINEST_1("popping message from queue, timeout=%d", timeout);
+ NPT_Result result = m_Queue.Pop(capsule, timeout);
+ if (NPT_SUCCEEDED(result) && capsule) {
+ if (capsule->m_Handler && capsule->m_Message) {
+ result = capsule->m_Handler->HandleMessage(capsule->m_Message);
+ }
+ delete capsule->m_Message;
+ delete capsule;
+ } else {
+ NPT_LOG_FINEST_1("m_Queue.Pop() returned %d", result);
+ }
+
+ return result;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.h b/lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.h
new file mode 100644
index 0000000..ca43e89
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSimpleMessageQueue.h
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+| Neptune - Simple Message Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SIMPLE_MESSAGE_QUEUE_H_
+#define _NPT_SIMPLE_MESSAGE_QUEUE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptThreads.h"
+#include "NptMessaging.h"
+#include "NptQueue.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+struct NPT_SimpleMessageCapsule;
+
+/*----------------------------------------------------------------------
+| NPT_SimpleMessageQueue
++---------------------------------------------------------------------*/
+class NPT_SimpleMessageQueue : public NPT_MessageQueue
+{
+ public:
+ // members
+ NPT_SimpleMessageQueue();
+ ~NPT_SimpleMessageQueue() override;
+
+ // NPT_MessageQueue methods
+ NPT_Result QueueMessage(NPT_Message* message,
+ NPT_MessageHandler* handler) override;
+ NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override;
+
+ private:
+ // members
+ NPT_Queue<NPT_SimpleMessageCapsule> m_Queue;
+};
+
+#endif // _NPT_SIMPLE_MESSAGE_QUEUE_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSockets.cpp b/lib/libUPnP/Neptune/Source/Core/NptSockets.cpp
new file mode 100644
index 0000000..7958f61
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSockets.cpp
@@ -0,0 +1,59 @@
+/*****************************************************************
+|
+| Neptune - Sockets
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptSockets.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+| NPT_SocketAddress::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_SocketAddress::ToString() const
+{
+ NPT_String s = m_IpAddress.ToString();
+ s += ':';
+ s += NPT_String::FromInteger(m_Port);
+ return s;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SocketAddress::operator==
++---------------------------------------------------------------------*/
+bool
+NPT_SocketAddress::operator==(const NPT_SocketAddress& other) const
+{
+ return (other.GetIpAddress().AsLong() == m_IpAddress.AsLong() &&
+ other.GetPort() == m_Port);
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSockets.h b/lib/libUPnP/Neptune/Source/Core/NptSockets.h
new file mode 100644
index 0000000..899e1bf
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSockets.h
@@ -0,0 +1,340 @@
+/*****************************************************************
+|
+| Neptune - Network Sockets
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SOCKETS_H_
+#define _NPT_SOCKETS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStreams.h"
+#include "NptStrings.h"
+#include "NptDataBuffer.h"
+#include "NptNetwork.h"
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_CONNECTION_RESET = NPT_ERROR_BASE_SOCKET - 0;
+const int NPT_ERROR_CONNECTION_ABORTED = NPT_ERROR_BASE_SOCKET - 1;
+const int NPT_ERROR_CONNECTION_REFUSED = NPT_ERROR_BASE_SOCKET - 2;
+const int NPT_ERROR_CONNECTION_FAILED = NPT_ERROR_BASE_SOCKET - 3;
+const int NPT_ERROR_HOST_UNKNOWN = NPT_ERROR_BASE_SOCKET - 4;
+const int NPT_ERROR_SOCKET_FAILED = NPT_ERROR_BASE_SOCKET - 5;
+const int NPT_ERROR_GETSOCKOPT_FAILED = NPT_ERROR_BASE_SOCKET - 6;
+const int NPT_ERROR_SETSOCKOPT_FAILED = NPT_ERROR_BASE_SOCKET - 7;
+const int NPT_ERROR_SOCKET_CONTROL_FAILED = NPT_ERROR_BASE_SOCKET - 8;
+const int NPT_ERROR_BIND_FAILED = NPT_ERROR_BASE_SOCKET - 9;
+const int NPT_ERROR_LISTEN_FAILED = NPT_ERROR_BASE_SOCKET - 10;
+const int NPT_ERROR_ACCEPT_FAILED = NPT_ERROR_BASE_SOCKET - 11;
+const int NPT_ERROR_ADDRESS_IN_USE = NPT_ERROR_BASE_SOCKET - 12;
+const int NPT_ERROR_NETWORK_DOWN = NPT_ERROR_BASE_SOCKET - 13;
+const int NPT_ERROR_NETWORK_UNREACHABLE = NPT_ERROR_BASE_SOCKET - 14;
+const int NPT_ERROR_HOST_UNREACHABLE = NPT_ERROR_BASE_SOCKET - 15;
+const int NPT_ERROR_NOT_CONNECTED = NPT_ERROR_BASE_SOCKET - 16;
+
+const unsigned int NPT_SOCKET_FLAG_CANCELLABLE = 1; // make the socket cancellable
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+class NPT_Socket;
+
+/*----------------------------------------------------------------------
+| NPT_SocketAddress
++---------------------------------------------------------------------*/
+class NPT_SocketAddress
+{
+public:
+ // constructors and destructor
+ NPT_SocketAddress() : m_Port(0) {}
+ NPT_SocketAddress(const NPT_IpAddress& address, NPT_IpPort port) :
+ m_IpAddress(address),
+ m_Port(port) {}
+
+ // methods
+ NPT_Result SetIpAddress(const NPT_IpAddress& address) {
+ m_IpAddress = address;
+ return NPT_SUCCESS;
+ }
+ const NPT_IpAddress& GetIpAddress() const {
+ return m_IpAddress;
+ }
+ NPT_Result SetPort(NPT_IpPort port) {
+ m_Port = port;
+ return NPT_SUCCESS;
+ }
+ NPT_IpPort GetPort() const {
+ return m_Port;
+ }
+ NPT_String ToString() const;
+
+ // operators
+ bool operator==(const NPT_SocketAddress& other) const;
+
+private:
+ // members
+ NPT_IpAddress m_IpAddress;
+ NPT_IpPort m_Port;
+};
+
+/*----------------------------------------------------------------------
+| NPT_SocketInfo
++---------------------------------------------------------------------*/
+typedef struct {
+ NPT_SocketAddress local_address;
+ NPT_SocketAddress remote_address;
+} NPT_SocketInfo;
+
+/*----------------------------------------------------------------------
+| NPT_SocketInterface
++---------------------------------------------------------------------*/
+class NPT_SocketInterface
+{
+ public:
+ virtual ~NPT_SocketInterface() {}
+
+ // interface methods
+ virtual NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true) = 0;
+ virtual NPT_Result Connect(const NPT_SocketAddress& address, NPT_Timeout timeout) = 0;
+ virtual NPT_Result WaitForConnection(NPT_Timeout timeout) = 0;
+ virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream) = 0;
+ virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) = 0;
+ virtual NPT_Result GetInfo(NPT_SocketInfo& info) = 0;
+ virtual NPT_Result SetReadTimeout(NPT_Timeout timeout) = 0;
+ virtual NPT_Result SetWriteTimeout(NPT_Timeout timeout) = 0;
+ virtual NPT_Result Cancel(bool shutdown=true) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_UdpSocketInterface
++---------------------------------------------------------------------*/
+class NPT_UdpSocketInterface
+{
+ public:
+ virtual ~NPT_UdpSocketInterface() {}
+
+ // methods
+ virtual NPT_Result Send(const NPT_DataBuffer& packet,
+ const NPT_SocketAddress* address = NULL) = 0;
+ virtual NPT_Result Receive(NPT_DataBuffer& packet,
+ NPT_SocketAddress* address = NULL) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_UdpMulticastSocketInterface
++---------------------------------------------------------------------*/
+class NPT_UdpMulticastSocketInterface
+{
+ public:
+ virtual ~NPT_UdpMulticastSocketInterface() {}
+
+ // methods
+ virtual NPT_Result JoinGroup(const NPT_IpAddress& group,
+ const NPT_IpAddress& iface) = 0;
+ virtual NPT_Result LeaveGroup(const NPT_IpAddress& group,
+ const NPT_IpAddress& iface) = 0;
+ virtual NPT_Result SetTimeToLive(unsigned char ttl) = 0;
+ virtual NPT_Result SetInterface(const NPT_IpAddress& iface) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TcpServerSocketInterface
++---------------------------------------------------------------------*/
+class NPT_TcpServerSocketInterface
+{
+ public:
+ virtual ~NPT_TcpServerSocketInterface() {}
+
+ // interface methods
+ virtual NPT_Result Listen(unsigned int max_clients) = 0;
+ virtual NPT_Result WaitForNewClient(NPT_Socket*& client,
+ NPT_Timeout timeout,
+ NPT_Flags flags) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Socket
++---------------------------------------------------------------------*/
+class NPT_Socket : public NPT_SocketInterface
+{
+public:
+ // static methods
+ static NPT_Result CancelBlockerSocket(NPT_Thread::ThreadId thread_id);
+
+ // constructor and destructor
+ explicit NPT_Socket(NPT_SocketInterface* delegate) : m_SocketDelegate(delegate) {}
+ ~NPT_Socket() override;
+
+ // delegate NPT_SocketInterface methods
+ NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true) override {
+ return m_SocketDelegate->Bind(address, reuse_address);
+ }
+ NPT_Result Connect(const NPT_SocketAddress& address,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
+ return m_SocketDelegate->Connect(address, timeout);
+ }
+ NPT_Result WaitForConnection(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
+ return m_SocketDelegate->WaitForConnection(timeout);
+ }
+ NPT_Result GetInputStream(NPT_InputStreamReference& stream) override {
+ return m_SocketDelegate->GetInputStream(stream);
+ }
+ NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) override {
+ return m_SocketDelegate->GetOutputStream(stream);
+ }
+ NPT_Result GetInfo(NPT_SocketInfo& info) override {
+ return m_SocketDelegate->GetInfo(info);
+ }
+ NPT_Result SetReadTimeout(NPT_Timeout timeout) override {
+ return m_SocketDelegate->SetReadTimeout(timeout);
+ }
+ NPT_Result SetWriteTimeout(NPT_Timeout timeout) override {
+ return m_SocketDelegate->SetWriteTimeout(timeout);
+ }
+ NPT_Result Cancel(bool shutdown=true) override {
+ return m_SocketDelegate->Cancel(shutdown);
+ }
+
+protected:
+ // constructor
+ NPT_Socket() : m_SocketDelegate(NULL) {}
+
+ // members
+ NPT_SocketInterface* m_SocketDelegate;
+};
+
+typedef NPT_Reference<NPT_Socket> NPT_SocketReference;
+
+/*----------------------------------------------------------------------
+| NPT_UdpSocket
++---------------------------------------------------------------------*/
+class NPT_UdpSocket : public NPT_Socket,
+ public NPT_UdpSocketInterface
+{
+ public:
+ // constructor and destructor
+ NPT_UdpSocket(NPT_Flags flags=0);
+ ~NPT_UdpSocket() override;
+
+ // delegate NPT_UdpSocketInterface methods
+ NPT_Result Send(const NPT_DataBuffer& packet,
+ const NPT_SocketAddress* address = NULL) override {
+ return m_UdpSocketDelegate->Send(packet, address);
+ }
+ NPT_Result Receive(NPT_DataBuffer& packet,
+ NPT_SocketAddress* address = NULL) override {
+ return m_UdpSocketDelegate->Receive(packet, address);
+ }
+
+protected:
+ // constructor
+ NPT_UdpSocket(NPT_UdpSocketInterface* delegate);
+
+ // members
+ NPT_UdpSocketInterface* m_UdpSocketDelegate;
+};
+
+/*----------------------------------------------------------------------
+| NPT_UdpMulticastSocket
++---------------------------------------------------------------------*/
+class NPT_UdpMulticastSocket : public NPT_UdpSocket,
+ public NPT_UdpMulticastSocketInterface
+{
+public:
+ // constructor and destructor
+ NPT_UdpMulticastSocket(NPT_Flags flags=0);
+ ~NPT_UdpMulticastSocket() override;
+
+ // delegate NPT_UdpMulticastSocketInterface methods
+ NPT_Result JoinGroup(const NPT_IpAddress& group,
+ const NPT_IpAddress& iface =
+ NPT_IpAddress::Any) override {
+ return m_UdpMulticastSocketDelegate->JoinGroup(group, iface);
+ }
+ NPT_Result LeaveGroup(const NPT_IpAddress& group,
+ const NPT_IpAddress& iface =
+ NPT_IpAddress::Any) override {
+ return m_UdpMulticastSocketDelegate->LeaveGroup(group, iface);
+ }
+ NPT_Result SetTimeToLive(unsigned char ttl) override {
+ return m_UdpMulticastSocketDelegate->SetTimeToLive(ttl);
+ }
+ NPT_Result SetInterface(const NPT_IpAddress& iface) override {
+ return m_UdpMulticastSocketDelegate->SetInterface(iface);
+ }
+
+protected:
+ // members
+ NPT_UdpMulticastSocketInterface* m_UdpMulticastSocketDelegate;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TcpClientSocket
++---------------------------------------------------------------------*/
+class NPT_TcpClientSocket : public NPT_Socket
+{
+public:
+ // constructors and destructor
+ NPT_TcpClientSocket(NPT_Flags flags=0);
+ ~NPT_TcpClientSocket() override;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TcpServerSocket
++---------------------------------------------------------------------*/
+class NPT_TcpServerSocket : public NPT_Socket,
+ public NPT_TcpServerSocketInterface
+{
+public:
+ // constructors and destructor
+ NPT_TcpServerSocket(NPT_Flags flags=0);
+ ~NPT_TcpServerSocket() override;
+
+ // delegate NPT_TcpServerSocketInterface methods
+ NPT_Result Listen(unsigned int max_clients) override {
+ return m_TcpServerSocketDelegate->Listen(max_clients);
+ }
+ NPT_Result WaitForNewClient(NPT_Socket*& client,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE,
+ NPT_Flags flags = 0) override {
+ return m_TcpServerSocketDelegate->WaitForNewClient(client, timeout, flags);
+ }
+
+protected:
+ // members
+ NPT_TcpServerSocketInterface* m_TcpServerSocketDelegate;
+};
+
+#endif // _NPT_SOCKETS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptStack.h b/lib/libUPnP/Neptune/Source/Core/NptStack.h
new file mode 100644
index 0000000..5078805
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptStack.h
@@ -0,0 +1,74 @@
+/*****************************************************************
+|
+| Neptune - Stack
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_STACK_H_
+#define _NPT_STACK_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptResults.h"
+#include "NptTypes.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+| NPT_Stack
++---------------------------------------------------------------------*/
+template <typename T>
+class NPT_Stack : public NPT_List<T>
+{
+public:
+ // methods
+ NPT_Result Push(const T& value) {
+ // NOTE: we must use the this-> accessor here because the standard
+ // requires it when the member to look up is in a parent template
+ return this->Add(value);
+ }
+
+ NPT_Result Peek(T& value) {
+ // NOTE: we must use the this-> accessor here because the standard
+ // requires it when the member to look up is in a parent template
+ if (this->m_ItemCount == 0) return NPT_ERROR_NO_SUCH_ITEM;
+ value = this->m_Tail->m_Data;
+ return NPT_SUCCESS;
+ }
+
+ NPT_Result Pop(T& value) {
+ // NOTE: we must use the this-> accessor here because the standard
+ // requires it when the member to look up is in a parent template
+ if (this->m_ItemCount == 0) return NPT_ERROR_NO_SUCH_ITEM;
+ typename NPT_List<T>::Iterator tail = this->GetLastItem();
+ value = *tail;
+ return this->Erase(tail);
+ }
+};
+
+#endif // _NPT_STACK_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptStreams.cpp b/lib/libUPnP/Neptune/Source/Core/NptStreams.cpp
new file mode 100644
index 0000000..79909fa
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptStreams.cpp
@@ -0,0 +1,724 @@
+/*****************************************************************
+|
+| Neptune - Byte Streams
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptStreams.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const NPT_Size NPT_INPUT_STREAM_LOAD_DEFAULT_READ_CHUNK = 4096;
+const NPT_LargeSize NPT_INPUT_STREAM_LOAD_MAX_SIZE = 0x40000000; // 1GB
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::Load(NPT_DataBuffer& buffer, NPT_Size max_read /* = 0 */)
+{
+ NPT_Result result;
+ NPT_LargeSize total_bytes_read;
+
+ // reset the buffer
+ buffer.SetDataSize(0);
+
+ // check the limits
+ if (max_read > NPT_INPUT_STREAM_LOAD_MAX_SIZE) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // try to get the stream size
+ NPT_LargeSize size;
+ if (NPT_SUCCEEDED(GetSize(size))) {
+ // make sure we don't read more than max_read
+ if (max_read && max_read < size) size = max_read;
+ if (size > NPT_INPUT_STREAM_LOAD_MAX_SIZE) {
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+ } else {
+ size = max_read;
+ }
+
+ // pre-allocate the buffer
+ if (size) NPT_CHECK(buffer.Reserve((NPT_Size)size));
+
+ // read the data from the file
+ total_bytes_read = 0;
+ do {
+ NPT_LargeSize available = 0;
+ NPT_LargeSize bytes_to_read;
+ NPT_Size bytes_read;
+ NPT_Byte* data;
+
+ // check if we know how much data is available
+ result = GetAvailable(available);
+ if (NPT_SUCCEEDED(result) && available) {
+ // we know how much is available
+ bytes_to_read = available;
+ } else {
+ bytes_to_read = NPT_INPUT_STREAM_LOAD_DEFAULT_READ_CHUNK;
+ }
+
+ // make sure we don't read more than what was asked
+ if (size != 0 && total_bytes_read+bytes_to_read>size) {
+ bytes_to_read = size-total_bytes_read;
+ }
+
+ // stop if we've read everything
+ if (bytes_to_read == 0) break;
+
+ // ensure that the buffer has enough space
+ if (total_bytes_read+bytes_to_read > NPT_INPUT_STREAM_LOAD_MAX_SIZE) {
+ buffer.SetBufferSize(0);
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+ NPT_CHECK(buffer.Reserve((NPT_Size)(total_bytes_read+bytes_to_read)));
+
+ // read the data
+ data = buffer.UseData()+total_bytes_read;
+ result = Read((void*)data, (NPT_Size)bytes_to_read, &bytes_read);
+ if (NPT_SUCCEEDED(result) && bytes_read != 0) {
+ total_bytes_read += bytes_read;
+ buffer.SetDataSize((NPT_Size)total_bytes_read);
+ }
+ } while(NPT_SUCCEEDED(result) && (size==0 || total_bytes_read < size));
+
+ if (result == NPT_ERROR_EOS) {
+ return NPT_SUCCESS;
+ } else {
+ return result;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::ReadFully
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadFully(void* buffer, NPT_Size bytes_to_read)
+{
+ // shortcut
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // read until failure
+ NPT_Size bytes_read;
+ while (bytes_to_read) {
+ NPT_Result result = Read(buffer, bytes_to_read, &bytes_read);
+ if (NPT_FAILED(result)) return result;
+ if (bytes_read == 0) return NPT_ERROR_INTERNAL;
+ NPT_ASSERT(bytes_read <= bytes_to_read);
+ bytes_to_read -= bytes_read;
+ buffer = (void*)(((NPT_Byte*)buffer)+bytes_read);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::ReadUI64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI64(NPT_UInt64& value)
+{
+ unsigned char buffer[8];
+
+ // read bytes from the stream
+ NPT_Result result;
+ result = ReadFully((void*)buffer, 8);
+ if (NPT_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = NPT_BytesToInt64Be(buffer);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::ReadUI32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI32(NPT_UInt32& value)
+{
+ unsigned char buffer[4];
+
+ // read bytes from the stream
+ NPT_Result result;
+ result = ReadFully((void*)buffer, 4);
+ if (NPT_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = NPT_BytesToInt32Be(buffer);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::ReadUI24
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI24(NPT_UInt32& value)
+{
+ unsigned char buffer[3];
+
+ // read bytes from the stream
+ NPT_Result result;
+ result = ReadFully((void*)buffer, 3);
+ if (NPT_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = NPT_BytesToInt24Be(buffer);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::ReadUI16
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI16(NPT_UInt16& value)
+{
+ unsigned char buffer[2];
+
+ // read bytes from the stream
+ NPT_Result result;
+ result = ReadFully((void*)buffer, 2);
+ if (NPT_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = NPT_BytesToInt16Be(buffer);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::ReadUI08
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI08(NPT_UInt8& value)
+{
+ unsigned char buffer[1];
+
+ // read bytes from the stream
+ NPT_Result result;
+ result = ReadFully((void*)buffer, 1);
+ if (NPT_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = buffer[0];
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_InputStream::Skip
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::Skip(NPT_Size count)
+{
+ // get the current location
+ NPT_Position position;
+ NPT_CHECK(Tell(position));
+
+ // seek ahead
+ return Seek(position+count);
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteFully
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteFully(const void* buffer, NPT_Size bytes_to_write)
+{
+ // shortcut
+ if (bytes_to_write == 0) return NPT_SUCCESS;
+
+ // write until failure
+ NPT_Size bytes_written;
+ while (bytes_to_write) {
+ NPT_Result result = Write(buffer, bytes_to_write, &bytes_written);
+ if (NPT_FAILED(result)) return result;
+ if (bytes_written == 0) return NPT_ERROR_INTERNAL;
+ NPT_ASSERT(bytes_written <= bytes_to_write);
+ bytes_to_write -= bytes_written;
+ buffer = (const void*)(((const NPT_Byte*)buffer)+bytes_written);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteString
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteString(const char* buffer)
+{
+ // shortcut
+ NPT_Size string_length;
+ if (buffer == NULL || (string_length = NPT_StringLength(buffer)) == 0) {
+ return NPT_SUCCESS;
+ }
+
+ // write the string
+ return WriteFully((const void*)buffer, string_length);
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteLine
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteLine(const char* buffer)
+{
+ NPT_CHECK(WriteString(buffer));
+ NPT_CHECK(WriteFully((const void*)"\r\n", 2));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteUI64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI64(NPT_UInt64 value)
+{
+ unsigned char buffer[8];
+
+ // convert value to bytes
+ NPT_BytesFromInt64Be(buffer, value);
+
+ // write bytes to the stream
+ return WriteFully((void*)buffer, 8);
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteUI32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI32(NPT_UInt32 value)
+{
+ unsigned char buffer[4];
+
+ // convert value to bytes
+ NPT_BytesFromInt32Be(buffer, value);
+
+ // write bytes to the stream
+ return WriteFully((void*)buffer, 4);
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteUI24
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI24(NPT_UInt32 value)
+{
+ unsigned char buffer[3];
+
+ // convert value to bytes
+ NPT_BytesFromInt24Be(buffer, value);
+
+ // write bytes to the stream
+ return WriteFully((void*)buffer, 3);
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteUI16
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI16(NPT_UInt16 value)
+{
+ unsigned char buffer[2];
+
+ // convert value to bytes
+ NPT_BytesFromInt16Be(buffer, value);
+
+ // write bytes to the stream
+ return WriteFully((void*)buffer, 2);
+}
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream::WriteUI08
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI08(NPT_UInt8 value)
+{
+ return WriteFully((void*)&value, 1);
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::NPT_MemoryStream
++---------------------------------------------------------------------*/
+NPT_MemoryStream::NPT_MemoryStream(NPT_Size initial_capacity) :
+ m_Buffer(initial_capacity),
+ m_ReadOffset(0),
+ m_WriteOffset(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::NPT_MemoryStream
++---------------------------------------------------------------------*/
+NPT_MemoryStream::NPT_MemoryStream(const void* data, NPT_Size size) :
+ m_Buffer(data, size),
+ m_ReadOffset(0),
+ m_WriteOffset(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MemoryStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ // check for shortcut
+ if (bytes_to_read == 0) {
+ if (bytes_read) *bytes_read = 0;
+ return NPT_SUCCESS;
+ }
+
+ // clip to what's available
+ NPT_Size available = m_Buffer.GetDataSize();
+ if (m_ReadOffset+bytes_to_read > available) {
+ bytes_to_read = available-m_ReadOffset;
+ }
+
+ // copy the data
+ if (bytes_to_read) {
+ NPT_CopyMemory(buffer, (void*)(((char*)m_Buffer.UseData())+m_ReadOffset), bytes_to_read);
+ m_ReadOffset += bytes_to_read;
+ }
+ if (bytes_read) *bytes_read = bytes_to_read;
+
+ return bytes_to_read?NPT_SUCCESS:NPT_ERROR_EOS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::InputSeek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MemoryStream::InputSeek(NPT_Position offset)
+{
+ if (offset > m_Buffer.GetDataSize()) {
+ return NPT_ERROR_OUT_OF_RANGE;
+ } else {
+ m_ReadOffset = (NPT_Size)offset;
+ return NPT_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MemoryStream::Write(const void* data,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written)
+{
+ NPT_CHECK(m_Buffer.Reserve(m_WriteOffset+bytes_to_write));
+
+ NPT_CopyMemory(m_Buffer.UseData()+m_WriteOffset, data, bytes_to_write);
+ m_WriteOffset += bytes_to_write;
+ if (m_WriteOffset > m_Buffer.GetDataSize()) {
+ m_Buffer.SetDataSize(m_WriteOffset);
+ }
+ if (bytes_written) *bytes_written = bytes_to_write;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::OutputSeek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MemoryStream::OutputSeek(NPT_Position offset)
+{
+ if (offset <= m_Buffer.GetDataSize()) {
+ m_WriteOffset = (NPT_Size)offset;
+ return NPT_SUCCESS;
+ } else {
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream::SetDataSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_MemoryStream::SetDataSize(NPT_Size size)
+{
+ // update data amount in buffer
+ NPT_CHECK(m_Buffer.SetDataSize(size));
+
+ // adjust the read and write offsets
+ if (m_ReadOffset > size) m_ReadOffset = size;
+ if (m_WriteOffset > size) m_WriteOffset = size;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_StreamToStreamCopy
++---------------------------------------------------------------------*/
+const unsigned int NPT_STREAM_COPY_BUFFER_SIZE = 65536; // copy 64k at a time
+NPT_Result
+NPT_StreamToStreamCopy(NPT_InputStream& from,
+ NPT_OutputStream& to,
+ NPT_Position offset /* = 0 */,
+ NPT_LargeSize size /* = 0, 0 means the entire stream */,
+ NPT_LargeSize* bytes_written /* = NULL */)
+{
+ // default values
+ if (bytes_written) *bytes_written = 0;
+
+ // seek into the input if required
+ if (offset) {
+ NPT_CHECK(from.Seek(offset));
+ }
+
+ // allocate a buffer for the transfer
+ NPT_LargeSize bytes_transfered = 0;
+ NPT_Byte* buffer = new NPT_Byte[NPT_STREAM_COPY_BUFFER_SIZE];
+ NPT_Result result = NPT_SUCCESS;
+ if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+
+ // copy until an error occurs or the end of stream is reached
+ for (;;) {
+ // read some data
+ NPT_Size bytes_to_read = NPT_STREAM_COPY_BUFFER_SIZE;
+ NPT_Size bytes_read = 0;
+ if (size) {
+ // a max size was specified
+ if (size-bytes_transfered < NPT_STREAM_COPY_BUFFER_SIZE) {
+ bytes_to_read = (NPT_Size)(size-bytes_transfered);
+ }
+ }
+ result = from.Read(buffer, bytes_to_read, &bytes_read);
+ if (NPT_FAILED(result)) {
+ if (result == NPT_ERROR_EOS) result = NPT_SUCCESS;
+ break;
+ }
+ if (bytes_read == 0) continue;
+
+ NPT_Size buffer_bytes_to_write = bytes_read;
+ NPT_Byte* buffer_bytes = (NPT_Byte*)buffer;
+ while (buffer_bytes_to_write) {
+ NPT_Size buffer_bytes_written = 0;
+ result = to.Write(buffer_bytes, buffer_bytes_to_write, &buffer_bytes_written);
+ if (NPT_FAILED(result)) goto end;
+ NPT_ASSERT(buffer_bytes_written <= buffer_bytes_to_write);
+ buffer_bytes_to_write -= buffer_bytes_written;
+ if (bytes_written) *bytes_written += buffer_bytes_written;
+ buffer_bytes += buffer_bytes_written;
+ }
+
+ // update the counts
+ if (size) {
+ bytes_transfered += bytes_read;
+ if (bytes_transfered >= size) break;
+ }
+ }
+
+end:
+ // free the buffer and return
+ delete[] buffer;
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_StringOutputStream::NPT_StringOutputStream
++---------------------------------------------------------------------*/
+NPT_StringOutputStream::NPT_StringOutputStream(NPT_Size size) :
+ m_String(new NPT_String),
+ m_StringIsOwned(true)
+{
+ m_String->Reserve(size);
+}
+
+
+/*----------------------------------------------------------------------
+| NPT_StringOutputStream::NPT_StringOutputStream
++---------------------------------------------------------------------*/
+NPT_StringOutputStream::NPT_StringOutputStream(NPT_String* storage) :
+ m_String(storage),
+ m_StringIsOwned(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_StringOutputStream::~NPT_StringOutputStream
++---------------------------------------------------------------------*/
+NPT_StringOutputStream::~NPT_StringOutputStream()
+{
+ if (m_StringIsOwned) delete m_String;
+}
+
+/*----------------------------------------------------------------------
+| NPT_StringOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StringOutputStream::Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written /* = NULL */)
+{
+ m_String->Append((const char*)buffer, bytes_to_write);
+ if (bytes_written) *bytes_written = bytes_to_write;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream::NPT_SubInputStream
++---------------------------------------------------------------------*/
+NPT_SubInputStream::NPT_SubInputStream(NPT_InputStreamReference& source,
+ NPT_Position start,
+ NPT_LargeSize size) :
+ m_Source(source),
+ m_Position(0),
+ m_Start(start),
+ m_Size(size)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SubInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ // default values
+ if (bytes_read) *bytes_read = 0;
+
+ // shortcut
+ if (bytes_to_read == 0) {
+ return NPT_SUCCESS;
+ }
+
+ // clamp to range
+ if (m_Position+bytes_to_read > m_Size) {
+ bytes_to_read = (NPT_Size)(m_Size - m_Position);
+ }
+
+ // check for end of substream
+ if (bytes_to_read == 0) {
+ return NPT_ERROR_EOS;
+ }
+
+ // seek inside the source
+ NPT_Result result;
+ result = m_Source->Seek(m_Start+m_Position);
+ if (NPT_FAILED(result)) {
+ return result;
+ }
+
+ // read from the source
+ NPT_Size source_bytes_read = 0;
+ result = m_Source->Read(buffer, bytes_to_read, &source_bytes_read);
+ if (NPT_SUCCEEDED(result)) {
+ m_Position += source_bytes_read;
+ if (bytes_read) *bytes_read = source_bytes_read;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SubInputStream::Seek(NPT_Position position)
+{
+ if (position == m_Position) return NPT_SUCCESS;
+ if (position > m_Size) return NPT_ERROR_OUT_OF_RANGE;
+ m_Position = position;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SubInputStream::Tell(NPT_Position& position)
+{
+ position = m_Position;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SubInputStream::GetSize(NPT_LargeSize& size)
+{
+ size = m_Size;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SubInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ available = m_Size-m_Position;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_NullOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NullOutputStream::Write(const void* /*buffer*/,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written /* = NULL */)
+{
+ if (bytes_written) *bytes_written = bytes_to_write;
+ return NPT_SUCCESS;
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptStreams.h b/lib/libUPnP/Neptune/Source/Core/NptStreams.h
new file mode 100644
index 0000000..bb22903
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptStreams.h
@@ -0,0 +1,321 @@
+/*****************************************************************
+|
+| Neptune - Byte Streams
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_STREAMS_H_
+#define _NPT_STREAMS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptReferences.h"
+#include "NptConstants.h"
+#include "NptResults.h"
+#include "NptDataBuffer.h"
+#include "NptStrings.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class NPT_String;
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_READ_FAILED = NPT_ERROR_BASE_IO - 0;
+const int NPT_ERROR_WRITE_FAILED = NPT_ERROR_BASE_IO - 1;
+const int NPT_ERROR_EOS = NPT_ERROR_BASE_IO - 2;
+
+/*----------------------------------------------------------------------
+| NPT_InputStream
++---------------------------------------------------------------------*/
+class NPT_InputStream
+{
+ public:
+ // constructor and destructor
+ virtual ~NPT_InputStream() {};
+
+ // methods
+ virtual NPT_Result Load(NPT_DataBuffer& buffer, NPT_Size max_read = 0);
+ virtual NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) = 0;
+ virtual NPT_Result ReadFully(void* buffer,
+ NPT_Size bytes_to_read);
+ virtual NPT_Result Seek(NPT_Position offset) = 0;
+ virtual NPT_Result Skip(NPT_Size offset);
+ virtual NPT_Result Tell(NPT_Position& offset) = 0;
+ virtual NPT_Result GetSize(NPT_LargeSize& size) = 0;
+ virtual NPT_Result GetAvailable(NPT_LargeSize& available) = 0;
+
+ // data access methods
+ NPT_Result ReadUI64(NPT_UInt64& value);
+ NPT_Result ReadUI32(NPT_UInt32& value);
+ NPT_Result ReadUI24(NPT_UInt32& value);
+ NPT_Result ReadUI16(NPT_UInt16& value);
+ NPT_Result ReadUI08(NPT_UInt8& value);
+};
+
+typedef NPT_Reference<NPT_InputStream> NPT_InputStreamReference;
+
+/*----------------------------------------------------------------------
+| NPT_OutputStream
++---------------------------------------------------------------------*/
+class NPT_OutputStream
+{
+public:
+ // constructor and destructor
+ virtual ~NPT_OutputStream() {};
+
+ // methods
+ virtual NPT_Result Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written = NULL) = 0;
+ virtual NPT_Result WriteFully(const void* buffer,
+ NPT_Size bytes_to_write);
+ virtual NPT_Result WriteString(const char* string_buffer);
+ virtual NPT_Result WriteLine(const char* line_buffer);
+ virtual NPT_Result Seek(NPT_Position offset) = 0;
+ virtual NPT_Result Tell(NPT_Position& offset) = 0;
+ virtual NPT_Result Flush() { return NPT_SUCCESS; }
+
+ // data access methods
+ NPT_Result WriteUI64(NPT_UInt64 value);
+ NPT_Result WriteUI32(NPT_UInt32 value);
+ NPT_Result WriteUI24(NPT_UInt32 value);
+ NPT_Result WriteUI16(NPT_UInt16 value);
+ NPT_Result WriteUI08(NPT_UInt8 value);
+};
+
+typedef NPT_Reference<NPT_OutputStream> NPT_OutputStreamReference;
+
+/*----------------------------------------------------------------------
+| NPT_StreamToStreamCopy
++---------------------------------------------------------------------*/
+NPT_Result NPT_StreamToStreamCopy(NPT_InputStream& from,
+ NPT_OutputStream& to,
+ NPT_Position offset = 0,
+ NPT_LargeSize size = 0, /* 0 means the entire stream */
+ NPT_LargeSize* bytes_written = NULL);
+
+/*----------------------------------------------------------------------
+| NPT_DelegatingInputStream
+|
+| Use this class as a base class if you need to inherit both from
+| NPT_InputStream and NPT_OutputStream which share the Seek and Tell
+| method. In this case, you override the base-specific version of
+| those methods, InputSeek, InputTell, instead of the Seek and Tell
+| methods.
++---------------------------------------------------------------------*/
+class NPT_DelegatingInputStream : public NPT_InputStream
+{
+public:
+ // NPT_InputStream methods
+ NPT_Result Seek(NPT_Position offset) override {
+ return InputSeek(offset);
+ }
+ NPT_Result Tell(NPT_Position& offset) override {
+ return InputTell(offset);
+ }
+
+private:
+ // methods
+ virtual NPT_Result InputSeek(NPT_Position offset) = 0;
+ virtual NPT_Result InputTell(NPT_Position& offset) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_DelegatingOutputStream
+|
+| Use this class as a base class if you need to inherit both from
+| NPT_InputStream and NPT_OutputStream which share the Seek and Tell
+| method. In this case, you override the base-specific version of
+| those methods, OutputSeek and OutputTell, instead of the Seek and
+| Tell methods.
++---------------------------------------------------------------------*/
+class NPT_DelegatingOutputStream : public NPT_OutputStream
+{
+public:
+ // NPT_OutputStream methods
+ NPT_Result Seek(NPT_Position offset) override {
+ return OutputSeek(offset);
+ }
+ NPT_Result Tell(NPT_Position& offset) override {
+ return OutputTell(offset);
+ }
+
+private:
+ // methods
+ virtual NPT_Result OutputSeek(NPT_Position offset) = 0;
+ virtual NPT_Result OutputTell(NPT_Position& offset) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_MemoryStream
++---------------------------------------------------------------------*/
+class NPT_MemoryStream :
+ public NPT_DelegatingInputStream,
+ public NPT_DelegatingOutputStream
+{
+public:
+ // constructor and destructor
+ NPT_MemoryStream(NPT_Size initial_capacity = 0);
+ NPT_MemoryStream(const void* data, NPT_Size size);
+ ~NPT_MemoryStream() override {}
+
+ // accessors
+ const NPT_DataBuffer& GetBuffer() const { return m_Buffer; }
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override {
+ size = m_Buffer.GetDataSize();
+ return NPT_SUCCESS;
+ }
+ NPT_Result GetAvailable(NPT_LargeSize& available) override {
+ available = (NPT_LargeSize)m_Buffer.GetDataSize()-m_ReadOffset;
+ return NPT_SUCCESS;
+ }
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written = NULL) override;
+
+ // methods delegated to m_Buffer
+ const NPT_Byte* GetData() const { return m_Buffer.GetData(); }
+ NPT_Byte* UseData() { return m_Buffer.UseData(); }
+ NPT_Size GetDataSize() const { return m_Buffer.GetDataSize(); }
+ NPT_Size GetBufferSize() const { return m_Buffer.GetBufferSize();}
+
+ // methods
+ NPT_Result SetDataSize(NPT_Size size);
+
+private:
+ // NPT_DelegatingInputStream methods
+ NPT_Result InputSeek(NPT_Position offset) override;
+ NPT_Result InputTell(NPT_Position& offset) override {
+ offset = m_ReadOffset;
+ return NPT_SUCCESS;
+ }
+
+ // NPT_DelegatingOutputStream methods
+ NPT_Result OutputSeek(NPT_Position offset) override;
+ NPT_Result OutputTell(NPT_Position& offset) override {
+ offset = m_WriteOffset;
+ return NPT_SUCCESS;
+ }
+
+protected:
+ // members
+ NPT_DataBuffer m_Buffer;
+ NPT_Size m_ReadOffset;
+ NPT_Size m_WriteOffset;
+};
+
+typedef NPT_Reference<NPT_MemoryStream> NPT_MemoryStreamReference;
+
+/*----------------------------------------------------------------------
+| NPT_StringOutputStream
++---------------------------------------------------------------------*/
+class NPT_StringOutputStream : public NPT_OutputStream
+{
+public:
+ // methods
+ NPT_StringOutputStream(NPT_Size size = 4096);
+ NPT_StringOutputStream(NPT_String* storage);
+ ~NPT_StringOutputStream() override ;
+
+ const NPT_String& GetString() const { return *m_String; }
+ NPT_Result Reset() { if (m_String) m_String->SetLength(0); return NPT_SUCCESS; }
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written = NULL) override;
+
+ NPT_Result Seek(NPT_Position /*offset*/) override { return NPT_ERROR_NOT_SUPPORTED; }
+ NPT_Result Tell(NPT_Position& offset) override { offset = m_String->GetLength(); return NPT_SUCCESS; }
+
+protected:
+ NPT_String* m_String;
+ bool m_StringIsOwned;
+};
+
+typedef NPT_Reference<NPT_StringOutputStream> NPT_StringOutputStreamReference;
+
+/*----------------------------------------------------------------------
+| NPT_SubInputStream
++---------------------------------------------------------------------*/
+class NPT_SubInputStream : public NPT_InputStream
+{
+public:
+ // constructor and destructor
+ NPT_SubInputStream(NPT_InputStreamReference& source,
+ NPT_Position start,
+ NPT_LargeSize size);
+
+ // methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result Seek(NPT_Position offset) override;
+ NPT_Result Tell(NPT_Position& offset) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override;
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+private:
+ NPT_InputStreamReference m_Source;
+ NPT_Position m_Position;
+ NPT_Position m_Start;
+ NPT_LargeSize m_Size;
+};
+
+/*----------------------------------------------------------------------
+| NPT_NullOutputStream
++---------------------------------------------------------------------*/
+class NPT_NullOutputStream : public NPT_OutputStream
+{
+public:
+ // methods
+ NPT_NullOutputStream() {}
+ ~NPT_NullOutputStream() override {}
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written = NULL) override;
+
+ NPT_Result Seek(NPT_Position /*offset*/) override { return NPT_ERROR_NOT_SUPPORTED; }
+ NPT_Result Tell(NPT_Position& /*offset*/) override { return NPT_ERROR_NOT_SUPPORTED; }
+};
+
+typedef NPT_Reference<NPT_NullOutputStream> NPT_NullOutputStreamReference;
+
+#endif // _NPT_STREAMS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptStrings.cpp b/lib/libUPnP/Neptune/Source/Core/NptStrings.cpp
new file mode 100644
index 0000000..819d9a2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptStrings.cpp
@@ -0,0 +1,1205 @@
+/*****************************************************************
+|
+| Neptune - String Objects
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptResults.h"
+#include "NptUtils.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_STRINGS_WHITESPACE_CHARS "\r\n\t "
+
+const unsigned int NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE = 256;
+const unsigned int NPT_STRING_FORMAT_BUFFER_MAX_SIZE = 0x80000; // 512k
+
+/*----------------------------------------------------------------------
+| helpers
++---------------------------------------------------------------------*/
+inline char NPT_Uppercase(char x) {
+ return (x >= 'a' && x <= 'z') ? x&0xdf : x;
+}
+
+inline char NPT_Lowercase(char x) {
+ return (x >= 'A' && x <= 'Z') ? x^32 : x;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::EmptyString
++---------------------------------------------------------------------*/
+char NPT_String::EmptyString = '\0';
+
+/*----------------------------------------------------------------------
+| NPT_String::FromInteger
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::FromInteger(NPT_Int64 value)
+{
+ char str[32];
+ char* c = &str[31];
+ *c-- = '\0';
+
+ // handle the sign
+ bool negative = false;
+ if (value < 0) {
+ negative = true;
+ value = -value;
+ }
+
+ // process the digits
+ do {
+ int digit = (int)(value%10);
+ *c-- = '0'+digit;
+ value /= 10;
+ } while(value);
+
+ if (negative) {
+ *c = '-';
+ } else {
+ ++c;
+ }
+
+ return NPT_String(c);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::FromIntegerU
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::FromIntegerU(NPT_UInt64 value)
+{
+ char str[32];
+ char* c = &str[31];
+ *c = '\0';
+
+ // process the digits
+ do {
+ int digit = (int)(value%10);
+ *--c = '0'+digit;
+ value /= 10;
+ } while(value);
+
+ return NPT_String(c);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Format
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::Format(const char* format, ...)
+{
+ NPT_String result;
+ NPT_Size buffer_size = NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE; // default value
+
+ va_list args;
+
+ for(;;) {
+ /* try to format (it might not fit) */
+ result.Reserve(buffer_size);
+ char* buffer = result.UseChars();
+ va_start(args, format);
+ int f_result = NPT_FormatStringVN(buffer, buffer_size, format, args);
+ va_end(args);
+ if (f_result >= (int)(buffer_size)) f_result = -1;
+ if (f_result >= 0) {
+ result.SetLength(f_result);
+ break;
+ }
+
+ /* the buffer was too small, try something bigger */
+ /* (we don't trust the return value of NPT_FormatStringVN */
+ /* for the actual size needed) */
+ buffer_size *= 2;
+ if (buffer_size > NPT_STRING_FORMAT_BUFFER_MAX_SIZE) break;
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const char* str)
+{
+ if (str == NULL) {
+ m_Chars = NULL;
+ } else {
+ m_Chars = Buffer::Create(str);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const char* str, NPT_Size length)
+{
+ if (str == NULL || length == 0) {
+ m_Chars = NULL;
+ } else {
+ for (unsigned int i=0; i<length-1; i++) {
+ if (str[i] == '\0') {
+ if (i == 0) {
+ m_Chars = NULL;
+ return;
+ }
+ length = i;
+ break;
+ }
+ }
+ m_Chars = Buffer::Create(str, length);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const NPT_String& str)
+{
+ if (str.GetLength() == 0) {
+ m_Chars = NULL;
+ } else {
+ m_Chars = Buffer::Create(str.GetChars(), str.GetLength());
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(char c, NPT_Cardinal repeat)
+{
+ if (repeat != 0) {
+ m_Chars = Buffer::Create(c, repeat);
+ } else {
+ m_Chars = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::SetLength
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::SetLength(NPT_Size length, bool pad)
+{
+ // special case for 0
+ if (length == 0) {
+ Reset();
+ return NPT_SUCCESS;
+ }
+
+ // reserve the space
+ Reserve(length);
+
+ // pad with spaces if necessary
+ char* chars = UseChars();
+ if (pad) {
+ unsigned int current_length = GetLength();
+ if (length > current_length) {
+ unsigned int pad_length = length-current_length;
+ NPT_SetMemory(chars+current_length, ' ', pad_length);
+ }
+ }
+
+ // update the length and terminate the buffer
+ GetBuffer()->SetLength(length);
+ chars[length] = '\0';
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::PrepareToWrite
++---------------------------------------------------------------------*/
+inline char*
+NPT_String::PrepareToWrite(NPT_Size length)
+{
+ NPT_ASSERT(length != 0);
+ if (m_Chars == NULL || GetBuffer()->GetAllocated() < length) {
+ // the buffer is too small, we need to allocate a new one.
+ NPT_Size needed = length;
+ if (m_Chars != NULL) {
+ NPT_Size grow = GetBuffer()->GetAllocated()*2;
+ if (grow > length) needed = grow;
+ delete GetBuffer();
+ }
+ m_Chars = Buffer::Create(needed);
+ }
+ GetBuffer()->SetLength(length);
+ return m_Chars;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Reserve
++---------------------------------------------------------------------*/
+void
+NPT_String::Reserve(NPT_Size allocate)
+{
+ if (m_Chars == NULL || GetBuffer()->GetAllocated() < allocate) {
+ // the buffer is too small, we need to allocate a new one.
+ NPT_Size needed = allocate;
+ if (m_Chars != NULL) {
+ NPT_Size grow = GetBuffer()->GetAllocated()*2;
+ if (grow > allocate) needed = grow;
+ }
+ NPT_Size length = GetLength();
+ char* copy = Buffer::Create(needed, length);
+ if (m_Chars != NULL) {
+ CopyString(copy, m_Chars);
+ delete GetBuffer();
+ } else {
+ copy[0] = '\0';
+ }
+ m_Chars = copy;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Assign
++---------------------------------------------------------------------*/
+void
+NPT_String::Assign(const char* str, NPT_Size length)
+{
+ if (str == NULL || length == 0) {
+ Reset();
+ } else {
+ for (unsigned int i=0; i<length-1; i++) {
+ if (str[i] == '\0') {
+ if (i == 0) {
+ Reset();
+ return;
+ } else {
+ length = i;
+ break;
+ }
+ }
+ }
+ PrepareToWrite(length);
+ CopyBuffer(m_Chars, str, length);
+ m_Chars[length] = '\0';
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::operator=
++---------------------------------------------------------------------*/
+NPT_String&
+NPT_String::operator=(const char* str)
+{
+ if (str == NULL) {
+ Reset();
+ } else {
+ NPT_Size length = StringLength(str);
+ if (length == 0) {
+ Reset();
+ } else {
+ CopyString(PrepareToWrite(length), str);
+ }
+ }
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::operator=
++---------------------------------------------------------------------*/
+NPT_String&
+NPT_String::operator=(const NPT_String& str)
+{
+ // do nothing if we're assigning to ourselves
+ if (this != &str) {
+ Assign(str.GetChars(), str.GetLength());
+ }
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::GetHash32
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_String::GetHash32() const
+{
+ return NPT_Fnv1aHashStr32(GetChars());
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::GetHash64
++---------------------------------------------------------------------*/
+NPT_UInt64
+NPT_String::GetHash64() const
+{
+ return NPT_Fnv1aHashStr64(GetChars());
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Append
++---------------------------------------------------------------------*/
+void
+NPT_String::Append(const char* str, NPT_Size length)
+{
+ // shortcut
+ if (str == NULL || length == 0) return;
+
+ // compute the new length
+ NPT_Size old_length = GetLength();
+ NPT_Size new_length = old_length + length;
+
+ // allocate enough space
+ Reserve(new_length);
+
+ // append the new string at the end of the current one
+ CopyBuffer(m_Chars+old_length, str, length);
+ m_Chars[new_length] = '\0';
+
+ // update the length
+ GetBuffer()->SetLength(new_length);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Compare
++---------------------------------------------------------------------*/
+int
+NPT_String::Compare(const char *s, bool ignore_case) const
+{
+ return NPT_String::Compare(GetChars(), s, ignore_case);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Compare
++---------------------------------------------------------------------*/
+int
+NPT_String::Compare(const char *s1, const char *s2, bool ignore_case)
+{
+ const char *r1 = s1;
+ const char *r2 = s2;
+
+ if (ignore_case) {
+ while (NPT_Uppercase(*r1) == NPT_Uppercase(*r2)) {
+ if (*r1++ == '\0') {
+ return 0;
+ }
+ r2++;
+ }
+ return NPT_Uppercase(*r1) - NPT_Uppercase(*r2);
+ } else {
+ while (*r1 == *r2) {
+ if (*r1++ == '\0') {
+ return 0;
+ }
+ r2++;
+ }
+ return (*r1 - *r2);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::CompareN
++---------------------------------------------------------------------*/
+int
+NPT_String::CompareN(const char *s, NPT_Size count, bool ignore_case) const
+{
+ return NPT_String::CompareN(GetChars(), s, count, ignore_case);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::CompareN
++---------------------------------------------------------------------*/
+int
+NPT_String::CompareN(const char* s1, const char *s2, NPT_Size count, bool ignore_case)
+{
+ const char* me = s1;
+
+ if (ignore_case) {
+ for (unsigned int i=0; i<count; i++) {
+ if (NPT_Uppercase(me[i]) != NPT_Uppercase(s2[i])) {
+ return NPT_Uppercase(me[i]) - NPT_Uppercase(s2[i]);
+ }
+ }
+ return 0;
+ } else {
+ for (unsigned int i=0; i<count; i++) {
+ if (me[i] != s2[i]) {
+ return (me[i] - s2[i]);
+ }
+ }
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Split
++---------------------------------------------------------------------*/
+NPT_List<NPT_String>
+NPT_String::Split(const char* separator) const
+{
+ NPT_List<NPT_String> result;
+ NPT_Size separator_length = NPT_StringLength(separator);
+
+ // sepcial case for empty separators
+ if (separator_length == 0) {
+ result.Add(*this);
+ return result;
+ }
+
+ int current = 0;
+ int next;
+ do {
+ next = Find(separator, current);
+ unsigned int end = (next>=0?(unsigned int)next:GetLength());
+ result.Add(SubString(current, end-current));
+ current = next+separator_length;
+ } while (next >= 0);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::SplitAny
++---------------------------------------------------------------------*/
+NPT_Array<NPT_String>
+NPT_String::SplitAny(const char* separator) const
+{
+ NPT_Array<NPT_String> result((GetLength()>>1)+1);
+
+ // sepcial case for empty separators
+ if (NPT_StringLength(separator) == 0) {
+ result.Add(*this);
+ return result;
+ }
+
+ int current = 0;
+ int next;
+ do {
+ next = FindAny(separator, current);
+ unsigned int end = (next>=0?(unsigned int)next:GetLength());
+ result.Add(SubString(current, end-current));
+ current = next+1;
+ } while (next >= 0);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Join
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::Join(NPT_List<NPT_String>& args, const char* separator)
+{
+ NPT_String output;
+ NPT_List<NPT_String>::Iterator arg = args.GetFirstItem();
+ while (arg) {
+ output += *arg;
+ if (++arg) output += separator;
+ }
+
+ return output;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::SubString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const
+{
+ if (first >= GetLength()) {
+ first = GetLength();
+ length = 0;
+ } else if (first+length >= GetLength()) {
+ length = GetLength()-first;
+ }
+ return NPT_String(GetChars()+first, length);
+}
+
+/*----------------------------------------------------------------------
+| NPT_StringStartsWith
+|
+| returns:
+| 1 if str starts with sub,
+| 0 if str is large enough but does not start with sub
+| -1 if str is too short to start with sub
++---------------------------------------------------------------------*/
+static inline int
+NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case)
+{
+ if (ignore_case) {
+ while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) {
+ if (*str++ == '\0') {
+ return 1;
+ }
+ sub++;
+ }
+ } else {
+ while (*str == *sub) {
+ if (*str++ == '\0') {
+ return 1;
+ }
+ sub++;
+ }
+ }
+ return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::StartsWith
++---------------------------------------------------------------------*/
+bool
+NPT_String::StartsWith(const char *s, bool ignore_case) const
+{
+ if (s == NULL) return false;
+ return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::EndsWith
++---------------------------------------------------------------------*/
+bool
+NPT_String::EndsWith(const char *s, bool ignore_case) const
+{
+ if (s == NULL) return false;
+ NPT_Size str_length = NPT_StringLength(s);
+ if (str_length > GetLength()) return false;
+ return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Find
++---------------------------------------------------------------------*/
+int
+NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const
+{
+ // check args
+ if (str == NULL || start >= GetLength()) return -1;
+
+ // skip to start position
+ const char* src = m_Chars + start;
+
+ // look for a substring
+ while (*src) {
+ int cmp = NPT_StringStartsWith(src, str, ignore_case);
+ switch (cmp) {
+ case -1:
+ // ref is too short, abort
+ return -1;
+ case 1:
+ // match
+ return (int)(src-m_Chars);
+ }
+ src++;
+ }
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Find
++---------------------------------------------------------------------*/
+int
+NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const
+{
+ // check args
+ if (start >= GetLength()) return -1;
+
+ // skip to start position
+ const char* src = m_Chars + start;
+
+ // look for the character
+ if (ignore_case) {
+ while (*src) {
+ if (NPT_Uppercase(*src) == NPT_Uppercase(c)) {
+ return (int)(src-m_Chars);
+ }
+ src++;
+ }
+ } else {
+ while (*src) {
+ if (*src == c) return (int)(src-m_Chars);
+ src++;
+ }
+ }
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::FindAny
++---------------------------------------------------------------------*/
+int
+NPT_String::FindAny(const char* s, NPT_Ordinal start, bool ignore_case) const
+{
+ // check args
+ if (start >= GetLength()) return -1;
+
+ // skip to start position
+ const char* src = m_Chars + start;
+
+ // look for the character
+ if (ignore_case) {
+ while (*src) {
+ for (NPT_Size i=0; i<NPT_StringLength(s); i++) {
+ if (NPT_Uppercase(*src) == NPT_Uppercase(s[i])) {
+ return (int)(src-m_Chars);
+ }
+ }
+ src++;
+ }
+ } else {
+ while (*src) {
+ for (NPT_Size i=0; i<NPT_StringLength(s); i++) {
+ if (*src == s[i]) return (int)(src-m_Chars);
+ }
+ src++;
+ }
+ }
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ReverseFind
++---------------------------------------------------------------------*/
+int
+NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const
+{
+ // check args
+ if (str == NULL || *str == '\0') return -1;
+
+ // look for a substring
+ NPT_Size my_length = GetLength();
+ NPT_Size str_length = NPT_StringLength(str);
+ int i=my_length-start-str_length;
+ const char* src = GetChars();
+ if (i<0) return -1;
+ for (;i>=0; i--) {
+ int cmp = NPT_StringStartsWith(src+i, str, ignore_case);
+ if (cmp == 1) {
+ // match
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ReverseFind
++---------------------------------------------------------------------*/
+int
+NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const
+{
+ // check args
+ NPT_Size length = GetLength();
+ int i = length-start-1;
+ if (i < 0) return -1;
+
+ // look for the character
+ const char* src = GetChars();
+ if (ignore_case) {
+ for (;i>=0;i--) {
+ if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) {
+ return i;
+ }
+ }
+ } else {
+ for (;i>=0;i--) {
+ if (src[i] == c) return i;
+ }
+ }
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::MakeLowercase
++---------------------------------------------------------------------*/
+void
+NPT_String::MakeLowercase()
+{
+ // the source is the current buffer
+ const char* src = GetChars();
+
+ // convert all the characters of the existing buffer
+ char* dst = const_cast<char*>(src);
+ while (*dst != '\0') {
+ *dst = NPT_Lowercase(*dst);
+ dst++;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::MakeUppercase
++---------------------------------------------------------------------*/
+void
+NPT_String::MakeUppercase()
+{
+ // the source is the current buffer
+ const char* src = GetChars();
+
+ // convert all the characters of the existing buffer
+ char* dst = const_cast<char*>(src);
+ while (*dst != '\0') {
+ *dst = NPT_Uppercase(*dst);
+ dst++;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToLowercase
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::ToLowercase() const
+{
+ NPT_String result(*this);
+ result.MakeLowercase();
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToUppercase
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::ToUppercase() const
+{
+ NPT_String result(*this);
+ result.MakeUppercase();
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Replace
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Replace(char a, char b)
+{
+ // check args
+ if (m_Chars == NULL || a == '\0' || b == '\0') return *this;
+
+ // we are going to modify the characters
+ char* src = m_Chars;
+
+ // process the buffer in place
+ while (*src) {
+ if (*src == a) *src = b;
+ src++;
+ }
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Replace
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Replace(char a, const char* str)
+{
+ // check args
+ if (m_Chars == NULL || a == '\0' || str == NULL || str[0] == '\0') return *this;
+
+ // optimization
+ if (NPT_StringLength(str) == 1) return Replace(a, str[0]);
+
+ // we are going to create a new string
+ NPT_String dst;
+ char* src = m_Chars;
+
+ // reserve at least as much as input
+ dst.Reserve(GetLength());
+
+ // process the buffer
+ while (*src) {
+ if (*src == a) {
+ dst += str;
+ } else {
+ dst += *src;
+ }
+ src++;
+ }
+
+ Assign(dst.GetChars(), dst.GetLength());
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Replace
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Replace(const char* before, const char* after)
+{
+ NPT_Size size_before = NPT_StringLength(before);
+ NPT_Size size_after = NPT_StringLength(after);
+ int index = Find(before);
+ while (index != NPT_STRING_SEARCH_FAILED) {
+ Erase(index, size_before);
+ Insert(after, index);
+ index = Find(before, index+size_after);
+ }
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Insert
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Insert(const char* str, NPT_Ordinal where)
+{
+ // check args
+ if (str == NULL || where > GetLength()) return *this;
+
+ // measure the string to insert
+ NPT_Size str_length = StringLength(str);
+ if (str_length == 0) return *this;
+
+ // compute the size of the new string
+ NPT_Size old_length = GetLength();
+ NPT_Size new_length = str_length + GetLength();
+
+ // prepare to write the new string
+ char* src = m_Chars;
+ char* nst = Buffer::Create(new_length, new_length);
+ char* dst = nst;
+
+ // copy the beginning of the old string
+ if (where > 0) {
+ CopyBuffer(dst, src, where);
+ src += where;
+ dst += where;
+ }
+
+ // copy the inserted string
+ CopyString(dst, str);
+ dst += str_length;
+
+ // copy the end of the old string
+ if (old_length > where) {
+ CopyString(dst, src);
+ }
+
+ // use the new string
+ if (m_Chars) delete GetBuffer();
+ m_Chars = nst;
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Erase
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */)
+{
+ // check bounds
+ NPT_Size length = GetLength();
+ if (start+count > length) {
+ if (start >= length) return *this;
+ count = length-start;
+ }
+ if (count == 0) return *this;
+
+ CopyString(m_Chars+start, m_Chars+start+count);
+ GetBuffer()->SetLength(length-count);
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger(int& value, bool relaxed) const
+{
+ return NPT_ParseInteger(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger(unsigned int& value, bool relaxed) const
+{
+ return NPT_ParseInteger(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger(long& value, bool relaxed) const
+{
+ return NPT_ParseInteger(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger(unsigned long& value, bool relaxed) const
+{
+ return NPT_ParseInteger(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger32(NPT_Int32& value, bool relaxed) const
+{
+ return NPT_ParseInteger32(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger32(NPT_UInt32& value, bool relaxed) const
+{
+ return NPT_ParseInteger32(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger64(NPT_Int64& value, bool relaxed) const
+{
+ return NPT_ParseInteger64(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToInteger64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToInteger64(NPT_UInt64& value, bool relaxed) const
+{
+ return NPT_ParseInteger64(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::ToFloat
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::ToFloat(float& value, bool relaxed) const
+{
+ return NPT_ParseFloat(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::TrimLeft
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::TrimLeft()
+{
+ return TrimLeft(NPT_STRINGS_WHITESPACE_CHARS);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::TrimLeft
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::TrimLeft(char c)
+{
+ char s[2] = {c, 0};
+ return TrimLeft((const char*)s);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::TrimLeft
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::TrimLeft(const char* chars)
+{
+ if (m_Chars == NULL) return *this;
+ const char* s = m_Chars;
+ while (char c = *s) {
+ const char* x = chars;
+ while (*x) {
+ if (*x == c) break;
+ x++;
+ }
+ if (*x == 0) break; // not found
+ s++;
+ }
+ if (s == m_Chars) {
+ // nothing was trimmed
+ return *this;
+ }
+
+ // shift chars to the left
+ char* d = m_Chars;
+ GetBuffer()->SetLength(GetLength()-(NPT_Size)(s-d));
+ while ((*d++ = *s++)) {};
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::TrimRight
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::TrimRight()
+{
+ return TrimRight(NPT_STRINGS_WHITESPACE_CHARS);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::TrimRight
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::TrimRight(char c)
+{
+ char s[2] = {c, 0};
+ return TrimRight((const char*)s);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::TrimRight
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::TrimRight(const char* chars)
+{
+ if (m_Chars == NULL || m_Chars[0] == '\0') return *this;
+ char* tail = m_Chars+GetLength()-1;
+ char* s = tail;
+ while (s != m_Chars-1) {
+ const char* x = chars;
+ while (*x) {
+ if (*x == *s) {
+ *s = '\0';
+ break;
+ }
+ x++;
+ }
+ if (*x == 0) break; // not found
+ s--;
+ }
+ if (s == tail) {
+ // nothing was trimmed
+ return *this;
+ }
+ GetBuffer()->SetLength(1+(int)(s-m_Chars));
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Trim
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Trim()
+{
+ TrimLeft();
+ return TrimRight();
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Trim
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Trim(char c)
+{
+ char s[2] = {c, 0};
+ TrimLeft((const char*)s);
+ return TrimRight((const char*)s);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::Trim
++---------------------------------------------------------------------*/
+const NPT_String&
+NPT_String::Trim(const char* chars)
+{
+ TrimLeft(chars);
+ return TrimRight(chars);
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::operator+(const NPT_String&, const char*)
++---------------------------------------------------------------------*/
+NPT_String
+operator+(const NPT_String& s1, const char* s2)
+{
+ // shortcut
+ if (s2 == NULL) return NPT_String(s1);
+
+ // measure strings
+ NPT_Size s1_length = s1.GetLength();
+ NPT_Size s2_length = NPT_String::StringLength(s2);
+
+ // allocate space for the new string
+ NPT_String result;
+ char* start = result.PrepareToWrite(s1_length+s2_length);
+
+ // concatenate the two strings into the result
+ NPT_String::CopyBuffer(start, s1, s1_length);
+ NPT_String::CopyString(start+s1_length, s2);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::operator+(const NPT_String& , const char*)
++---------------------------------------------------------------------*/
+NPT_String
+operator+(const char* s1, const NPT_String& s2)
+{
+ // shortcut
+ if (s1 == NULL) return NPT_String(s2);
+
+ // measure strings
+ NPT_Size s1_length = NPT_String::StringLength(s1);
+ NPT_Size s2_length = s2.GetLength();
+
+ // allocate space for the new string
+ NPT_String result;
+ char* start = result.PrepareToWrite(s1_length+s2_length);
+
+ // concatenate the two strings into the result
+ NPT_String::CopyBuffer(start, s1, s1_length);
+ NPT_String::CopyString(start+s1_length, s2.GetChars());
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_String::operator+(const NPT_String& , char)
++---------------------------------------------------------------------*/
+NPT_String
+operator+(const NPT_String& s1, char c)
+{
+ // allocate space for the new string
+ NPT_String result;
+ result.Reserve(s1.GetLength()+1);
+
+ // append
+ result = s1;
+ result += c;
+
+ return result;
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptStrings.h b/lib/libUPnP/Neptune/Source/Core/NptStrings.h
new file mode 100644
index 0000000..c445b33
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptStrings.h
@@ -0,0 +1,358 @@
+/*****************************************************************
+|
+| Neptune - String Objects
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_STRINGS_H_
+#define _NPT_STRINGS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#if defined(NPT_CONFIG_HAVE_NEW_H)
+#include <new>
+#endif
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptList.h"
+#include "NptArray.h"
+#include "NptDebug.h"
+#include "NptHash.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_STRING_SEARCH_FAILED = -1;
+
+/*----------------------------------------------------------------------
+| NPT_String
++---------------------------------------------------------------------*/
+class NPT_String
+{
+public:
+ // factories
+ static NPT_String FromInteger(NPT_Int64 value);
+ static NPT_String FromIntegerU(NPT_UInt64 value);
+ static NPT_String Format(const char* format, ...);
+
+ // constructors
+ NPT_String(const NPT_String& str);
+ NPT_String(const char* str);
+ NPT_String(const char* str, NPT_Size length);
+ NPT_String(char c, NPT_Cardinal repeat = 1);
+ NPT_String() : m_Chars(NULL) {}
+ ~NPT_String() { if (m_Chars) GetBuffer()->Destroy(); }
+
+ // string info and manipulations
+ bool IsEmpty() const { return m_Chars == NULL || GetBuffer()->GetLength() == 0; }
+ NPT_Size GetLength() const { return m_Chars ? GetBuffer()->GetLength() : 0; }
+ NPT_Size GetCapacity() const { return m_Chars ? GetBuffer()->GetAllocated() : 0; }
+ NPT_Result SetLength(NPT_Size length, bool pad = false);
+ void Assign(const char* chars, NPT_Size size);
+ void Append(const char* chars, NPT_Size size);
+ void Append(const char* s) { Append(s, StringLength(s)); }
+ int Compare(const char* s, bool ignore_case = false) const;
+ static int Compare(const char* s1, const char* s2, bool ignore_case = false);
+ int CompareN(const char* s, NPT_Size count, bool ignore_case = false) const;
+ static int CompareN(const char* s1, const char* s2, NPT_Size count, bool ignore_case = false);
+
+ // substrings
+ NPT_String SubString(NPT_Ordinal first, NPT_Size length) const;
+ NPT_String SubString(NPT_Ordinal first) const {
+ return SubString(first, GetLength());
+ }
+ NPT_String Left(NPT_Size length) const {
+ return SubString(0, length);
+ }
+ NPT_String Right(NPT_Size length) const {
+ return length >= GetLength() ?
+ *this :
+ SubString(GetLength()-length, length);
+ }
+ NPT_List<NPT_String> Split(const char* separator) const;
+ NPT_Array<NPT_String> SplitAny(const char* separator) const;
+ static NPT_String Join(NPT_List<NPT_String>& args, const char* separator);
+
+ // buffer management
+ void Reserve(NPT_Size length);
+
+ // hashing
+ NPT_UInt32 GetHash32() const;
+ NPT_UInt64 GetHash64() const;
+
+ // conversions
+ NPT_String ToLowercase() const;
+ NPT_String ToUppercase() const;
+ NPT_Result ToInteger(int& value, bool relaxed = true) const;
+ NPT_Result ToInteger(unsigned int& value, bool relaxed = true) const;
+ NPT_Result ToInteger(long& value, bool relaxed = true) const;
+ NPT_Result ToInteger(unsigned long& value, bool relaxed = true) const;
+ NPT_Result ToInteger32(NPT_Int32& value, bool relaxed = true) const;
+ NPT_Result ToInteger32(NPT_UInt32& value, bool relaxed = true) const;
+ NPT_Result ToInteger64(NPT_Int64& value, bool relaxed = true) const;
+ NPT_Result ToInteger64(NPT_UInt64& value, bool relaxed = true) const;
+ NPT_Result ToFloat(float& value, bool relaxed = true) const;
+
+ // processing
+ void MakeLowercase();
+ void MakeUppercase();
+ const NPT_String& Replace(char a, char b);
+ const NPT_String& Replace(char a, const char* b);
+
+ // search
+ int Find(char c, NPT_Ordinal start = 0, bool ignore_case = false) const;
+ int Find(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const;
+ int FindAny(const char* s, NPT_Ordinal start, bool ignore_case = false) const;
+ int ReverseFind(char c, NPT_Ordinal start = 0, bool ignore_case = false) const;
+ int ReverseFind(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const;
+ bool StartsWith(const char* s, bool ignore_case = false) const;
+ bool EndsWith(const char* s, bool ignore_case = false) const;
+
+ // editing
+ const NPT_String& Insert(const char* s, NPT_Ordinal where = 0);
+ const NPT_String& Erase(NPT_Ordinal start, NPT_Cardinal count = 1);
+ const NPT_String& Replace(const char* before, const char* after);
+ // void Replace(NPT_Ordinal start, NPT_Cardinal count, const char* s);
+ const NPT_String& TrimLeft();
+ const NPT_String& TrimLeft(char c);
+ const NPT_String& TrimLeft(const char* chars);
+ const NPT_String& TrimRight();
+ const NPT_String& TrimRight(char c);
+ const NPT_String& TrimRight(const char* chars);
+ const NPT_String& Trim();
+ const NPT_String& Trim(char c);
+ const NPT_String& Trim(const char* chars);
+
+ // type casting
+ operator char*() const { return m_Chars ? m_Chars: &EmptyString; }
+ operator const char* () const { return m_Chars ? m_Chars: &EmptyString; }
+ const char* GetChars() const { return m_Chars ? m_Chars: &EmptyString; }
+ char* UseChars() { return m_Chars ? m_Chars: &EmptyString; }
+
+ // operator overloading
+ NPT_String& operator=(const char* str);
+ NPT_String& operator=(const NPT_String& str);
+ NPT_String& operator=(char c);
+ const NPT_String& operator+=(const NPT_String& s) {
+ Append(s.GetChars(), s.GetLength());
+ return *this;
+ }
+ const NPT_String& operator+=(const char* s) {
+ Append(s);
+ return *this;
+ }
+ const NPT_String& operator+=(char c) {
+ Append(&c, 1);
+ return *this;
+ }
+ char operator[](int index) const {
+ NPT_ASSERT((unsigned int)index < GetLength());
+ return GetChars()[index];
+ }
+ char& operator[](int index) {
+ NPT_ASSERT((unsigned int)index < GetLength());
+ return UseChars()[index];
+ }
+
+ // friend operators
+ friend NPT_String operator+(const NPT_String& s1, const NPT_String& s2) {
+ return s1+s2.GetChars();
+ }
+ friend NPT_String operator+(const NPT_String& s1, const char* s2);
+ friend NPT_String operator+(const char* s1, const NPT_String& s2);
+ friend NPT_String operator+(const NPT_String& s, char c);
+ friend NPT_String operator+(char c, const NPT_String& s);
+
+protected:
+ // inner classes
+ class Buffer {
+ public:
+ // class methods
+ static Buffer* Allocate(NPT_Size allocated, NPT_Size length) {
+ void* mem = ::operator new(sizeof(Buffer)+allocated+1);
+ return new(mem) Buffer(allocated, length);
+ }
+ static char* Create(NPT_Size allocated, NPT_Size length=0) {
+ Buffer* shared = Allocate(allocated, length);
+ return shared->GetChars();
+ }
+ static char* Create(const char* copy) {
+ NPT_Size length = StringLength(copy);
+ Buffer* shared = Allocate(length, length);
+ CopyString(shared->GetChars(), copy);
+ return shared->GetChars();
+ }
+ static char* Create(const char* copy, NPT_Size length) {
+ Buffer* shared = Allocate(length, length);
+ CopyBuffer(shared->GetChars(), copy, length);
+ shared->GetChars()[length] = '\0';
+ return shared->GetChars();
+ }
+ static char* Create(char c, NPT_Cardinal repeat) {
+ Buffer* shared = Allocate(repeat, repeat);
+ char* s = shared->GetChars();
+ while (repeat--) {
+ *s++ = c;
+ }
+ *s = '\0';
+ return shared->GetChars();
+ }
+
+ // methods
+ char* GetChars() {
+ // return a pointer to the first char
+ return reinterpret_cast<char*>(this+1);
+ }
+ NPT_Size GetLength() const { return m_Length; }
+ void SetLength(NPT_Size length) { m_Length = length; }
+ NPT_Size GetAllocated() const { return m_Allocated; }
+ void Destroy() { ::operator delete((void*)this); }
+
+ private:
+ // methods
+ Buffer(NPT_Size allocated, NPT_Size length = 0) :
+ m_Length(length),
+ m_Allocated(allocated) {}
+
+ // members
+ NPT_Cardinal m_Length;
+ NPT_Cardinal m_Allocated;
+ // the actual string data follows
+
+ };
+
+ // members
+ char* m_Chars;
+
+private:
+ // friends
+ friend class Buffer;
+
+ // static members
+ static char EmptyString;
+
+ // methods
+ Buffer* GetBuffer() const {
+ return reinterpret_cast<Buffer*>(m_Chars)-1;
+ }
+ void Reset() {
+ if (m_Chars != NULL) {
+ delete GetBuffer();
+ m_Chars = NULL;
+ }
+ }
+ char* PrepareToWrite(NPT_Size length);
+ void PrepareToAppend(NPT_Size length, NPT_Size allocate);
+
+ // static methods
+ static void CopyString(char* dst, const char* src) {
+ while ((*dst++ = *src++)){}
+ }
+
+ static void CopyBuffer(char* dst, const char* src, NPT_Size size) {
+ while (size--) *dst++ = *src++;
+ }
+
+ static NPT_Size StringLength(const char* str) {
+ NPT_Size length = 0;
+ while (*str++) length++;
+ return length;
+ }
+};
+
+/*----------------------------------------------------------------------
+| external operators
++---------------------------------------------------------------------*/
+inline bool operator==(const NPT_String& s1, const NPT_String& s2) {
+ return s1.Compare(s2) == 0;
+}
+inline bool operator==(const NPT_String& s1, const char* s2) {
+ return s1.Compare(s2) == 0;
+}
+inline bool operator==(const char* s1, const NPT_String& s2) {
+ return s2.Compare(s1) == 0;
+}
+inline bool operator!=(const NPT_String& s1, const NPT_String& s2) {
+ return s1.Compare(s2) != 0;
+}
+inline bool operator!=(const NPT_String& s1, const char* s2) {
+ return s1.Compare(s2) != 0;
+}
+inline bool operator!=(const char* s1, const NPT_String& s2) {
+ return s2.Compare(s1) != 0;
+}
+inline bool operator<(const NPT_String& s1, const NPT_String& s2) {
+ return s1.Compare(s2) < 0;
+}
+inline bool operator<(const NPT_String& s1, const char* s2) {
+ return s1.Compare(s2) < 0;
+}
+inline bool operator<(const char* s1, const NPT_String& s2) {
+ return s2.Compare(s1) > 0;
+}
+inline bool operator>(const NPT_String& s1, const NPT_String& s2) {
+ return s1.Compare(s2) > 0;
+}
+inline bool operator>(const NPT_String& s1, const char* s2) {
+ return s1.Compare(s2) > 0;
+}
+inline bool operator>(const char* s1, const NPT_String& s2) {
+ return s2.Compare(s1) < 0;
+}
+inline bool operator<=(const NPT_String& s1, const NPT_String& s2) {
+ return s1.Compare(s2) <= 0;
+}
+inline bool operator<=(const NPT_String& s1, const char* s2) {
+ return s1.Compare(s2) <= 0;
+}
+inline bool operator<=(const char* s1, const NPT_String& s2) {
+ return s2.Compare(s1) >= 0;
+}
+inline bool operator>=(const NPT_String& s1, const NPT_String& s2) {
+ return s1.Compare(s2) >= 0;
+}
+inline bool operator>=(const NPT_String& s1, const char* s2) {
+ return s1.Compare(s2) >= 0;
+}
+inline bool operator>=(const char* s1, const NPT_String& s2) {
+ return s2.Compare(s1) <= 0;
+}
+
+/*----------------------------------------------------------------------
+| hashing
++---------------------------------------------------------------------*/
+template <>
+struct NPT_Hash<NPT_String>
+{
+ NPT_UInt32 operator()(const NPT_String& s) const { return s.GetHash32(); }
+};
+
+
+#endif // _NPT_STRINGS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSystem.cpp b/lib/libUPnP/Neptune/Source/Core/NptSystem.cpp
new file mode 100644
index 0000000..0d4e9b2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSystem.cpp
@@ -0,0 +1,37 @@
+/*****************************************************************
+|
+| Neptune - System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptSystem.h"
+
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptSystem.h b/lib/libUPnP/Neptune/Source/Core/NptSystem.h
new file mode 100644
index 0000000..224a058
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptSystem.h
@@ -0,0 +1,63 @@
+/*****************************************************************
+|
+| Neptune - System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SYSTEM_H_
+#define _NPT_SYSTEM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptTime.h"
+
+/*----------------------------------------------------------------------
+| NPT_System
++---------------------------------------------------------------------*/
+class NPT_System
+{
+public:
+ // methods
+ static NPT_Result GetProcessId(NPT_UInt32& id);
+ static NPT_Result GetMachineName(NPT_String& name);
+ static NPT_Result GetCurrentTimeStamp(NPT_TimeStamp& now);
+ static NPT_Result Sleep(const NPT_TimeInterval& duration);
+ static NPT_Result SleepUntil(const NPT_TimeStamp& when);
+ static NPT_Result SetRandomSeed(unsigned int seed);
+ static NPT_UInt32 GetRandomInteger();
+
+protected:
+ // constructor
+ NPT_System() {}
+};
+
+NPT_Result NPT_GetSystemMachineName(NPT_String& name);
+
+#endif // _NPT_SYSTEM_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptThreads.cpp b/lib/libUPnP/Neptune/Source/Core/NptThreads.cpp
new file mode 100644
index 0000000..25a867d
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptThreads.cpp
@@ -0,0 +1,161 @@
+/*****************************************************************
+|
+| Neptune - Threads
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+| NPT_SingletonLock
++---------------------------------------------------------------------*/
+NPT_Mutex NPT_SingletonLock::Instance;
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot
++---------------------------------------------------------------------*/
+NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot() :
+ m_CallbackArgs(NULL),
+ m_Shutdown(false),
+ m_NotificationHelper(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackSlot::Shutdown
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ThreadCallbackSlot::Shutdown()
+{
+ // protect against concurrent access
+ //FIXME: This will not work if another Thread has called ReceiveCallback with a timeout
+ NPT_AutoLock lock(m_ReadLock);
+
+ // signal we are shut down
+ m_Shutdown = true;
+
+ // clear up any pending callbacks
+ m_Pending.SetValue(0);
+ m_Ack.SetValue(1);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackSlot::SetNotificationHelper
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ThreadCallbackSlot::SetNotificationHelper(NotificationHelper* helper)
+{
+ m_NotificationHelper = helper;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackSlot::ReceiveCallback
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ThreadCallbackSlot::ReceiveCallback(NPT_ThreadCallbackReceiver& receiver,
+ NPT_Timeout timeout)
+{
+ // protect against concurrent access
+ //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - read locking, timeout=%d\n", timeout);
+ NPT_AutoLock lock(m_ReadLock);
+
+ if (timeout) {
+ // wait until there is a pending callback
+ //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - waiting...\n");
+ NPT_Result result = m_Pending.WaitUntilEquals(1, timeout);
+ if (NPT_FAILED(result)) return result; // don't log here because the result
+ // could be NPT_ERROR_TIMEOUT which
+ // is an expected normal case.
+ //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - got it\n");
+ } else {
+ // see if something is pending
+ if (m_Pending.GetValue() == 0) {
+ //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - nothing pending\n");
+ return NPT_ERROR_CALLBACK_NOTHING_PENDING;
+ }
+ }
+
+ // check if we have been shutdown
+ if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;
+
+ // process the callback
+ //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - calling back\n");
+ receiver.OnCallback(const_cast<void*>(m_CallbackArgs));
+
+ // signal that we've processed the callback
+ m_Pending.SetValue(0);
+ m_Ack.SetValue(1);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackSlot::SendCallback
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ThreadCallbackSlot::SendCallback(void* args)
+{
+ // protect against concurrent access
+ //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - write locking\n");
+ NPT_AutoLock lock(m_WriteLock);
+
+ // there should be nothing pending
+#if defined(NPT_DEBUG)
+ NPT_ASSERT(m_Pending.GetValue() == 0);
+#endif
+
+ // check if we have been shutdown
+ if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;
+
+ // put the callback args
+ m_CallbackArgs = args;
+ //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - signalling\n");
+ m_Pending.SetValue(1);
+
+ // call the helper before we wait
+ if (m_NotificationHelper) {
+ m_NotificationHelper->Notify();
+ }
+
+ // wait until the callback has been process, or we've been shutdown
+ //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - waiting...\n");
+ m_Ack.WaitUntilEquals(1);
+ //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - got it\n");
+
+ // done
+ m_Ack.SetValue(0);
+ m_CallbackArgs = NULL;
+
+ return m_Shutdown?NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN:NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptThreads.h b/lib/libUPnP/Neptune/Source/Core/NptThreads.h
new file mode 100644
index 0000000..b14568e
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptThreads.h
@@ -0,0 +1,322 @@
+/*****************************************************************
+|
+| Neptune - Threads
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_THREADS_H_
+#define _NPT_THREADS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptInterfaces.h"
+
+/*----------------------------------------------------------------------
+| error codes
++---------------------------------------------------------------------*/
+const int NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN = NPT_ERROR_BASE_THREADS-0;
+const int NPT_ERROR_CALLBACK_NOTHING_PENDING = NPT_ERROR_BASE_THREADS-1;
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_THREAD_PRIORITY_MIN = -15;
+const int NPT_THREAD_PRIORITY_IDLE = -15;
+const int NPT_THREAD_PRIORITY_LOWEST = -2;
+const int NPT_THREAD_PRIORITY_BELOW_NORMAL = -1;
+const int NPT_THREAD_PRIORITY_NORMAL = 0;
+const int NPT_THREAD_PRIORITY_ABOVE_NORMAL = 1;
+const int NPT_THREAD_PRIORITY_HIGHEST = 2;
+const int NPT_THREAD_PRIORITY_TIME_CRITICAL = 15;
+const int NPT_THREAD_PRIORITY_MAX = 15;
+
+/*----------------------------------------------------------------------
+| NPT_MutexInterface
++---------------------------------------------------------------------*/
+class NPT_MutexInterface
+{
+ public:
+ // methods
+ virtual ~NPT_MutexInterface() {}
+ virtual NPT_Result Lock() = 0;
+ virtual NPT_Result Unlock() = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Mutex
++---------------------------------------------------------------------*/
+class NPT_Mutex : public NPT_MutexInterface
+{
+ public:
+ // methods
+ NPT_Mutex(bool recursive = false);
+ ~NPT_Mutex() override { delete m_Delegate; }
+ NPT_Result Lock() override { return m_Delegate->Lock(); }
+ NPT_Result Unlock() override { return m_Delegate->Unlock(); }
+
+ private:
+ // members
+ NPT_MutexInterface* m_Delegate;
+};
+
+/*----------------------------------------------------------------------
+| NPT_AutoLock
++---------------------------------------------------------------------*/
+class NPT_AutoLock
+{
+ public:
+ // methods
+ NPT_AutoLock(NPT_Mutex &mutex) : m_Mutex(mutex) {
+ m_Mutex.Lock();
+ }
+ ~NPT_AutoLock() {
+ m_Mutex.Unlock();
+ }
+
+ private:
+ // members
+ NPT_Mutex& m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Lock
++---------------------------------------------------------------------*/
+template <typename T>
+class NPT_Lock : public T,
+ public NPT_Mutex
+{
+};
+
+/*----------------------------------------------------------------------
+| NPT_SingletonLock
++---------------------------------------------------------------------*/
+class NPT_SingletonLock
+{
+public:
+ static NPT_Mutex& GetInstance() {
+ return Instance;
+ }
+
+private:
+ static NPT_Mutex Instance;
+};
+
+/*----------------------------------------------------------------------
+| NPT_SharedVariableInterface
++---------------------------------------------------------------------*/
+class NPT_SharedVariableInterface
+{
+ public:
+ // methods
+ virtual ~NPT_SharedVariableInterface() {}
+ virtual void SetValue(int value)= 0;
+ virtual int GetValue() = 0;
+ virtual NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+ virtual NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_SharedVariable
++---------------------------------------------------------------------*/
+class NPT_SharedVariable : public NPT_SharedVariableInterface
+{
+ public:
+ // methods
+ NPT_SharedVariable(int value = 0);
+ ~NPT_SharedVariable() override { delete m_Delegate; }
+ void SetValue(int value) override {
+ m_Delegate->SetValue(value);
+ }
+ int GetValue() override {
+ return m_Delegate->GetValue();
+ }
+ NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
+ return m_Delegate->WaitUntilEquals(value, timeout);
+ }
+ NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
+ return m_Delegate->WaitWhileEquals(value, timeout);
+ }
+
+ private:
+ // members
+ NPT_SharedVariableInterface* m_Delegate;
+};
+
+/*----------------------------------------------------------------------
+| NPT_AtomicVariableInterface
++---------------------------------------------------------------------*/
+class NPT_AtomicVariableInterface
+{
+ public:
+ // methods
+ virtual ~NPT_AtomicVariableInterface() {}
+ virtual int Increment() = 0;
+ virtual int Decrement() = 0;
+ virtual int GetValue() = 0;
+ virtual void SetValue(int value) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_AtomicVariable
++---------------------------------------------------------------------*/
+class NPT_AtomicVariable : public NPT_AtomicVariableInterface
+{
+ public:
+ // methods
+ NPT_AtomicVariable(int value = 0);
+ ~NPT_AtomicVariable() override { delete m_Delegate; }
+ int Increment() override { return m_Delegate->Increment();}
+ int Decrement() override { return m_Delegate->Decrement();}
+ void SetValue(int value) override { m_Delegate->SetValue(value); }
+ int GetValue() override { return m_Delegate->GetValue(); }
+
+ private:
+ // members
+ NPT_AtomicVariableInterface* m_Delegate;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Runnable
++---------------------------------------------------------------------*/
+class NPT_Runnable
+{
+public:
+ virtual ~NPT_Runnable() {}
+ virtual void Run() = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ThreadInterface
++---------------------------------------------------------------------*/
+class NPT_ThreadInterface: public NPT_Runnable, public NPT_Interruptible
+{
+ public:
+ // methods
+ ~NPT_ThreadInterface() override {}
+ virtual NPT_Result Start() = 0;
+ virtual NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+ virtual NPT_Result SetPriority(int /*priority*/) { return NPT_SUCCESS; }
+ virtual NPT_Result CancelBlockerSocket() = 0;
+ virtual NPT_Result GetPriority(int& priority) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Thread
++---------------------------------------------------------------------*/
+class NPT_Thread : public NPT_ThreadInterface
+{
+ public:
+ // types
+ typedef NPT_UInt64 ThreadId;
+
+ // class methods
+ static ThreadId GetCurrentThreadId();
+ static NPT_Result SetCurrentThreadPriority(int priority);
+ static NPT_Result GetCurrentThreadPriority(int& priority);
+
+ // methods
+ explicit NPT_Thread(bool detached = false);
+ explicit NPT_Thread(NPT_Runnable& target, bool detached = false);
+ ~NPT_Thread() override { delete m_Delegate; }
+
+ // cancel any socket that this thread may be waiting for
+ NPT_Result CancelBlockerSocket() override { return m_Delegate->CancelBlockerSocket(); }
+
+ // NPT_ThreadInterface methods
+ NPT_Result Start() override {
+ return m_Delegate->Start();
+ }
+ NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
+ return m_Delegate->Wait(timeout);
+ }
+ NPT_Result SetPriority(int priority) override {
+ return m_Delegate->SetPriority(priority);
+ }
+ NPT_Result GetPriority(int& priority) override {
+ return m_Delegate->GetPriority(priority);
+ }
+
+ // NPT_Runnable methods
+ void Run() override {}
+
+ // NPT_Interruptible methods
+ NPT_Result Interrupt() override { return m_Delegate->Interrupt(); }
+
+ private:
+ // members
+ NPT_ThreadInterface* m_Delegate;
+};
+
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackReceiver
++---------------------------------------------------------------------*/
+class NPT_ThreadCallbackReceiver
+{
+public:
+ virtual ~NPT_ThreadCallbackReceiver() {}
+ virtual void OnCallback(void* args) = 0;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ThreadCallbackSlot
++---------------------------------------------------------------------*/
+class NPT_ThreadCallbackSlot
+{
+public:
+ // types
+ class NotificationHelper {
+ public:
+ virtual ~NotificationHelper() {};
+ virtual void Notify(void) = 0;
+ };
+
+ // constructor
+ NPT_ThreadCallbackSlot();
+
+ // methods
+ NPT_Result ReceiveCallback(NPT_ThreadCallbackReceiver& receiver, NPT_Timeout timeout = 0);
+ NPT_Result SendCallback(void* args);
+ NPT_Result SetNotificationHelper(NotificationHelper* helper);
+ NPT_Result Shutdown();
+
+protected:
+ // members
+ volatile void* m_CallbackArgs;
+ volatile bool m_Shutdown;
+ NPT_SharedVariable m_Pending;
+ NPT_SharedVariable m_Ack;
+ NPT_Mutex m_ReadLock;
+ NPT_Mutex m_WriteLock;
+ NotificationHelper* m_NotificationHelper;
+};
+
+#endif // _NPT_THREADS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTime.cpp b/lib/libUPnP/Neptune/Source/Core/NptTime.cpp
new file mode 100755
index 0000000..d842259
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTime.cpp
@@ -0,0 +1,714 @@
+/*****************************************************************
+|
+| Neptune - Time
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTime.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const char* const NPT_TIME_DAYS_SHORT[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+const char* const NPT_TIME_DAYS_LONG[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+const char* const NPT_TIME_MONTHS[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+static const NPT_Int32 NPT_TIME_MONTH_DAY[] = {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
+static const NPT_Int32 NPT_TIME_MONTH_DAY_LEAP[] = {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+static const NPT_Int32 NPT_TIME_ELAPSED_DAYS_AT_MONTH[13] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+const NPT_Int32 NPT_SECONDS_PER_DAY = (24L * 60L * 60L);
+const NPT_Int32 NPT_SECONDS_PER_YEAR = (365L * NPT_SECONDS_PER_DAY);
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define NPT_TIME_YEAR_IS_LEAP(_y) ((((_y)%4 == 0) && ((_y)%100 != 0)) || ((_y)%400 == 0))
+#define NPT_TIME_CHECK_BOUNDS(_var, _low, _high) do { \
+ if (((_var)<(_low)) || ((_var)>(_high))) { \
+ return NPT_ERROR_OUT_OF_RANGE; \
+ } \
+} while (0)
+
+/*----------------------------------------------------------------------
+| NPT_TimeStamp::NPT_TimeStamp
++---------------------------------------------------------------------*/
+NPT_TimeStamp::NPT_TimeStamp(const NPT_TimeStamp& timestamp)
+{
+ m_NanoSeconds = timestamp.m_NanoSeconds;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TimeStamp::NPT_TimeStamp
++---------------------------------------------------------------------*/
+NPT_TimeStamp::NPT_TimeStamp(double seconds)
+{
+ m_NanoSeconds = (NPT_Int64)(seconds * 1e9);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TimeStamp::operator+=
++---------------------------------------------------------------------*/
+NPT_TimeStamp&
+NPT_TimeStamp::operator+=(const NPT_TimeStamp& t)
+{
+ m_NanoSeconds += t.m_NanoSeconds;
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TimeStamp::operator-=
++---------------------------------------------------------------------*/
+NPT_TimeStamp&
+NPT_TimeStamp::operator-=(const NPT_TimeStamp& t)
+{
+ m_NanoSeconds -= t.m_NanoSeconds;
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| MatchString
++---------------------------------------------------------------------*/
+static int
+MatchString(const char* string, const char* const* list, unsigned int list_length)
+{
+ for (unsigned int i=0; i<list_length; i++) {
+ if (NPT_StringsEqual(string, list[i])) return i;
+ }
+
+ return -1;
+}
+
+/*----------------------------------------------------------------------
+| ElapsedLeapYearsSince1900
++---------------------------------------------------------------------*/
+static NPT_UInt32
+ElapsedLeapYearsSince1900(NPT_UInt32 year)
+{
+ if (year < 1901) return 0;
+ NPT_UInt32 years_since_1900 = year-1-1900; // not including the current year
+ return years_since_1900/4 -
+ years_since_1900/100 +
+ (years_since_1900+300)/400;
+}
+
+/*----------------------------------------------------------------------
+| ElapsedDaysSince1900
++---------------------------------------------------------------------*/
+static NPT_UInt32
+ElapsedDaysSince1900(const NPT_DateTime& date)
+{
+ // compute the number of days elapsed in the year
+ NPT_UInt32 day_count = NPT_TIME_ELAPSED_DAYS_AT_MONTH[date.m_Month-1] + date.m_Day - 1;
+
+ // adjust for leap years after february
+ if (NPT_TIME_YEAR_IS_LEAP(date.m_Year) && (date.m_Month > 2)) ++day_count;
+
+ // compute the total number of elapsed days
+ NPT_UInt32 leap_year_count = ElapsedLeapYearsSince1900(date.m_Year);
+ day_count += (date.m_Year-1900)*365 + leap_year_count;
+
+ return day_count;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::NPT_DateTime
++---------------------------------------------------------------------*/
+NPT_DateTime::NPT_DateTime() :
+ m_Year(1970),
+ m_Month(1),
+ m_Day(1),
+ m_Hours(0),
+ m_Minutes(0),
+ m_Seconds(0),
+ m_NanoSeconds(0),
+ m_TimeZone(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::NPT_DateTime
++---------------------------------------------------------------------*/
+NPT_DateTime::NPT_DateTime(const NPT_TimeStamp& timestamp, bool local)
+{
+ FromTimeStamp(timestamp, local);
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::ChangeTimeZone
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DateTime::ChangeTimeZone(NPT_Int32 timezone)
+{
+ if (timezone < -12*60 || timezone > 12*60) {
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+ NPT_TimeStamp ts;
+ NPT_Result result = ToTimeStamp(ts);
+ if (NPT_FAILED(result)) return result;
+ ts.SetNanos(ts.ToNanos()+(NPT_Int64)timezone*(NPT_Int64)60*(NPT_Int64)1000000000);
+
+ result = FromTimeStamp(ts);
+ m_TimeZone = timezone;
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::FromTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DateTime::FromTimeStamp(const NPT_TimeStamp& ts, bool local)
+{
+ // number of seconds from the epoch (positive or negative)
+ NPT_Int64 seconds = ts.ToSeconds();
+
+ // check the range (we only allow up to 31 bits of negative range for seconds
+ // in order to have the same lower bound as the 32-bit gmtime() function)
+ if (seconds < 0 && (NPT_Int32)seconds != seconds) return NPT_ERROR_OUT_OF_RANGE;
+
+ // adjust for the timezone if necessary
+ NPT_Int32 timezone = 0;
+ if (local) {
+ timezone = GetLocalTimeZone();
+ seconds += timezone*60;
+ }
+
+ // adjust to the number of seconds since 1900
+ seconds += (NPT_Int64)NPT_SECONDS_PER_YEAR*70 +
+ (NPT_Int64)(17*NPT_SECONDS_PER_DAY); // 17 leap year between 1900 and 1970
+
+ // compute the years since 1900, not adjusting for leap years
+ NPT_UInt32 years_since_1900 = (NPT_UInt32)(seconds/NPT_SECONDS_PER_YEAR);
+
+ // compute the number of seconds elapsed in the current year
+ seconds -= (NPT_Int64)years_since_1900 * NPT_SECONDS_PER_YEAR;
+
+ // adjust for leap years
+ bool is_leap_year = false;
+ NPT_Int64 leap_years_since_1900 = ElapsedLeapYearsSince1900(years_since_1900+1900);
+ if (seconds < (leap_years_since_1900 * NPT_SECONDS_PER_DAY)) {
+ // not enough seconds in the current year to compensate, move one year back
+ seconds += NPT_SECONDS_PER_YEAR;
+ seconds -= leap_years_since_1900 * NPT_SECONDS_PER_DAY;
+ --years_since_1900;
+ if (NPT_TIME_YEAR_IS_LEAP(years_since_1900+1900) ) {
+ seconds += NPT_SECONDS_PER_DAY;
+ is_leap_year = true;
+ }
+ } else {
+ seconds -= leap_years_since_1900 * NPT_SECONDS_PER_DAY;
+ if (NPT_TIME_YEAR_IS_LEAP(years_since_1900+1900) ) {
+ is_leap_year = true;
+ }
+ }
+
+ // now we know the year
+ m_Year = years_since_1900+1900;
+
+ // compute the number of days since January 1 (0 - 365)
+ NPT_UInt32 day_of_the_year = (NPT_UInt32)(seconds/NPT_SECONDS_PER_DAY);
+
+ // compute the number of seconds in the current day
+ seconds -= day_of_the_year * NPT_SECONDS_PER_DAY;
+
+ // compute the number of months since January (0 - 11) and the day of month (1 - 31) */
+ const NPT_Int32* month_day = is_leap_year?NPT_TIME_MONTH_DAY_LEAP:NPT_TIME_MONTH_DAY;
+ NPT_UInt32 month;
+ for (month = 1; month_day[month] < (NPT_Int32)day_of_the_year ; month++) {}
+
+ // now we know the month and day
+ m_Month = month;
+ m_Day = day_of_the_year - month_day[month-1];
+
+ // compute the number of hours since midnight (0 - 23), minutes after the hour
+ // (0 - 59), seconds after the minute (0 - 59) and nanoseconds
+ m_Hours = (NPT_Int32)seconds/3600;
+ seconds -= m_Hours * 3600L;
+ m_Minutes = (NPT_Int32)seconds / 60;
+ m_Seconds = (NPT_Int32)seconds - m_Minutes * 60;
+ m_NanoSeconds = (NPT_Int32)(ts.ToNanos()%1000000000);
+ if (local) {
+ m_TimeZone = timezone;
+ } else {
+ m_TimeZone = 0;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CheckDate
++---------------------------------------------------------------------*/
+static NPT_Result
+CheckDate(const NPT_DateTime& date)
+{
+ NPT_TIME_CHECK_BOUNDS(date.m_Year, NPT_DATETIME_YEAR_MIN, NPT_DATETIME_YEAR_MAX);
+ NPT_TIME_CHECK_BOUNDS(date.m_Month, 1, 12);
+ NPT_TIME_CHECK_BOUNDS(date.m_Day, 1, 31);
+ NPT_TIME_CHECK_BOUNDS(date.m_Hours, 0, 23);
+ NPT_TIME_CHECK_BOUNDS(date.m_Minutes, 0, 59);
+ NPT_TIME_CHECK_BOUNDS(date.m_Seconds, 0, 59);
+ NPT_TIME_CHECK_BOUNDS(date.m_NanoSeconds, 0, 999999999);
+ NPT_TIME_CHECK_BOUNDS(date.m_TimeZone, -12*60, 12*60);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::ToTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DateTime::ToTimeStamp(NPT_TimeStamp& timestamp) const
+{
+ // default value
+ timestamp.SetNanos(0);
+
+ // check bounds
+ NPT_Result result = CheckDate(*this);
+ if (NPT_FAILED(result)) return result;
+
+ // compute the number of days elapsed since 1900
+ NPT_UInt32 days = ElapsedDaysSince1900(*this);
+
+ // compute the number of nanoseconds
+ NPT_Int64 seconds = (NPT_Int64)days * (24*60*60) +
+ (NPT_Int64)m_Hours * (60*60) +
+ (NPT_Int64)m_Minutes * (60) +
+ (NPT_Int64)m_Seconds;
+ seconds -= (NPT_Int64)m_TimeZone*60;
+
+ // adjust to the number of seconds since 1900
+ seconds -= (NPT_Int64)NPT_SECONDS_PER_YEAR*70 +
+ (NPT_Int64)(17*NPT_SECONDS_PER_DAY); // 17 leap year between 1900 and 1970
+
+ timestamp.FromNanos(seconds * 1000000000 + m_NanoSeconds);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AppendNumber
++---------------------------------------------------------------------*/
+static void
+AppendNumber(NPT_String& output, NPT_UInt32 number, unsigned int digit_count)
+{
+ NPT_Size new_length = output.GetLength()+digit_count;
+ output.SetLength(new_length);
+ char* dest = output.UseChars()+new_length;
+ while (digit_count--) {
+ *--dest = '0'+(number%10);
+ number /= 10;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_DateTime::ToString(Format format, NPT_Flags flags) const
+{
+ NPT_String result;
+
+ if (NPT_FAILED(CheckDate(*this))) return result;
+
+ switch (format) {
+ case FORMAT_W3C:
+ AppendNumber(result, m_Year, 4);
+ result += '-';
+ AppendNumber(result, m_Month, 2);
+ result += '-';
+ AppendNumber(result, m_Day, 2);
+ result += 'T';
+ AppendNumber(result, m_Hours, 2);
+ result += ':';
+ AppendNumber(result, m_Minutes, 2);
+ result += ':';
+ AppendNumber(result, m_Seconds, 2);
+ if (flags & FLAG_EMIT_FRACTION) {
+ result += '.';
+ if (flags & FLAG_EXTENDED_PRECISION) {
+ // nanoseconds precision
+ AppendNumber(result, m_NanoSeconds, 9);
+ } else {
+ // only miliseconds precision
+ AppendNumber(result, m_NanoSeconds/1000000, 3);
+ }
+ }
+ if (m_TimeZone) {
+ NPT_UInt32 tz;
+ if (m_TimeZone > 0) {
+ result += '+';
+ tz = m_TimeZone;
+ } else {
+ result += '-';
+ tz = -m_TimeZone;
+ }
+ AppendNumber(result, tz/60, 2);
+ result += ':';
+ AppendNumber(result, tz%60, 2);
+ } else {
+ result += 'Z';
+ }
+ break;
+
+ case FORMAT_ANSI: {
+ // compute the number of days elapsed since 1900
+ NPT_UInt32 days = ElapsedDaysSince1900(*this);
+
+ // format the result
+ result.SetLength(24);
+ NPT_FormatString(result.UseChars(), result.GetLength()+1,
+ "%.3s %.3s%3d %.2d:%.2d:%.2d %d",
+ NPT_TIME_DAYS_SHORT[(days+1)%7],
+ NPT_TIME_MONTHS[m_Month-1],
+ m_Day,
+ m_Hours,
+ m_Minutes,
+ m_Seconds,
+ m_Year);
+ break;
+ }
+
+ case FORMAT_RFC_1036:
+ case FORMAT_RFC_1123: {
+ // compute the number of days elapsed since 1900
+ NPT_UInt32 days = ElapsedDaysSince1900(*this);
+
+ if (format == FORMAT_RFC_1036) {
+ result += NPT_TIME_DAYS_LONG[(days+1)%7];
+ result += ", ";
+ AppendNumber(result, m_Day, 2);
+ result += '-';
+ result += NPT_TIME_MONTHS[m_Month-1];
+ result += '-';
+ AppendNumber(result, m_Year%100, 2);
+ } else {
+ result += NPT_TIME_DAYS_SHORT[(days+1)%7];
+ result += ", ";
+ AppendNumber(result, m_Day, 2);
+ result += ' ';
+ result += NPT_TIME_MONTHS[m_Month-1];
+ result += ' ';
+ AppendNumber(result, m_Year, 4);
+ }
+ result += ' ';
+ AppendNumber(result, m_Hours, 2);
+ result += ':';
+ AppendNumber(result, m_Minutes, 2);
+ result += ':';
+ AppendNumber(result, m_Seconds, 2);
+ if (m_TimeZone) {
+ if (m_TimeZone > 0) {
+ result += " +";
+ AppendNumber(result, m_TimeZone/60, 2);
+ AppendNumber(result, m_TimeZone%60, 2);
+ } else {
+ result += " -";
+ AppendNumber(result, -m_TimeZone/60, 2);
+ AppendNumber(result, -m_TimeZone%60, 2);
+ }
+ } else {
+ result += " GMT";
+ }
+ break;
+ }
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_DateTime::FromString
++--------------------------------------------------------------------*/
+NPT_Result
+NPT_DateTime::FromString(const char* date, Format format)
+{
+ if (date == NULL || date[0] == '\0') return NPT_ERROR_INVALID_PARAMETERS;
+
+ // create a local copy to work with
+ NPT_String workspace(date);
+ char* input = workspace.UseChars();
+ NPT_Size input_size = workspace.GetLength();
+
+ switch (format) {
+ case FORMAT_W3C: {
+ if (input_size < 17 && input_size != 10) return NPT_ERROR_INVALID_SYNTAX;
+
+ // check separators
+ if (input[4] != '-' ||
+ input[7] != '-') {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // replace separators with terminators
+ input[4] = input[7] = '\0';
+
+ bool no_seconds = true;
+ if (input_size > 10) {
+ if (input[10] != 'T' ||
+ input[13] != ':') {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ input[10] = input[13] = '\0';
+ if (input[16] == ':') {
+ input[16] = '\0';
+ no_seconds = false;
+ if (input_size < 20) return NPT_ERROR_INVALID_SYNTAX;
+ } else {
+ m_Seconds = 0;
+ }
+ }
+
+
+ // parse CCYY-MM-DD fields
+ if (NPT_FAILED(NPT_ParseInteger(input, m_Year, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+5, m_Month, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+8, m_Day, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // parse remaining fields if any
+ if (input_size > 10) {
+ // parse the timezone part
+ if (input[input_size-1] == 'Z') {
+ m_TimeZone = 0;
+ input[input_size-1] = '\0';
+ } else if (input[input_size-6] == '+' || input[input_size-6] == '-') {
+ if (input[input_size-3] != ':') return NPT_ERROR_INVALID_SYNTAX;
+ input[input_size-3] = '\0';
+ unsigned int hh, mm;
+ if (NPT_FAILED(NPT_ParseInteger(input+input_size-5, hh, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+input_size-2, mm, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ if (hh > 59 || mm > 59) return NPT_ERROR_INVALID_SYNTAX;
+ m_TimeZone = hh*60+mm;
+ if (input[input_size-6] == '-') m_TimeZone = -m_TimeZone;
+ input[input_size-6] = '\0';
+ }
+
+ // parse fields
+ if (NPT_FAILED(NPT_ParseInteger(input+11, m_Hours, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+14, m_Minutes, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ if (!no_seconds && input[19] == '.') {
+ char fraction[10];
+ fraction[9] = '\0';
+ unsigned int fraction_size = NPT_StringLength(&input[20]);
+ if (fraction_size == 0) return NPT_ERROR_INVALID_SYNTAX;
+ for (unsigned int i=0; i<9; i++) {
+ if (i < fraction_size) {
+ fraction[i] = input[20+i];
+ } else {
+ fraction[i] = '0';
+ }
+ }
+ if (NPT_FAILED(NPT_ParseInteger(fraction, m_NanoSeconds, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ input[19] = '\0';
+ } else {
+ m_NanoSeconds = 0;
+ }
+ if (!no_seconds) {
+ if (NPT_FAILED(NPT_ParseInteger(input+17, m_Seconds, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ }
+ }
+ break;
+ }
+
+ case FORMAT_RFC_1036:
+ case FORMAT_RFC_1123: {
+ if (input_size < 26) return NPT_ERROR_INVALID_SYNTAX;
+ // look for the weekday and separtor
+ const char* wday = input;
+ while (*input && *input != ',') {
+ ++input;
+ --input_size;
+ }
+ if (*input == '\0' || *wday == ',') return NPT_ERROR_INVALID_SYNTAX;
+ *input++ = '\0';
+ --input_size;
+
+ // look for the timezone
+ char* timezone = input+input_size-1;
+ unsigned int timezone_size = 0;
+ while (input_size && *timezone != ' ') {
+ --timezone;
+ ++timezone_size;
+ --input_size;
+ }
+ if (input_size == 0) return NPT_ERROR_INVALID_SYNTAX;
+ *timezone++ = '\0';
+
+ // check separators
+ if (input_size < 20) return NPT_ERROR_INVALID_SYNTAX;
+ unsigned int yl = input_size-18;
+ if (yl != 2 && yl != 4) return NPT_ERROR_INVALID_SYNTAX;
+ char sep;
+ int wday_index;
+ if (format == FORMAT_RFC_1036) {
+ sep = '-';
+ wday_index = MatchString(wday, NPT_TIME_DAYS_LONG, 7);
+ } else {
+ sep = ' ';
+ wday_index = MatchString(wday, NPT_TIME_DAYS_SHORT, 7);
+ }
+ if (input[0] != ' ' ||
+ input[3] != sep ||
+ input[7] != sep ||
+ input[8+yl] != ' ' ||
+ input[11+yl] != ':' ||
+ input[14+yl] != ':') {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ input[3] = input[7] = input[8+yl] = input[11+yl] = input[14+yl] = '\0';
+
+ // parse fields
+ m_Month = 1+MatchString(input+4, NPT_TIME_MONTHS, 12);
+ if (NPT_FAILED(NPT_ParseInteger(input+1, m_Day, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+8, m_Year, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+9+yl, m_Hours, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+12+yl, m_Minutes, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+15+yl, m_Seconds, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // adjust short year lengths
+ if (yl == 2) m_Year += 1900;
+
+ // parse the timezone
+ if (NPT_StringsEqual(timezone, "GMT") ||
+ NPT_StringsEqual(timezone, "UT") ||
+ NPT_StringsEqual(timezone, "Z")) {
+ m_TimeZone = 0;
+ } else if (NPT_StringsEqual(timezone, "EDT")) {
+ m_TimeZone = -4*60;
+ } else if (NPT_StringsEqual(timezone, "EST") ||
+ NPT_StringsEqual(timezone, "CDT")) {
+ m_TimeZone = -5*60;
+ } else if (NPT_StringsEqual(timezone, "CST") ||
+ NPT_StringsEqual(timezone, "MDT")) {
+ m_TimeZone = -6*60;
+ } else if (NPT_StringsEqual(timezone, "MST") ||
+ NPT_StringsEqual(timezone, "PDT")) {
+ m_TimeZone = -7*60;
+ } else if (NPT_StringsEqual(timezone, "PST")) {
+ m_TimeZone = -8*60;
+ } else if (timezone_size == 1) {
+ if (timezone[0] >= 'A' && timezone[0] <= 'I') {
+ m_TimeZone = -60*(1+timezone[0]-'A');
+ } else if (timezone[0] >= 'K' && timezone[0] <= 'M') {
+ m_TimeZone = -60*(timezone[0]-'A');
+ } else if (timezone[0] >= 'N' && timezone[0] <= 'Y') {
+ m_TimeZone = 60*(1+timezone[0]-'N');
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ } else if (timezone_size == 5) {
+ int sign;
+ if (timezone[0] == '-') {
+ sign = -1;
+ } else if (timezone[0] == '+') {
+ sign = 1;
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ NPT_UInt32 tz;
+ if (NPT_FAILED(NPT_ParseInteger(timezone+1, tz, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ unsigned int hh = (tz/100);
+ unsigned int mm = (tz%100);
+ if (hh > 59 || mm > 59) return NPT_ERROR_INVALID_SYNTAX;
+ m_TimeZone = sign*(hh*60+mm);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // compute the number of days elapsed since 1900
+ NPT_UInt32 days = ElapsedDaysSince1900(*this);
+ if ((int)((days+1)%7) != wday_index) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ m_NanoSeconds = 0;
+
+ break;
+ }
+
+ case FORMAT_ANSI: {
+ if (input_size != 24) return NPT_ERROR_INVALID_SYNTAX;
+
+ // check separators
+ if (input[3] != ' ' ||
+ input[7] != ' ' ||
+ input[10] != ' ' ||
+ input[13] != ':' ||
+ input[16] != ':' ||
+ input[19] != ' ') {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ input[3] = input[7] = input[10] = input[13] = input[16] = input[19] = '\0';
+ if (input[8] == ' ') input[8] = '0';
+
+ m_Month = 1+MatchString(input+4, NPT_TIME_MONTHS, 12);
+ if (NPT_FAILED(NPT_ParseInteger(input+8, m_Day, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+11, m_Hours, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+14, m_Minutes, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+17, m_Seconds, false)) ||
+ NPT_FAILED(NPT_ParseInteger(input+20, m_Year, false))) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // compute the number of days elapsed since 1900
+ NPT_UInt32 days = ElapsedDaysSince1900(*this);
+ if ((int)((days+1)%7) != MatchString(input, NPT_TIME_DAYS_SHORT, 7)) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ m_TimeZone = 0;
+ m_NanoSeconds = 0;
+ break;
+ }
+
+ default:
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return CheckDate(*this);
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTime.h b/lib/libUPnP/Neptune/Source/Core/NptTime.h
new file mode 100644
index 0000000..ae02a48
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTime.h
@@ -0,0 +1,156 @@
+/*****************************************************************
+|
+| Neptune - Time
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_TIME_H_
+#define _NPT_TIME_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptStrings.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define NPT_DATETIME_YEAR_MIN 1901
+#define NPT_DATETIME_YEAR_MAX 2262
+
+/*----------------------------------------------------------------------
+| NPT_TimeStamp
++---------------------------------------------------------------------*/
+class NPT_TimeStamp
+{
+ public:
+ // methods
+ NPT_TimeStamp(const NPT_TimeStamp& timestamp);
+ NPT_TimeStamp() : m_NanoSeconds(0) {}
+ NPT_TimeStamp(NPT_Int64 nanoseconds) : m_NanoSeconds(nanoseconds) {}
+ NPT_TimeStamp(double seconds);
+ NPT_TimeStamp& operator+=(const NPT_TimeStamp& time_stamp);
+ NPT_TimeStamp& operator-=(const NPT_TimeStamp& time_stamp);
+ bool operator==(const NPT_TimeStamp& t) const { return m_NanoSeconds == t.m_NanoSeconds; }
+ bool operator!=(const NPT_TimeStamp& t) const { return m_NanoSeconds != t.m_NanoSeconds; }
+ bool operator> (const NPT_TimeStamp& t) const { return m_NanoSeconds > t.m_NanoSeconds; }
+ bool operator< (const NPT_TimeStamp& t) const { return m_NanoSeconds < t.m_NanoSeconds; }
+ bool operator>=(const NPT_TimeStamp& t) const { return m_NanoSeconds >= t.m_NanoSeconds; }
+ bool operator<=(const NPT_TimeStamp& t) const { return m_NanoSeconds <= t.m_NanoSeconds; }
+
+ // accessors
+ void SetNanos(NPT_Int64 nanoseconds) { m_NanoSeconds = nanoseconds; }
+ void SetMicros(NPT_Int64 micros) { m_NanoSeconds = micros * 1000; }
+ void SetMillis(NPT_Int64 millis) { m_NanoSeconds = millis * 1000000; }
+ void SetSeconds(NPT_Int64 seconds) { m_NanoSeconds = seconds * 1000000000; }
+
+ // conversion
+ operator double() const { return (double)m_NanoSeconds/1E9; }
+ void FromNanos(NPT_Int64 nanoseconds) { m_NanoSeconds = nanoseconds; }
+ NPT_Int64 ToNanos() const { return m_NanoSeconds; }
+ NPT_Int64 ToMicros() const { return m_NanoSeconds/1000; }
+ NPT_Int64 ToMillis() const { return m_NanoSeconds/1000000; }
+ NPT_Int64 ToSeconds() const { return m_NanoSeconds/1000000000; }
+
+private:
+ // members
+ NPT_Int64 m_NanoSeconds;
+};
+
+/*----------------------------------------------------------------------
+| operator+
++---------------------------------------------------------------------*/
+inline
+NPT_TimeStamp
+operator+(const NPT_TimeStamp& t1, const NPT_TimeStamp& t2)
+{
+ NPT_TimeStamp t = t1;
+ return t += t2;
+}
+
+/*----------------------------------------------------------------------
+| operator-
++---------------------------------------------------------------------*/
+inline
+NPT_TimeStamp
+operator-(const NPT_TimeStamp& t1, const NPT_TimeStamp& t2)
+{
+ NPT_TimeStamp t = t1;
+ return t -= t2;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TimeInterval
++---------------------------------------------------------------------*/
+typedef NPT_TimeStamp NPT_TimeInterval;
+
+/*----------------------------------------------------------------------
+| NPT_DateTime
++---------------------------------------------------------------------*/
+class NPT_DateTime {
+public:
+ // types
+ enum Format {
+ FORMAT_ANSI,
+ FORMAT_W3C,
+ FORMAT_RFC_1123, // RFC 822 updated by RFC 1123
+ FORMAT_RFC_1036 // RFC 850 updated by RFC 1036
+ };
+
+ enum FormatFlags {
+ FLAG_EMIT_FRACTION = 1,
+ FLAG_EXTENDED_PRECISION = 2
+ };
+
+ // class methods
+ NPT_Int32 GetLocalTimeZone();
+
+ // constructors
+ NPT_DateTime();
+ NPT_DateTime(const NPT_TimeStamp& timestamp, bool local=false);
+
+ // methods
+ NPT_Result ChangeTimeZone(NPT_Int32 timezone);
+ NPT_Result FromTimeStamp(const NPT_TimeStamp& timestamp, bool local=false);
+ NPT_Result ToTimeStamp(NPT_TimeStamp& timestamp) const;
+ NPT_Result FromString(const char* date, Format format = FORMAT_ANSI);
+ NPT_String ToString(Format format = FORMAT_ANSI, NPT_Flags flags=0) const;
+
+ // members
+ NPT_Int32 m_Year; // year
+ NPT_Int32 m_Month; // month of the year (1-12)
+ NPT_Int32 m_Day; // day of the month (1-31)
+ NPT_Int32 m_Hours; // hours (0-23)
+ NPT_Int32 m_Minutes; // minutes (0-59)
+ NPT_Int32 m_Seconds; // seconds (0-59)
+ NPT_Int32 m_NanoSeconds; // nanoseconds (0-999999999)
+ NPT_Int32 m_TimeZone; // minutes offset from GMT
+};
+
+#endif // _NPT_TIME_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTls.cpp b/lib/libUPnP/Neptune/Source/Core/NptTls.cpp
new file mode 100644
index 0000000..594adbd
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTls.cpp
@@ -0,0 +1,1227 @@
+/*****************************************************************
+|
+| Neptune - TLS/SSL Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTls.h"
+#include "NptLogging.h"
+#include "NptUtils.h"
+#include "NptSockets.h"
+#include "NptSystem.h"
+#include "NptDigest.h"
+#include "NptAutomaticCleaner.h"
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.tls")
+
+#if defined(NPT_CONFIG_ENABLE_TLS)
+#include "ssl.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_TLS_CONTEXT_DEFAULT_SESSION_CACHE = 16;
+const unsigned int NPT_HTTP_TLS_CONNECTOR_MAX_PROXY_RESPONSE_SIZE = (16*1024);
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef NPT_Reference<NPT_TlsSessionImpl> NPT_TlsSessionImplReference;
+
+/*----------------------------------------------------------------------
+| SSL_DateTime_Before
++---------------------------------------------------------------------*/
+int
+SSL_DateTime_Before(const SSL_DateTime* t1, const SSL_DateTime* t2)
+{
+ if (t1->year == t2->year) {
+ if (t1->month == t2->month) {
+ if (t1->day == t2->day) {
+ return t1->hours*3600+t1->minutes*60+t1->seconds <
+ t2->hours*3600+t2->minutes*60+t2->seconds ? 1 : 0;
+ } else {
+ return t1->day < t2->day ? 1 : 0;
+ }
+ } else {
+ return t1->month < t2->month ? 1 : 0;
+ }
+ } else {
+ return t1->year < t2->year ? 1 : 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| SSL_DateTime_Now
++---------------------------------------------------------------------*/
+void
+SSL_DateTime_Now(SSL_DateTime* now)
+{
+ NPT_TimeStamp ts;
+ NPT_System::GetCurrentTimeStamp(ts);
+ NPT_DateTime dt;
+ dt.FromTimeStamp(ts);
+ now->year = dt.m_Year;
+ now->month = dt.m_Month;
+ now->day = dt.m_Day;
+ now->hours = dt.m_Hours;
+ now->minutes = dt.m_Minutes;
+ now->seconds = dt.m_Seconds;
+}
+
+/*----------------------------------------------------------------------
+| SSL_GetRandomSeed
++---------------------------------------------------------------------*/
+uint64_t
+SSL_GetRandomSeed()
+{
+ NPT_TimeStamp ts;
+ NPT_System::GetCurrentTimeStamp(ts);
+ return ts.ToNanos();
+}
+
+/*----------------------------------------------------------------------
+| SSL_Mutex_Create
++---------------------------------------------------------------------*/
+void
+SSL_Mutex_Create(NPT_Mutex** mutex)
+{
+ *mutex = new NPT_Mutex();
+}
+
+/*----------------------------------------------------------------------
+| SSL_Mutex_Destroy
++---------------------------------------------------------------------*/
+void
+SSL_Mutex_Destroy(NPT_Mutex* mutex)
+{
+ delete mutex;
+}
+
+/*----------------------------------------------------------------------
+| SSL_Mutex_Lock
++---------------------------------------------------------------------*/
+void
+SSL_Mutex_Lock(NPT_Mutex* mutex)
+{
+ mutex->Lock();
+}
+
+/*----------------------------------------------------------------------
+| SSL_Mutex_Lock
++---------------------------------------------------------------------*/
+void
+SSL_Mutex_Unlock(NPT_Mutex* mutex)
+{
+ mutex->Unlock();
+}
+
+/*----------------------------------------------------------------------
+| SSL_Sha256_ComputeDigest
++---------------------------------------------------------------------*/
+void
+SSL_Sha256_ComputeDigest(const unsigned char* data,
+ unsigned int data_size,
+ unsigned char* digest_value)
+{
+ NPT_Digest* digest = NULL;
+ NPT_Digest::Create(NPT_Digest::ALGORITHM_SHA256, digest);
+ digest->Update(data, data_size);
+ NPT_DataBuffer buffer;
+ digest->GetDigest(buffer);
+ NPT_CopyMemory(digest_value, buffer.GetData(), 32);
+ delete digest;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Tls::MatchDnsName
++---------------------------------------------------------------------*/
+bool
+NPT_Tls::MatchDnsName(const char* hostname, const char* dns_name)
+{
+ // NULL or empty names don't match anything
+ if (hostname == NULL || *hostname == '\0') return false;
+ if (dns_name == NULL || *dns_name == '\0') return false;
+
+ // check for wildcards */
+ if (dns_name[0] == '*') {
+ // wildcard match, expect '*.' at the start, we don't match '*foo.com'
+ if (dns_name[1] != '.') return false;
+
+ // skip the first component of the hostname
+ while (hostname[0] != '\0' && hostname[0] != '.') {
+ ++hostname;
+ }
+ if (hostname[0] == '.') ++hostname;
+
+ // compare the tails
+ return NPT_String::Compare(hostname, dns_name+2, true) == 0;
+ } else {
+ // full match
+ return NPT_String::Compare(hostname, dns_name, true) == 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Tls::MatchDnsNames
++---------------------------------------------------------------------*/
+bool
+NPT_Tls::MatchDnsNames(const char* hostname,
+ const NPT_List<NPT_String>& dns_names)
+{
+ // NULL or empty names don't match anything
+ if (hostname == NULL || *hostname == '\0') return false;
+
+ // check the dns names
+ for (NPT_List<NPT_String>::Iterator i = dns_names.GetFirstItem();
+ i;
+ ++i) {
+ if (MatchDnsName(hostname, (*i).GetChars())) return true;
+ }
+
+ // no match
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Tls_MapResult
++---------------------------------------------------------------------*/
+static NPT_Result
+NPT_Tls_MapResult(int err)
+{
+ switch (err) {
+ case SSL_ERROR_CONN_LOST: return NPT_ERROR_CONNECTION_ABORTED;
+ case SSL_ERROR_TIMEOUT: return NPT_ERROR_TIMEOUT;
+ case SSL_ERROR_EOS: return NPT_ERROR_EOS;
+ case SSL_CLOSE_NOTIFY: return NPT_ERROR_EOS;
+ case SSL_ERROR_NOT_SUPPORTED: return NPT_ERROR_NOT_SUPPORTED;
+ case SSL_ERROR_INVALID_HANDSHAKE: return NPT_ERROR_TLS_INVALID_HANDSHAKE;
+ case SSL_ERROR_INVALID_PROT_MSG: return NPT_ERROR_TLS_INVALID_PROTOCOL_MESSAGE;
+ case SSL_ERROR_INVALID_HMAC: return NPT_ERROR_TLS_INVALID_HMAC;
+ case SSL_ERROR_INVALID_VERSION: return NPT_ERROR_TLS_INVALID_VERSION;
+ case SSL_ERROR_INVALID_SESSION: return NPT_ERROR_TLS_INVALID_SESSION;
+ case SSL_ERROR_NO_CIPHER: return NPT_ERROR_TLS_NO_CIPHER;
+ case SSL_ERROR_BAD_CERTIFICATE: return NPT_ERROR_TLS_BAD_CERTIFICATE;
+ case SSL_ERROR_INVALID_KEY: return NPT_ERROR_TLS_INVALID_KEY;
+ case SSL_ERROR_FINISHED_INVALID: return NPT_ERROR_TLS_INVALID_FINISHED_MESSAGE;
+ case SSL_ERROR_NO_CERT_DEFINED: return NPT_ERROR_TLS_NO_CERTIFICATE_DEFINED;
+ case SSL_ERROR_NO_CLIENT_RENOG: return NPT_ERROR_TLS_NO_CLIENT_RENEGOTIATION;
+ case -SSL_ALERT_HANDSHAKE_FAILURE: return NPT_ERROR_TLS_ALERT_HANDSHAKE_FAILED;
+ case -SSL_ALERT_BAD_CERTIFICATE: return NPT_ERROR_TLS_ALERT_BAD_CERTIFICATE;
+ case -SSL_ALERT_INVALID_VERSION: return NPT_ERROR_TLS_ALERT_INVALID_VERSION;
+ case -SSL_ALERT_BAD_RECORD_MAC: return NPT_ERROR_TLS_ALERT_BAD_RECORD_MAC;
+ case -SSL_ALERT_DECODE_ERROR: return NPT_ERROR_TLS_ALERT_DECODE_ERROR;
+ case -SSL_ALERT_DECRYPT_ERROR: return NPT_ERROR_TLS_ALERT_DECRYPT_ERROR;
+ case -SSL_ALERT_ILLEGAL_PARAMETER: return NPT_ERROR_TLS_ALERT_ILLEGAL_PARAMETER;
+ case -SSL_ALERT_UNEXPECTED_MESSAGE: return NPT_ERROR_TLS_ALERT_UNEXPECTED_MESSAGE;
+ case SSL_X509_ERROR(X509_NOT_OK): return NPT_ERROR_TLS_CERTIFICATE_FAILURE;
+ case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): return NPT_ERROR_TLS_CERTIFICATE_NO_TRUST_ANCHOR;
+ case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): return NPT_ERROR_TLS_CERTIFICATE_BAD_SIGNATURE;
+ case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): return NPT_ERROR_TLS_CERTIFICATE_NOT_YET_VALID;
+ case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): return NPT_ERROR_TLS_CERTIFICATE_EXPIRED;
+ case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): return NPT_ERROR_TLS_CERTIFICATE_SELF_SIGNED;
+ case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): return NPT_ERROR_TLS_CERTIFICATE_INVALID_CHAIN;
+ case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): return NPT_ERROR_TLS_CERTIFICATE_UNSUPPORTED_DIGEST;
+ case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): return NPT_ERROR_TLS_CERTIFICATE_INVALID_PRIVATE_KEY;
+ case 0: return NPT_SUCCESS;
+ default: return NPT_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContextImpl
++---------------------------------------------------------------------*/
+class NPT_TlsContextImpl {
+public:
+ NPT_TlsContextImpl(NPT_Flags options) :
+ m_SSL_CTX(ssl_ctx_new(((options & NPT_TlsContext::OPTION_VERIFY_LATER)?SSL_SERVER_VERIFY_LATER:0) |
+ ((options & NPT_TlsContext::OPTION_REQUIRE_CLIENT_CERTIFICATE)?SSL_CLIENT_AUTHENTICATION:0),
+ (options & NPT_TlsContext::OPTION_NO_SESSION_CACHE)?0:NPT_TLS_CONTEXT_DEFAULT_SESSION_CACHE)) {}
+ ~NPT_TlsContextImpl() { ssl_ctx_free(m_SSL_CTX); }
+
+ NPT_Result LoadKey(NPT_TlsKeyFormat key_format,
+ const unsigned char* key_data,
+ NPT_Size key_data_size,
+ const char* password);
+ NPT_Result SelfSignCertificate(const char* common_name,
+ const char* organization,
+ const char* organizational_name);
+ NPT_Result AddTrustAnchor(const unsigned char* ta_data,
+ NPT_Size ta_data_size);
+
+ SSL_CTX* m_SSL_CTX;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsContextImpl::LoadKey
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContextImpl::LoadKey(NPT_TlsKeyFormat key_format,
+ const unsigned char* key_data,
+ NPT_Size key_data_size,
+ const char* password)
+{
+ int object_type;
+ switch (key_format) {
+ case NPT_TLS_KEY_FORMAT_RSA_PRIVATE: object_type = SSL_OBJ_RSA_KEY; break;
+ case NPT_TLS_KEY_FORMAT_PKCS8: object_type = SSL_OBJ_PKCS8; break;
+ case NPT_TLS_KEY_FORMAT_PKCS12: object_type = SSL_OBJ_PKCS12; break;
+ default: return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ int result = ssl_obj_memory_load(m_SSL_CTX, object_type, key_data, key_data_size, password);
+ return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContextImpl::SelfSignCertificate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContextImpl::SelfSignCertificate(const char* common_name,
+ const char* organization,
+ const char* organizational_name)
+{
+ const char* dn[3] = {common_name, organization, organizational_name};
+ uint8_t* certificate = NULL;
+ int result = ssl_x509_create(m_SSL_CTX, 0, dn, &certificate);
+ if (result <= 0) {
+ if (certificate) {
+ ssl_mem_free(certificate);
+ }
+ return NPT_Tls_MapResult(result);
+ }
+ result = ssl_obj_memory_load(m_SSL_CTX, SSL_OBJ_X509_CERT, certificate, result, NULL);
+ ssl_mem_free(certificate);
+
+ return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContextImpl::AddTrustAnchor
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContextImpl::AddTrustAnchor(const unsigned char* ta_data,
+ NPT_Size ta_data_size)
+{
+ int result = ssl_obj_memory_load(m_SSL_CTX, SSL_OBJ_X509_CACERT, ta_data, ta_data_size, NULL);
+ return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsStreamAdapter
++---------------------------------------------------------------------*/
+struct NPT_TlsStreamAdapter
+{
+ static int Read(SSL_SOCKET* _self, void* buffer, unsigned int size) {
+ NPT_TlsStreamAdapter* self = (NPT_TlsStreamAdapter*)_self;
+ NPT_Size bytes_read = 0;
+ NPT_Result result = self->m_Input->Read(buffer, size, &bytes_read);
+ if (NPT_FAILED(result)) {
+ switch (result) {
+ case NPT_ERROR_EOS: return SSL_ERROR_EOS;
+ case NPT_ERROR_TIMEOUT: return SSL_ERROR_TIMEOUT;
+ default: return SSL_ERROR_CONN_LOST;
+ }
+ }
+ return bytes_read;
+ }
+
+ static int Write(SSL_SOCKET* _self, const void* buffer, unsigned int size) {
+ NPT_TlsStreamAdapter* self = (NPT_TlsStreamAdapter*)_self;
+ NPT_Size bytes_written = 0;
+ NPT_Result result = self->m_Output->Write(buffer, size, &bytes_written);
+ if (NPT_FAILED(result)) {
+ switch (result) {
+ case NPT_ERROR_EOS: return SSL_ERROR_EOS;
+ case NPT_ERROR_TIMEOUT: return SSL_ERROR_TIMEOUT;
+ default: return SSL_ERROR_CONN_LOST;
+ }
+ }
+ return bytes_written;
+ }
+
+ NPT_TlsStreamAdapter(NPT_InputStreamReference input,
+ NPT_OutputStreamReference output) :
+ m_Input(input), m_Output(output) {
+ m_Base.Read = Read;
+ m_Base.Write = Write;
+ }
+
+ SSL_SOCKET m_Base;
+ NPT_InputStreamReference m_Input;
+ NPT_OutputStreamReference m_Output;
+};
+
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl
++---------------------------------------------------------------------*/
+class NPT_TlsSessionImpl {
+public:
+ NPT_TlsSessionImpl(SSL_CTX* context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output) :
+ m_SSL_CTX(context),
+ m_SSL(NULL),
+ m_StreamAdapter(input, output) {}
+ virtual ~NPT_TlsSessionImpl() { ssl_free(m_SSL); }
+
+ // methods
+ virtual NPT_Result Handshake() = 0;
+ virtual NPT_Result GetHandshakeStatus();
+ virtual NPT_Result VerifyPeerCertificate();
+ virtual NPT_Result VerifyDnsNameMatch(const char* hostname);
+ virtual NPT_Result GetSessionId(NPT_DataBuffer& session_id);
+ virtual NPT_UInt32 GetCipherSuiteId();
+ virtual NPT_Result GetPeerCertificateInfo(NPT_TlsCertificateInfo& cert_info,
+ NPT_Ordinal position);
+
+ // members
+ SSL_CTX* m_SSL_CTX;
+ SSL* m_SSL;
+ NPT_TlsStreamAdapter m_StreamAdapter;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl::GetHandshakeStatus
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::GetHandshakeStatus()
+{
+ int status;
+ if (m_SSL == NULL || (status = ssl_handshake_status(m_SSL)) == SSL_NOT_OK) {
+ // no handshake done
+ return NPT_ERROR_INVALID_STATE;
+ }
+
+ return NPT_Tls_MapResult(status);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl::VerifyPeerCertificate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::VerifyPeerCertificate()
+{
+ if (m_SSL == NULL || ssl_handshake_status(m_SSL) == SSL_NOT_OK) {
+ // no handshake done
+ return NPT_ERROR_INVALID_STATE;
+ }
+
+ int result = ssl_verify_cert(m_SSL);
+ return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl::VerifyDnsNameMatch
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::VerifyDnsNameMatch(const char* hostname)
+{
+ if (hostname == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+ if (m_SSL == NULL || ssl_handshake_status(m_SSL) == SSL_NOT_OK) {
+ // no handshake done
+ return NPT_ERROR_INVALID_STATE;
+ }
+
+ // get the peer certificate
+ const SSL_X509_CERT* cert = ssl_get_peer_cert(m_SSL, 0);
+ if (cert == NULL) return NPT_ERROR_NO_SUCH_ITEM;
+
+ // try the common name
+ const char* common_name = ssl_cert_get_dn(cert, SSL_X509_CERT_COMMON_NAME);
+ if (common_name && NPT_Tls::MatchDnsName(hostname, common_name)) return NPT_SUCCESS;
+
+ // try all the alt DNS names
+ const char* alt_name = NULL;
+ for (unsigned int i=0; (alt_name=ssl_cert_get_subject_alt_dnsname(cert, i)); i++) {
+ if (NPT_Tls::MatchDnsName(hostname, alt_name)) return NPT_SUCCESS;
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl::GetSessionId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::GetSessionId(NPT_DataBuffer& session_id)
+{
+ if (m_SSL == NULL || ssl_handshake_status(m_SSL) == SSL_NOT_OK) {
+ // no handshake done
+ session_id.SetDataSize(0);
+ return NPT_ERROR_INVALID_STATE;
+ }
+
+ // return the session id
+ session_id.SetData(ssl_get_session_id(m_SSL),
+ ssl_get_session_id_size(m_SSL));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl::GetCipherSuiteId
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_TlsSessionImpl::GetCipherSuiteId()
+{
+ if (m_SSL == NULL || ssl_handshake_status(m_SSL) == SSL_NOT_OK) {
+ // no handshake done
+ return 0;
+ }
+
+ return ssl_get_cipher_id(m_SSL);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSessionImpl::GetPeerCertificateInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::GetPeerCertificateInfo(NPT_TlsCertificateInfo& cert_info,
+ NPT_Ordinal position)
+{
+ if (m_SSL == NULL || ssl_handshake_status(m_SSL) == SSL_NOT_OK) {
+ // no handshake done
+ return NPT_ERROR_INVALID_STATE;
+ }
+
+ // find the certificate at the requested index
+ const SSL_X509_CERT* cert = ssl_get_peer_cert(m_SSL, position);
+ if (cert == NULL) return NPT_ERROR_NO_SUCH_ITEM;
+
+ // get the certificate fields
+ cert_info.subject.common_name = ssl_cert_get_dn(cert, SSL_X509_CERT_COMMON_NAME);
+ cert_info.subject.organization = ssl_cert_get_dn(cert, SSL_X509_CERT_ORGANIZATION);
+ cert_info.subject.organizational_name = ssl_cert_get_dn(cert, SSL_X509_CERT_ORGANIZATIONAL_NAME);
+ cert_info.issuer.common_name = ssl_cert_get_dn(cert, SSL_X509_CA_CERT_COMMON_NAME);
+ cert_info.issuer.organization = ssl_cert_get_dn(cert, SSL_X509_CA_CERT_ORGANIZATION);
+ cert_info.issuer.organizational_name = ssl_cert_get_dn(cert, SSL_X509_CA_CERT_ORGANIZATIONAL_NAME);
+
+ ssl_cert_get_fingerprints(cert, cert_info.fingerprint.md5, cert_info.fingerprint.sha1);
+ SSL_DateTime not_before, not_after;
+ ssl_cert_get_validity_dates(cert, &not_before, &not_after);
+ cert_info.issue_date.m_Year = not_before.year;
+ cert_info.issue_date.m_Month = not_before.month;
+ cert_info.issue_date.m_Day = not_before.day;
+ cert_info.issue_date.m_Hours = not_before.hours;
+ cert_info.issue_date.m_Minutes = not_before.minutes;
+ cert_info.issue_date.m_Seconds = not_before.seconds;
+ cert_info.issue_date.m_NanoSeconds = 0;
+ cert_info.issue_date.m_TimeZone = 0;
+ cert_info.expiration_date.m_Year = not_after.year;
+ cert_info.expiration_date.m_Month = not_after.month;
+ cert_info.expiration_date.m_Day = not_after.day;
+ cert_info.expiration_date.m_Hours = not_after.hours;
+ cert_info.expiration_date.m_Minutes = not_after.minutes;
+ cert_info.expiration_date.m_Seconds = not_after.seconds;
+ cert_info.expiration_date.m_NanoSeconds = 0;
+ cert_info.expiration_date.m_TimeZone = 0;
+
+ // alternate names
+ cert_info.alternate_names.Clear();
+ const char* alt_name = NULL;
+ for (unsigned int i=0; (alt_name=ssl_cert_get_subject_alt_dnsname(cert, i)); i++) {
+ cert_info.alternate_names.Add(NPT_String(alt_name));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsClientSessionImpl
++---------------------------------------------------------------------*/
+class NPT_TlsClientSessionImpl : public NPT_TlsSessionImpl {
+public:
+ NPT_TlsClientSessionImpl(SSL_CTX* context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output) :
+ NPT_TlsSessionImpl(context, input, output) {}
+
+ // methods
+ virtual NPT_Result Handshake();
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsClientSessionImpl::Handshake
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsClientSessionImpl::Handshake()
+{
+ if (m_SSL == NULL) {
+ // we have not created the client object yet
+ m_SSL = ssl_client_new(m_SSL_CTX, &m_StreamAdapter.m_Base, NULL, 0);
+ }
+
+ int result = ssl_handshake_status(m_SSL);
+ return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsServerSessionImpl
++---------------------------------------------------------------------*/
+class NPT_TlsServerSessionImpl : public NPT_TlsSessionImpl {
+public:
+ NPT_TlsServerSessionImpl(SSL_CTX* context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output) :
+ NPT_TlsSessionImpl(context, input, output) {}
+
+ // methods
+ virtual NPT_Result Handshake();
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsServerSessionImpl::Handshake
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsServerSessionImpl::Handshake()
+{
+ if (m_SSL == NULL) {
+ // we have not created the server object yet
+ m_SSL = ssl_server_new(m_SSL_CTX, &m_StreamAdapter.m_Base);
+ }
+
+ uint8_t* data = NULL;
+ int result;
+ while ((result = ssl_handshake_status(m_SSL)) == SSL_NOT_OK) {
+ result = ssl_read(m_SSL, &data);
+ if (result != SSL_OK) break;
+ if (data != NULL) {
+ NPT_LOG_WARNING("got data during handshake???");
+ return NPT_ERROR_INTERNAL;
+ }
+ }
+ return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsInputStream
++---------------------------------------------------------------------*/
+class NPT_TlsInputStream : public NPT_InputStream {
+public:
+ NPT_TlsInputStream(NPT_TlsSessionImplReference& session) :
+ m_Session(session),
+ m_Position(0),
+ m_RecordCacheData(NULL),
+ m_RecordCacheSize(0) {}
+
+ // NPT_InputStream methods
+ virtual NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL);
+ virtual NPT_Result Seek(NPT_Position) { return NPT_ERROR_NOT_SUPPORTED; }
+ virtual NPT_Result Tell(NPT_Position& offset) { offset = m_Position; return NPT_SUCCESS; }
+ virtual NPT_Result GetSize(NPT_LargeSize& size) { size=0; return NPT_ERROR_NOT_SUPPORTED; }
+ virtual NPT_Result GetAvailable(NPT_LargeSize& available);
+
+private:
+ NPT_TlsSessionImplReference m_Session;
+ NPT_Position m_Position;
+ uint8_t* m_RecordCacheData;
+ NPT_Size m_RecordCacheSize;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ // setup default values
+ if (bytes_read) *bytes_read = 0;
+
+ // quick check for edge case
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // read a new record if we don't have one cached
+ if (m_RecordCacheData == NULL) {
+ int ssl_result;
+ do {
+ ssl_result = ssl_read(m_Session->m_SSL, &m_RecordCacheData);
+ } while (ssl_result == 0);
+ if (ssl_result < 0) {
+ return NPT_Tls_MapResult(ssl_result);
+ }
+ m_RecordCacheSize = ssl_result;
+ }
+
+ // we now have data in cache
+ if (bytes_to_read > m_RecordCacheSize) {
+ // read at most what's in the cache
+ bytes_to_read = m_RecordCacheSize;
+ }
+ NPT_CopyMemory(buffer, m_RecordCacheData, bytes_to_read);
+ if (bytes_read) *bytes_read = bytes_to_read;
+
+ // update the record cache
+ m_RecordCacheSize -= bytes_to_read;
+ if (m_RecordCacheSize == 0) {
+ // nothing left in the cache
+ m_RecordCacheData = NULL;
+ } else {
+ // move the cache pointer
+ m_RecordCacheData += bytes_to_read;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsInputStream::GetAvailable(NPT_LargeSize& /*available*/)
+{
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsOutputStream
++---------------------------------------------------------------------*/
+class NPT_TlsOutputStream : public NPT_OutputStream {
+public:
+ NPT_TlsOutputStream(NPT_TlsSessionImplReference& session) :
+ m_Session(session),
+ m_Position(0) {}
+
+ // NPT_OutputStream methods
+ virtual NPT_Result Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written = NULL);
+ virtual NPT_Result Seek(NPT_Position) { return NPT_ERROR_NOT_SUPPORTED; }
+ virtual NPT_Result Tell(NPT_Position& offset) { offset = m_Position; return NPT_SUCCESS; }
+
+private:
+ NPT_TlsSessionImplReference m_Session;
+ NPT_Position m_Position;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsOutputStream::Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written)
+{
+ // setup default values
+ if (bytes_written) *bytes_written = 0;
+
+ // quick check for edge case
+ if (bytes_to_write == 0) return NPT_SUCCESS;
+
+ // write some data
+ int ssl_result;
+ do {
+ ssl_result = ssl_write(m_Session->m_SSL, (const uint8_t*)buffer, bytes_to_write);
+ } while (ssl_result == 0);
+ if (ssl_result < 0) {
+ return NPT_Tls_MapResult(ssl_result);
+ }
+ m_Position += ssl_result;
+ if (bytes_written) *bytes_written = (NPT_Size)ssl_result;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Tls::GetDefaultTrustAnchors
++---------------------------------------------------------------------*/
+const NPT_TlsTrustAnchorData*
+NPT_Tls::GetDefaultTrustAnchors(NPT_Ordinal indx)
+{
+ if (indx == 0) {
+ return NptTlsDefaultTrustAnchorsBase;
+ } else if (indx == 2) {
+ return NptTlsDefaultTrustAnchorsExtended;
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext::NPT_TlsContext
++---------------------------------------------------------------------*/
+NPT_TlsContext::NPT_TlsContext(NPT_Flags options) :
+ m_Impl(new NPT_TlsContextImpl(options))
+{
+ if (options & OPTION_ADD_DEFAULT_TRUST_ANCHORS) {
+ const NPT_TlsTrustAnchorData* ta = NPT_Tls::GetDefaultTrustAnchors(0);
+ if (ta) {
+ AddTrustAnchors(ta);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext::~NPT_TlsContext
++---------------------------------------------------------------------*/
+NPT_TlsContext::~NPT_TlsContext()
+{
+ delete m_Impl;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext::LoadKey
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContext::LoadKey(NPT_TlsKeyFormat key_format,
+ const unsigned char* key_data,
+ NPT_Size key_data_size,
+ const char* password)
+{
+ return m_Impl->LoadKey(key_format, key_data, key_data_size, password);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext::SelfSignCertificate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContext::SelfSignCertificate(const char* common_name,
+ const char* organization,
+ const char* organizational_name)
+{
+ return m_Impl->SelfSignCertificate(common_name, organization, organizational_name);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext::AddTrustAnchor
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContext::AddTrustAnchor(const unsigned char* ta_data,
+ NPT_Size ta_data_size)
+{
+ return m_Impl->AddTrustAnchor(ta_data, ta_data_size);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext::AddTrustAnchors
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsContext::AddTrustAnchors(const NPT_TlsTrustAnchorData* anchors,
+ NPT_Cardinal anchor_count)
+{
+ if (anchors == NULL) return NPT_SUCCESS;
+ for (unsigned int i=0;
+ anchor_count ?
+ (i<anchor_count) :
+ (anchors[i].cert_data && anchors[i].cert_size);
+ i++) {
+ // add the trust anchor and ignore the error
+ m_Impl->AddTrustAnchor(anchors[i].cert_data, anchors[i].cert_size);
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::NPT_TlsSession
++---------------------------------------------------------------------*/
+NPT_TlsSession::NPT_TlsSession(NPT_TlsContext& context,
+ NPT_TlsSessionImpl* impl) :
+ m_Context(context),
+ m_Impl(impl),
+ m_InputStream(new NPT_TlsInputStream(m_Impl)),
+ m_OutputStream(new NPT_TlsOutputStream(m_Impl))
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::~NPT_TlsSession
++---------------------------------------------------------------------*/
+NPT_TlsSession::~NPT_TlsSession()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::Handshake
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::Handshake()
+{
+ return m_Impl->Handshake();
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::GetHandshakeStatus
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::GetHandshakeStatus()
+{
+ return m_Impl->GetHandshakeStatus();
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::VerifyPeerCertificate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::VerifyPeerCertificate()
+{
+ return m_Impl->VerifyPeerCertificate();
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::VerifyDnsNameMatch
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::VerifyDnsNameMatch(const char* hostname)
+{
+ return m_Impl->VerifyDnsNameMatch(hostname);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsClientSession::GetSessionId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::GetSessionId(NPT_DataBuffer& session_id)
+{
+ return m_Impl->GetSessionId(session_id);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::GetCipherSuiteId
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_TlsSession::GetCipherSuiteId()
+{
+ return m_Impl->GetCipherSuiteId();
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::GetPeerCertificateInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::GetPeerCertificateInfo(NPT_TlsCertificateInfo& cert_info,
+ unsigned int position)
+{
+ return m_Impl->GetPeerCertificateInfo(cert_info, position);
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::GetInputStream(NPT_InputStreamReference& stream)
+{
+ stream = m_InputStream;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSession::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+ stream = m_OutputStream;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsClientSession::NPT_TlsClientSession
++---------------------------------------------------------------------*/
+NPT_TlsClientSession::NPT_TlsClientSession(NPT_TlsContext& context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output) :
+ NPT_TlsSession(context, new NPT_TlsClientSessionImpl(context.m_Impl->m_SSL_CTX, input, output))
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_TlsServerSession::NPT_TlsServerSession
++---------------------------------------------------------------------*/
+NPT_TlsServerSession::NPT_TlsServerSession(NPT_TlsContext& context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output) :
+ NPT_TlsSession(context, new NPT_TlsServerSessionImpl(context.m_Impl->m_SSL_CTX, input, output))
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector::DefaultTlsContext
++---------------------------------------------------------------------*/
+NPT_TlsContext* NPT_HttpTlsConnector::DefaultTlsContext = NULL;
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector::NPT_HttpTlsConnector
++---------------------------------------------------------------------*/
+NPT_HttpTlsConnector::NPT_HttpTlsConnector(NPT_Flags options) :
+ m_TlsContext(GetDefaultTlsContext()),
+ m_Options(options)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector::NPT_HttpTlsConnector
++---------------------------------------------------------------------*/
+NPT_HttpTlsConnector::NPT_HttpTlsConnector(NPT_TlsContext& tls_context, NPT_Flags options) :
+ m_TlsContext(tls_context),
+ m_Options(options)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector::GetDefaultTlsContext
++---------------------------------------------------------------------*/
+NPT_TlsContext&
+NPT_HttpTlsConnector::GetDefaultTlsContext()
+{
+ if (DefaultTlsContext == NULL) {
+ NPT_SingletonLock::GetInstance().Lock();
+ if (DefaultTlsContext == NULL) {
+ DefaultTlsContext = new NPT_TlsContext(NPT_TlsContext::OPTION_VERIFY_LATER |
+ NPT_TlsContext::OPTION_ADD_DEFAULT_TRUST_ANCHORS);
+
+ // Prepare for recycling
+ NPT_AutomaticCleaner::GetInstance()->RegisterTlsContext(DefaultTlsContext);
+ }
+ NPT_SingletonLock::GetInstance().Unlock();
+ }
+
+ return *DefaultTlsContext;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector::VerifyPeer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpTlsConnector::VerifyPeer(NPT_TlsClientSession& session, const char* hostname)
+{
+ // verify the certificate
+ NPT_Result result = session.VerifyPeerCertificate();
+ if (NPT_FAILED(result)) {
+ if (result == NPT_ERROR_TLS_CERTIFICATE_SELF_SIGNED) {
+ if (!m_Options && OPTION_ACCEPT_SELF_SIGNED_CERTS) {
+ // self-signed certs are not acceptable
+ NPT_LOG_FINE("rejecting self-signed certificate");
+ return result;
+ }
+ } else {
+ NPT_LOG_WARNING_2("TLS certificate verification failed (%d:%s)", result, NPT_ResultText(result));
+ return result;
+ }
+ }
+
+ // chech the DNS name
+ if (!(m_Options & OPTION_ACCEPT_HOSTNAME_MISMATCH)) {
+ // check the hostname
+ result = session.VerifyDnsNameMatch(hostname);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_2("TLS certificate does not match DNS name (%d:%s)", result, NPT_ResultText(result));
+ return NPT_ERROR_TLS_DNS_NAME_MISMATCH;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+#endif // defined(NPT_CONFIG_ENABLE_TLS)
+
+/*----------------------------------------------------------------------
+| NPT_HttpSimpleTlsConnection
++---------------------------------------------------------------------*/
+class NPT_HttpSimpleTlsConnection : public NPT_HttpClient::Connection
+{
+public:
+ NPT_InputStreamReference& GetInputStream() override {
+ return m_InputStream;
+ }
+ NPT_OutputStreamReference& GetOutputStream() override {
+ return m_OutputStream;
+ }
+
+ // members
+ NPT_InputStreamReference m_InputStream;
+ NPT_OutputStreamReference m_OutputStream;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpTlsConnector::Connect(const NPT_HttpUrl& url,
+ NPT_HttpClient& client,
+ const NPT_HttpProxyAddress* proxy,
+ bool reuse,
+ NPT_HttpClient::Connection*& connection)
+{
+ // default values
+ connection = NULL;
+
+ // local reference holders
+ NPT_InputStreamReference input_stream;
+ NPT_OutputStreamReference output_stream;
+
+ // decide which server we need to connect to
+ const char* peer_hostname = (const char*)url.GetHost();
+ const char* server_hostname;
+ NPT_UInt16 server_port;
+ if (proxy) {
+ // the proxy is set
+ server_hostname = (const char*)proxy->GetHostName();
+ server_port = proxy->GetPort();
+ } else {
+ // no proxy: connect directly
+ server_hostname = peer_hostname;
+ server_port = url.GetPort();
+ }
+
+ // resolve the server address
+ NPT_IpAddress ip_address;
+ NPT_CHECK_FINE(ip_address.ResolveName(server_hostname, client.GetConfig().m_NameResolverTimeout));
+
+ // check if we can reuse a connection
+ // TODO: with this we don't yet support reusing a connection to a proxy
+ NPT_SocketAddress socket_address(ip_address, server_port);
+ NPT_HttpConnectionManager* connection_manager = NPT_HttpConnectionManager::GetInstance();
+ if (!proxy && reuse) {
+ NPT_LOG_FINE("looking for a connection to reuse");
+ connection = connection_manager->FindConnection(socket_address);
+ if (connection) {
+ NPT_LOG_FINE("reusing connection");
+ // track connection immediately so we can abort it later
+ NPT_CHECK_FINE(Connector::TrackConnection(client, connection));
+ return NPT_SUCCESS;
+ }
+ }
+
+ // create a socket
+ NPT_LOG_FINE_2("TLS connector will connect to %s:%d", server_hostname, server_port);
+ NPT_TcpClientSocket* tcp_socket = new NPT_TcpClientSocket(NPT_SOCKET_FLAG_CANCELLABLE);
+ NPT_SocketReference socket(tcp_socket);
+ tcp_socket->SetReadTimeout(client.GetConfig().m_IoTimeout);
+ tcp_socket->SetWriteTimeout(client.GetConfig().m_IoTimeout);
+
+ // create a connection object for the socket so we can abort it during connect
+ // even though streams are not valid yet
+ NPT_Reference<NPT_HttpConnectionManager::Connection> cref(new NPT_HttpConnectionManager::Connection(*connection_manager,
+ socket,
+ input_stream,
+ output_stream));
+ // track connection immediately before connecting so we can abort immediately it if necessary
+ NPT_CHECK_FINE(Connector::TrackConnection(client, cref.AsPointer()));
+
+ // connect to the server
+ NPT_CHECK_FINE(tcp_socket->Connect(socket_address, client.GetConfig().m_ConnectionTimeout));
+
+ // get the streams
+ NPT_InputStreamReference raw_input;
+ NPT_OutputStreamReference raw_output;
+ NPT_CHECK_FINE(tcp_socket->GetInputStream(raw_input));
+ NPT_CHECK_FINE(tcp_socket->GetOutputStream(raw_output));
+
+ if (url.GetSchemeId() == NPT_Url::SCHEME_ID_HTTPS) {
+#if defined(NPT_CONFIG_ENABLE_TLS)
+ if (proxy) {
+ // RFC 2817 CONNECT
+ NPT_String connect_host = url.GetHost() + ":" + NPT_String::FromInteger(url.GetPort());
+ NPT_String connect = "CONNECT " + connect_host + " HTTP/1.1\r\n"
+ "Host: " + connect_host + "\r\n\r\n";
+ NPT_Result result = raw_output->WriteFully(connect.GetChars(), connect.GetLength());
+ if (NPT_FAILED(result)) return result;
+ NPT_String connect_response;
+ connect_response.Reserve(1024);
+ bool connect_ok = false;
+ for (unsigned int x=0; x<NPT_HTTP_TLS_CONNECTOR_MAX_PROXY_RESPONSE_SIZE; x++) {
+ connect_response.Reserve(x+1);
+ result = raw_input->Read(connect_response.UseChars()+x, 1);
+ if (NPT_FAILED(result)) return result;
+ if (connect_response.GetChars()[x] == '\n') {
+ connect_response.SetLength(x+1);
+ if (!connect_ok) {
+ // check the connection result
+ NPT_LOG_FINE_1("proxy response: %s", connect_response.GetChars());
+ if (connect_response.GetLength() < 12) {
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+ if (!connect_response.StartsWith("HTTP/1.")) {
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+ if (connect_response[8] != ' ') {
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+ NPT_String status_code = connect_response.SubString(9, 3);
+ if (status_code != "200") {
+ NPT_LOG_WARNING_1("proxy response is not 200 (%s)", status_code.GetChars());
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+ connect_ok = true;
+ } else {
+ if (connect_response.EndsWith("\r\n\r\n")) {
+ // this is the end, my friend
+ break;
+ }
+ }
+ }
+ }
+ if (!connect_ok) {
+ return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+ }
+ }
+
+ // setup the TLS connection
+ NPT_TlsClientSession tls_session(m_TlsContext, raw_input, raw_output);
+ NPT_Result result = tls_session.Handshake();
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_2("TLS handshake failed (%d:%s)", result, NPT_ResultText(result));
+ return result;
+ }
+ result = VerifyPeer(tls_session, peer_hostname);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_2("VerifyPeer failed (%d:%s)", result, NPT_ResultText(result));
+ return result;
+ }
+
+ // return the TLS streams
+ tls_session.GetInputStream(input_stream);
+ tls_session.GetOutputStream(output_stream);
+#else
+ return NPT_ERROR_NOT_SUPPORTED;
+#endif
+ } else {
+ input_stream = raw_input;
+ output_stream = raw_output;
+ }
+
+ // update connection streams
+ cref->m_InputStream = input_stream;
+ cref->m_OutputStream = output_stream;
+
+ connection = cref.AsPointer();
+ cref.Detach(); // release the internal ref
+
+ return NPT_SUCCESS;
+}
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTls.h b/lib/libUPnP/Neptune/Source/Core/NptTls.h
new file mode 100644
index 0000000..d5459d6
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTls.h
@@ -0,0 +1,304 @@
+/*****************************************************************
+|
+| Neptune - TLS/SSL Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_TLS_H_
+#define _NPT_TLS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptStreams.h"
+#include "NptTime.h"
+#include "NptHttp.h"
+
+/*----------------------------------------------------------------------
+| error codes
++---------------------------------------------------------------------*/
+const NPT_Result NPT_ERROR_INVALID_PASSWORD = (NPT_ERROR_BASE_TLS-1);
+const NPT_Result NPT_ERROR_TLS_INVALID_HANDSHAKE = (NPT_ERROR_BASE_TLS-2);
+const NPT_Result NPT_ERROR_TLS_INVALID_PROTOCOL_MESSAGE = (NPT_ERROR_BASE_TLS-3);
+const NPT_Result NPT_ERROR_TLS_INVALID_HMAC = (NPT_ERROR_BASE_TLS-4);
+const NPT_Result NPT_ERROR_TLS_INVALID_VERSION = (NPT_ERROR_BASE_TLS-5);
+const NPT_Result NPT_ERROR_TLS_INVALID_SESSION = (NPT_ERROR_BASE_TLS-6);
+const NPT_Result NPT_ERROR_TLS_NO_CIPHER = (NPT_ERROR_BASE_TLS-7);
+const NPT_Result NPT_ERROR_TLS_BAD_CERTIFICATE = (NPT_ERROR_BASE_TLS-8);
+const NPT_Result NPT_ERROR_TLS_INVALID_KEY = (NPT_ERROR_BASE_TLS-9);
+const NPT_Result NPT_ERROR_TLS_NO_CLIENT_RENEGOTIATION = (NPT_ERROR_BASE_TLS-10);
+const NPT_Result NPT_ERROR_TLS_INVALID_FINISHED_MESSAGE = (NPT_ERROR_BASE_TLS-11);
+const NPT_Result NPT_ERROR_TLS_NO_CERTIFICATE_DEFINED = (NPT_ERROR_BASE_TLS-12);
+const NPT_Result NPT_ERROR_TLS_ALERT_HANDSHAKE_FAILED = (NPT_ERROR_BASE_TLS-13);
+const NPT_Result NPT_ERROR_TLS_ALERT_BAD_CERTIFICATE = (NPT_ERROR_BASE_TLS-14);
+const NPT_Result NPT_ERROR_TLS_ALERT_INVALID_VERSION = (NPT_ERROR_BASE_TLS-15);
+const NPT_Result NPT_ERROR_TLS_ALERT_BAD_RECORD_MAC = (NPT_ERROR_BASE_TLS-16);
+const NPT_Result NPT_ERROR_TLS_ALERT_DECODE_ERROR = (NPT_ERROR_BASE_TLS-17);
+const NPT_Result NPT_ERROR_TLS_ALERT_DECRYPT_ERROR = (NPT_ERROR_BASE_TLS-18);
+const NPT_Result NPT_ERROR_TLS_ALERT_ILLEGAL_PARAMETER = (NPT_ERROR_BASE_TLS-19);
+const NPT_Result NPT_ERROR_TLS_ALERT_UNEXPECTED_MESSAGE = (NPT_ERROR_BASE_TLS-20);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_FAILURE = (NPT_ERROR_BASE_TLS-21);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_NO_TRUST_ANCHOR = (NPT_ERROR_BASE_TLS-22);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_BAD_SIGNATURE = (NPT_ERROR_BASE_TLS-23);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_NOT_YET_VALID = (NPT_ERROR_BASE_TLS-24);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_EXPIRED = (NPT_ERROR_BASE_TLS-25);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_SELF_SIGNED = (NPT_ERROR_BASE_TLS-26);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_INVALID_CHAIN = (NPT_ERROR_BASE_TLS-27);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_UNSUPPORTED_DIGEST = (NPT_ERROR_BASE_TLS-28);
+const NPT_Result NPT_ERROR_TLS_CERTIFICATE_INVALID_PRIVATE_KEY = (NPT_ERROR_BASE_TLS-29);
+const NPT_Result NPT_ERROR_TLS_DNS_NAME_MISMATCH = (NPT_ERROR_BASE_TLS-30);
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_TLS_NULL_WITH_NULL_NULL = 0x00;
+const unsigned int NPT_TLS_RSA_WITH_RC4_128_MD5 = 0x04;
+const unsigned int NPT_TLS_RSA_WITH_RC4_128_SHA = 0x05;
+const unsigned int NPT_TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F;
+const unsigned int NPT_TLS_RSA_WITH_AES_256_CBC_SHA = 0x35;
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class NPT_TlsContextImpl;
+class NPT_TlsSessionImpl;
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef enum {
+ NPT_TLS_KEY_FORMAT_RSA_PRIVATE,
+ NPT_TLS_KEY_FORMAT_PKCS8,
+ NPT_TLS_KEY_FORMAT_PKCS12
+} NPT_TlsKeyFormat;
+
+struct NPT_TlsTrustAnchorData {
+ const unsigned char* cert_data;
+ unsigned int cert_size;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Tls
++---------------------------------------------------------------------*/
+class NPT_Tls
+{
+public:
+ static const NPT_TlsTrustAnchorData* GetDefaultTrustAnchors(NPT_Ordinal indx=0);
+ static bool MatchDnsNames(const char* hostname,
+ const NPT_List<NPT_String>& dns_names);
+ static bool MatchDnsName(const char* hostname, const char* dns_name);
+
+private:
+ NPT_Tls() {}; // don't instantiate
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsContext
++---------------------------------------------------------------------*/
+class NPT_TlsContext : public NPT_AutomaticCleaner::Singleton
+{
+public:
+ enum {
+ OPTION_VERIFY_LATER = 1,
+ OPTION_REQUIRE_CLIENT_CERTIFICATE = 2,
+ OPTION_ADD_DEFAULT_TRUST_ANCHORS = 4,
+ OPTION_NO_SESSION_CACHE = 8
+ };
+ NPT_TlsContext(NPT_Flags options=0);
+ ~NPT_TlsContext() override;
+
+ // methods
+ NPT_Result LoadKey(NPT_TlsKeyFormat key_format,
+ const unsigned char* key_data,
+ NPT_Size key_data_size,
+ const char* password);
+
+ NPT_Result SelfSignCertificate(const char* common_name,
+ const char* organization,
+ const char* organizational_name);
+
+ /**
+ * Add one trust anchor
+ */
+ NPT_Result AddTrustAnchor(const unsigned char* ta_data,
+ NPT_Size ta_data_size);
+ /**
+ * Add one or more trust anchors, from a list
+ * @param anchors Array of trust anchor data
+ * @param anchor_count Number of anchors in the array, or 0 if the array
+ * is terminated by a 'sentinel' (an anchor data with the field cert_data set
+ * to NULL and the field cert_size set to 0).
+ */
+ NPT_Result AddTrustAnchors(const NPT_TlsTrustAnchorData* anchors,
+ NPT_Cardinal anchor_count = 0);
+
+protected:
+ NPT_TlsContextImpl* m_Impl;
+
+ // friends
+ friend class NPT_TlsSession;
+ friend class NPT_TlsClientSession;
+ friend class NPT_TlsServerSession;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsCertificateInfo
++---------------------------------------------------------------------*/
+struct NPT_TlsCertificateInfo
+{
+ struct _subject {
+ NPT_String common_name;
+ NPT_String organization;
+ NPT_String organizational_name;
+ } subject;
+ struct _issuer {
+ NPT_String common_name;
+ NPT_String organization;
+ NPT_String organizational_name;
+ } issuer;
+ struct _fingerprint {
+ unsigned char sha1[20];
+ unsigned char md5[16];
+ } fingerprint;
+ NPT_DateTime issue_date;
+ NPT_DateTime expiration_date;
+ NPT_List<NPT_String> alternate_names;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsSession
++---------------------------------------------------------------------*/
+class NPT_TlsSession
+{
+public:
+ virtual ~NPT_TlsSession();
+ virtual NPT_Result Handshake();
+ virtual NPT_Result GetHandshakeStatus();
+ virtual NPT_Result GetPeerCertificateInfo(NPT_TlsCertificateInfo& info, NPT_Ordinal position=0);
+ virtual NPT_Result VerifyPeerCertificate();
+ virtual NPT_Result VerifyDnsNameMatch(const char* hostname);
+ virtual NPT_Result GetSessionId(NPT_DataBuffer& session_id);
+ virtual NPT_UInt32 GetCipherSuiteId();
+ virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+ virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+
+protected:
+ NPT_TlsSession(NPT_TlsContext& context,
+ NPT_TlsSessionImpl* impl);
+
+ NPT_TlsContext& m_Context;
+ NPT_Reference<NPT_TlsSessionImpl> m_Impl;
+ NPT_InputStreamReference m_InputStream;
+ NPT_OutputStreamReference m_OutputStream;
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsClientSession
++---------------------------------------------------------------------*/
+class NPT_TlsClientSession : public NPT_TlsSession
+{
+public:
+ NPT_TlsClientSession(NPT_TlsContext& context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output);
+};
+
+/*----------------------------------------------------------------------
+| NPT_TlsServerSession
++---------------------------------------------------------------------*/
+class NPT_TlsServerSession : public NPT_TlsSession
+{
+public:
+ NPT_TlsServerSession(NPT_TlsContext& context,
+ NPT_InputStreamReference& input,
+ NPT_OutputStreamReference& output);
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpTlsConnector
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_ENABLE_TLS)
+class NPT_HttpTlsConnector : public NPT_HttpClient::Connector
+{
+public:
+ enum {
+ OPTION_ACCEPT_SELF_SIGNED_CERTS = 1,
+ OPTION_ACCEPT_HOSTNAME_MISMATCH = 2
+ };
+ NPT_HttpTlsConnector(NPT_Flags options = 0);
+ NPT_HttpTlsConnector(NPT_TlsContext& tls_context, NPT_Flags options = 0);
+ virtual ~NPT_HttpTlsConnector() {}
+ NPT_TlsContext& GetTlsContext() { return m_TlsContext; }
+ virtual NPT_Result Connect(const NPT_HttpUrl& url,
+ NPT_HttpClient& client,
+ const NPT_HttpProxyAddress* proxy,
+ bool reuse,
+ NPT_HttpClient::Connection*& connection);
+
+ virtual NPT_Result VerifyPeer(NPT_TlsClientSession& session,
+ const char* hostname);
+
+private:
+ // class methods
+ static NPT_TlsContext& GetDefaultTlsContext();
+
+ // class members
+ static NPT_TlsContext* DefaultTlsContext;
+
+ // members
+ NPT_TlsContext& m_TlsContext;
+ NPT_Flags m_Options;
+};
+#else
+class NPT_HttpTlsConnector : public NPT_HttpClient::Connector
+{
+public:
+ ~NPT_HttpTlsConnector() override {}
+ NPT_Result Connect(const NPT_HttpUrl& url,
+ NPT_HttpClient& client,
+ const NPT_HttpProxyAddress* proxy,
+ bool reuse,
+ NPT_HttpClient::Connection*& connection) override;
+};
+#endif
+
+/*----------------------------------------------------------------------
+| Trust Anchors
++-----------------------------------------------------------------*/
+/**
+ * Arrays of trust anchors (each array element is of type NPT_TlsTrustAnchorData
+ * and the last element is a terminator element: the cert_data field is NULL
+ * and the cert_size field is 0
+ */
+#if defined(NPT_CONFIG_ENABLE_TLS)
+#include "NptTlsDefaultTrustAnchorsBase.h"
+#include "NptTlsDefaultTrustAnchorsExtended.h"
+#endif
+
+#endif // _NPT_TLS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsBase.h b/lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsBase.h
new file mode 100644
index 0000000..170cdb2
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsBase.h
@@ -0,0 +1,583 @@
+/*****************************************************************
+|
+| Neptune - Trust Anchors
+|
+| This file is automatically generated by a script, do not edit!
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+ /* This file is automatically generated by GenTrustAnchorsTables.py, do not edit */
+
+#include "NptTls.h"
+
+extern const NPT_TlsTrustAnchorData NptTlsDefaultTrustAnchorsBase[137];
+
+/* Verisign/RSA Secure Server CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0000_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0000_Data[];
+
+/* GTE CyberTrust Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0001_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0001_Data[];
+
+/* GTE CyberTrust Global Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0002_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0002_Data[];
+
+/* Thawte Personal Basic CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0003_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0003_Data[];
+
+/* Thawte Personal Premium CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0004_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0004_Data[];
+
+/* Thawte Personal Freemail CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0005_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0005_Data[];
+
+/* Thawte Server CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0006_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0006_Data[];
+
+/* Thawte Premium Server CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0007_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0007_Data[];
+
+/* Equifax Secure CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0008_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0008_Data[];
+
+/* Digital Signature Trust Co. Global CA 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0009_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0009_Data[];
+
+/* Digital Signature Trust Co. Global CA 3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0010_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0010_Data[];
+
+/* Digital Signature Trust Co. Global CA 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0011_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0011_Data[];
+
+/* Digital Signature Trust Co. Global CA 4 */
+extern const unsigned int NptTlsTrustAnchor_Base_0012_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0012_Data[];
+
+/* Verisign Class 1 Public Primary Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0013_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0013_Data[];
+
+/* Verisign Class 2 Public Primary Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0014_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0014_Data[];
+
+/* Verisign Class 3 Public Primary Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0015_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0015_Data[];
+
+/* Verisign Class 1 Public Primary Certification Authority - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0016_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0016_Data[];
+
+/* Verisign Class 2 Public Primary Certification Authority - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0017_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0017_Data[];
+
+/* Verisign Class 3 Public Primary Certification Authority - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0018_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0018_Data[];
+
+/* Verisign Class 4 Public Primary Certification Authority - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0019_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0019_Data[];
+
+/* GlobalSign Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0020_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0020_Data[];
+
+/* GlobalSign Root CA - R2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0021_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0021_Data[];
+
+/* ValiCert Class 1 VA */
+extern const unsigned int NptTlsTrustAnchor_Base_0022_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0022_Data[];
+
+/* ValiCert Class 2 VA */
+extern const unsigned int NptTlsTrustAnchor_Base_0023_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0023_Data[];
+
+/* RSA Root Certificate 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0024_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0024_Data[];
+
+/* Verisign Class 1 Public Primary Certification Authority - G3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0025_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0025_Data[];
+
+/* Verisign Class 2 Public Primary Certification Authority - G3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0026_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0026_Data[];
+
+/* Verisign Class 3 Public Primary Certification Authority - G3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0027_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0027_Data[];
+
+/* Verisign Class 4 Public Primary Certification Authority - G3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0028_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0028_Data[];
+
+/* Entrust.net Secure Server CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0029_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0029_Data[];
+
+/* Entrust.net Secure Personal CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0030_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0030_Data[];
+
+/* Entrust.net Premium 2048 Secure Server CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0031_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0031_Data[];
+
+/* Baltimore CyberTrust Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0032_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0032_Data[];
+
+/* Equifax Secure Global eBusiness CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0033_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0033_Data[];
+
+/* Equifax Secure eBusiness CA 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0034_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0034_Data[];
+
+/* Equifax Secure eBusiness CA 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0035_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0035_Data[];
+
+/* Visa International Global Root 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0036_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0036_Data[];
+
+/* AddTrust Low-Value Services Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0037_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0037_Data[];
+
+/* AddTrust External Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0038_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0038_Data[];
+
+/* AddTrust Public Services Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0039_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0039_Data[];
+
+/* AddTrust Qualified Certificates Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0040_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0040_Data[];
+
+/* Verisign Time Stamping Authority CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0041_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0041_Data[];
+
+/* Thawte Time Stamping CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0042_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0042_Data[];
+
+/* Entrust.net Global Secure Server CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0043_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0043_Data[];
+
+/* Entrust.net Global Secure Personal CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0044_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0044_Data[];
+
+/* Entrust Root Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0045_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0045_Data[];
+
+/* AOL Time Warner Root Certification Authority 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0046_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0046_Data[];
+
+/* AOL Time Warner Root Certification Authority 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0047_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0047_Data[];
+
+/* beTRUSTed Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0048_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0048_Data[];
+
+/* beTRUSTed Root CA-Baltimore Implementation */
+extern const unsigned int NptTlsTrustAnchor_Base_0049_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0049_Data[];
+
+/* beTRUSTed Root CA - Entrust Implementation */
+extern const unsigned int NptTlsTrustAnchor_Base_0050_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0050_Data[];
+
+/* beTRUSTed Root CA - RSA Implementation */
+extern const unsigned int NptTlsTrustAnchor_Base_0051_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0051_Data[];
+
+/* RSA Security 2048 v3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0052_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0052_Data[];
+
+/* RSA Security 1024 v3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0053_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0053_Data[];
+
+/* GeoTrust Global CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0054_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0054_Data[];
+
+/* GeoTrust Global CA 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0055_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0055_Data[];
+
+/* GeoTrust Universal CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0056_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0056_Data[];
+
+/* GeoTrust Universal CA 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0057_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0057_Data[];
+
+/* UTN-USER First-Network Applications */
+extern const unsigned int NptTlsTrustAnchor_Base_0058_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0058_Data[];
+
+/* America Online Root Certification Authority 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0059_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0059_Data[];
+
+/* America Online Root Certification Authority 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0060_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0060_Data[];
+
+/* Visa eCommerce Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0061_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0061_Data[];
+
+/* TC TrustCenter, Germany, Class 2 CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0062_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0062_Data[];
+
+/* TC TrustCenter, Germany, Class 3 CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0063_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0063_Data[];
+
+/* Certum Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0064_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0064_Data[];
+
+/* Comodo AAA Services root */
+extern const unsigned int NptTlsTrustAnchor_Base_0065_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0065_Data[];
+
+/* Comodo Secure Services root */
+extern const unsigned int NptTlsTrustAnchor_Base_0066_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0066_Data[];
+
+/* Comodo Trusted Services root */
+extern const unsigned int NptTlsTrustAnchor_Base_0067_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0067_Data[];
+
+/* IPS Chained CAs root */
+extern const unsigned int NptTlsTrustAnchor_Base_0068_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0068_Data[];
+
+/* IPS CLASE1 root */
+extern const unsigned int NptTlsTrustAnchor_Base_0069_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0069_Data[];
+
+/* IPS CLASE3 root */
+extern const unsigned int NptTlsTrustAnchor_Base_0070_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0070_Data[];
+
+/* IPS CLASEA1 root */
+extern const unsigned int NptTlsTrustAnchor_Base_0071_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0071_Data[];
+
+/* IPS CLASEA3 root */
+extern const unsigned int NptTlsTrustAnchor_Base_0072_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0072_Data[];
+
+/* IPS Servidores root */
+extern const unsigned int NptTlsTrustAnchor_Base_0073_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0073_Data[];
+
+/* IPS Timestamping root */
+extern const unsigned int NptTlsTrustAnchor_Base_0074_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0074_Data[];
+
+/* QuoVadis Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0075_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0075_Data[];
+
+/* QuoVadis Root CA 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0076_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0076_Data[];
+
+/* QuoVadis Root CA 3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0077_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0077_Data[];
+
+/* Security Communication Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0078_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0078_Data[];
+
+/* Sonera Class 1 Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0079_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0079_Data[];
+
+/* Sonera Class 2 Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0080_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0080_Data[];
+
+/* Staat der Nederlanden Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0081_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0081_Data[];
+
+/* TDC Internet Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0082_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0082_Data[];
+
+/* TDC OCES Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0083_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0083_Data[];
+
+/* UTN DATACorp SGC Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0084_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0084_Data[];
+
+/* UTN USERFirst Email Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0085_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0085_Data[];
+
+/* UTN USERFirst Hardware Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0086_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0086_Data[];
+
+/* UTN USERFirst Object Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0087_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0087_Data[];
+
+/* Camerfirma Chambers of Commerce Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0088_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0088_Data[];
+
+/* Camerfirma Global Chambersign Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0089_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0089_Data[];
+
+/* NetLock Qualified (Class QA) Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0090_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0090_Data[];
+
+/* NetLock Notary (Class A) Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0091_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0091_Data[];
+
+/* NetLock Business (Class B) Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0092_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0092_Data[];
+
+/* NetLock Express (Class C) Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0093_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0093_Data[];
+
+/* XRamp Global CA Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0094_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0094_Data[];
+
+/* Go Daddy Class 2 CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0095_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0095_Data[];
+
+/* Starfield Class 2 CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0096_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0096_Data[];
+
+/* StartCom Ltd. */
+extern const unsigned int NptTlsTrustAnchor_Base_0097_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0097_Data[];
+
+/* StartCom Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0098_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0098_Data[];
+
+/* Firmaprofesional Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0099_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0099_Data[];
+
+/* Wells Fargo Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0100_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0100_Data[];
+
+/* Swisscom Root CA 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0101_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0101_Data[];
+
+/* DigiCert Assured ID Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0102_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0102_Data[];
+
+/* DigiCert Global Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0103_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0103_Data[];
+
+/* DigiCert High Assurance EV Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0104_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0104_Data[];
+
+/* Certplus Class 2 Primary CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0105_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0105_Data[];
+
+/* DST Root CA X3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0106_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0106_Data[];
+
+/* DST ACES CA X6 */
+extern const unsigned int NptTlsTrustAnchor_Base_0107_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0107_Data[];
+
+/* SwissSign Platinum CA - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0108_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0108_Data[];
+
+/* SwissSign Gold CA - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0109_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0109_Data[];
+
+/* SwissSign Silver CA - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0110_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0110_Data[];
+
+/* GeoTrust Primary Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0111_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0111_Data[];
+
+/* thawte Primary Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0112_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0112_Data[];
+
+/* VeriSign Class 3 Public Primary Certification Authority - G5 */
+extern const unsigned int NptTlsTrustAnchor_Base_0113_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0113_Data[];
+
+/* SecureTrust CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0114_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0114_Data[];
+
+/* Secure Global CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0115_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0115_Data[];
+
+/* COMODO Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0116_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0116_Data[];
+
+/* DigiNotar Root CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0117_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0117_Data[];
+
+/* Network Solutions Certificate Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0118_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0118_Data[];
+
+/* WellsSecure Public Root Certificate Authority */
+extern const unsigned int NptTlsTrustAnchor_Base_0119_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0119_Data[];
+
+/* IGC/A */
+extern const unsigned int NptTlsTrustAnchor_Base_0120_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0120_Data[];
+
+/* Security Communication EV RootCA1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0121_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0121_Data[];
+
+/* TC TrustCenter Class 2 CA II */
+extern const unsigned int NptTlsTrustAnchor_Base_0122_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0122_Data[];
+
+/* TC TrustCenter Class 3 CA II */
+extern const unsigned int NptTlsTrustAnchor_Base_0123_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0123_Data[];
+
+/* TC TrustCenter Universal CA I */
+extern const unsigned int NptTlsTrustAnchor_Base_0124_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0124_Data[];
+
+/* Deutsche Telekom Root CA 2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0125_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0125_Data[];
+
+/* ComSign CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0126_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0126_Data[];
+
+/* ComSign Secured CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0127_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0127_Data[];
+
+/* Cybertrust Global Root */
+extern const unsigned int NptTlsTrustAnchor_Base_0128_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0128_Data[];
+
+/* Buypass Class 2 CA 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0129_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0129_Data[];
+
+/* Buypass Class 3 CA 1 */
+extern const unsigned int NptTlsTrustAnchor_Base_0130_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0130_Data[];
+
+/* certSIGN ROOT CA */
+extern const unsigned int NptTlsTrustAnchor_Base_0131_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0131_Data[];
+
+/* ApplicationCA - Japanese Government */
+extern const unsigned int NptTlsTrustAnchor_Base_0132_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0132_Data[];
+
+/* GeoTrust Primary Certification Authority - G3 */
+extern const unsigned int NptTlsTrustAnchor_Base_0133_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0133_Data[];
+
+/* thawte Primary Root CA - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0134_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0134_Data[];
+
+/* GeoTrust Primary Certification Authority - G2 */
+extern const unsigned int NptTlsTrustAnchor_Base_0135_Size;
+extern const unsigned char NptTlsTrustAnchor_Base_0135_Data[];
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsExtended.h b/lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsExtended.h
new file mode 100644
index 0000000..005a6f0
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTlsDefaultTrustAnchorsExtended.h
@@ -0,0 +1,91 @@
+/*****************************************************************
+|
+| Neptune - Trust Anchors
+|
+| This file is automatically generated by a script, do not edit!
+|
+| Copyright (c) 2002-2010, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+ /* This file is automatically generated by GenTrustAnchorsTables.py, do not edit */
+
+#include "NptTls.h"
+
+extern const NPT_TlsTrustAnchorData NptTlsDefaultTrustAnchorsExtended[14];
+
+/* ABAecom (sub., Am. Bankers Assn.) Root CA */
+extern const unsigned int NptTlsTrustAnchor_Extended_0000_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0000_Data[];
+
+/* Taiwan GRCA */
+extern const unsigned int NptTlsTrustAnchor_Extended_0001_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0001_Data[];
+
+/* TURKTRUST Certificate Services Provider Root 1 */
+extern const unsigned int NptTlsTrustAnchor_Extended_0002_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0002_Data[];
+
+/* TURKTRUST Certificate Services Provider Root 2 */
+extern const unsigned int NptTlsTrustAnchor_Extended_0003_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0003_Data[];
+
+/* OISTE WISeKey Global Root GA CA */
+extern const unsigned int NptTlsTrustAnchor_Extended_0004_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0004_Data[];
+
+/* S-TRUST Authentication and Encryption Root CA 2005 PN */
+extern const unsigned int NptTlsTrustAnchor_Extended_0005_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0005_Data[];
+
+/* Microsec e-Szigno Root CA */
+extern const unsigned int NptTlsTrustAnchor_Extended_0006_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0006_Data[];
+
+/* Certigna */
+extern const unsigned int NptTlsTrustAnchor_Extended_0007_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0007_Data[];
+
+/* AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. */
+extern const unsigned int NptTlsTrustAnchor_Extended_0008_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0008_Data[];
+
+/* ePKI Root Certification Authority */
+extern const unsigned int NptTlsTrustAnchor_Extended_0009_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0009_Data[];
+
+/* TUBITAK UEKAE Kok Sertifika Hizmet Saglayicisi - Surum 3 */
+extern const unsigned int NptTlsTrustAnchor_Extended_0010_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0010_Data[];
+
+/* CNNIC ROOT */
+extern const unsigned int NptTlsTrustAnchor_Extended_0011_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0011_Data[];
+
+/* EBG Elektronik Sertifika Hizmet Saglayicisi */
+extern const unsigned int NptTlsTrustAnchor_Extended_0012_Size;
+extern const unsigned char NptTlsTrustAnchor_Extended_0012_Data[];
+
diff --git a/lib/libUPnP/Neptune/Source/Core/NptTypes.h b/lib/libUPnP/Neptune/Source/Core/NptTypes.h
new file mode 100644
index 0000000..4c82174
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptTypes.h
@@ -0,0 +1,149 @@
+/*****************************************************************
+|
+| Neptune - Types
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_TYPES_H_
+#define _NPT_TYPES_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+/*----------------------------------------------------------------------
+| sized types (this assumes that ints are 32 bits)
++---------------------------------------------------------------------*/
+typedef NPT_CONFIG_INT64_TYPE NPT_Int64;
+typedef unsigned NPT_CONFIG_INT64_TYPE NPT_UInt64;
+typedef unsigned int NPT_UInt32;
+typedef int NPT_Int32;
+typedef unsigned short NPT_UInt16;
+typedef short NPT_Int16;
+typedef unsigned char NPT_UInt8;
+typedef char NPT_Int8;
+typedef float NPT_Float;
+
+/*----------------------------------------------------------------------
+| named types
++---------------------------------------------------------------------*/
+typedef int NPT_Result;
+typedef unsigned int NPT_Cardinal;
+typedef unsigned int NPT_Ordinal;
+typedef NPT_UInt32 NPT_Size;
+typedef NPT_UInt64 NPT_LargeSize;
+typedef NPT_Int32 NPT_Offset;
+typedef NPT_UInt64 NPT_Position;
+typedef NPT_Int32 NPT_Timeout;
+typedef void NPT_Interface;
+typedef NPT_UInt8 NPT_Byte;
+typedef NPT_UInt32 NPT_Flags;
+typedef void* NPT_Any;
+typedef const void* NPT_AnyConst;
+
+/*----------------------------------------------------------------------
+| limits
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_HAVE_LIMITS_H)
+#include <limits.h>
+#endif
+
+#if !defined(NPT_INT_MIN)
+#if defined(NPT_CONFIG_HAVE_INT_MIN)
+#define NPT_INT_MIN INT_MIN
+#endif
+#endif
+
+#if !defined(NPT_INT_MAX)
+#if defined(NPT_CONFIG_HAVE_INT_MAX)
+#define NPT_INT_MAX INT_MAX
+#endif
+#endif
+
+#if !defined(NPT_UINT_MAX)
+#if defined(NPT_CONFIG_HAVE_UINT_MAX)
+#define NPT_UINT_MAX UINT_MAX
+#endif
+#endif
+
+#if !defined(NPT_LONG_MIN)
+#if defined(NPT_CONFIG_HAVE_LONG_MIN)
+#define NPT_LONG_MIN LONG_MIN
+#endif
+#endif
+
+#if !defined(NPT_LONG_MAX)
+#if defined(NPT_CONFIG_HAVE_LONG_MAX)
+#define NPT_LONG_MAX LONG_MAX
+#endif
+#endif
+
+#if !defined(NPT_ULONG_MAX)
+#if defined(NPT_CONFIG_HAVE_ULONG_MAX)
+#define NPT_ULONG_MAX ULONG_MAX
+#endif
+#endif
+
+#if !defined(NPT_INT32_MAX)
+#define NPT_INT32_MAX 0x7FFFFFFF
+#endif
+
+#if !defined(NPT_INT32_MIN)
+#define NPT_INT32_MIN (-NPT_INT32_MAX - 1)
+#endif
+
+#if !defined(NPT_UINT32_MAX)
+#define NPT_UINT32_MAX 0xFFFFFFFF
+#endif
+
+#if !defined(NPT_INT64_MAX)
+#if defined(NPT_CONFIG_HAVE_LLONG_MAX)
+#define NPT_INT64_MAX LLONG_MAX
+#else
+#define NPT_INT64_MAX 0x7FFFFFFFFFFFFFFFLL
+#endif
+#endif
+
+#if !defined(NPT_INT64_MIN)
+#if defined(NPT_CONFIG_HAVE_LLONG_MIN)
+#define NPT_INT64_MIN LLONG_MIN
+#else
+#define NPT_INT64_MIN (-NPT_INT64_MAX - 1LL)
+#endif
+#endif
+
+#if !defined(NPT_UINT64_MAX)
+#if defined(NPT_CONFIG_HAVE_ULLONG_MAX)
+#define NPT_UINT64_MAX ULLONG_MAX
+#else
+#define NPT_UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
+#endif
+#endif
+
+#endif // _NPT_TYPES_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptUri.cpp b/lib/libUPnP/Neptune/Source/Core/NptUri.cpp
new file mode 100644
index 0000000..e4a7c3b
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptUri.cpp
@@ -0,0 +1,912 @@
+/*****************************************************************
+|
+| Neptune - URI
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ***************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptUri.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+| NPT_Uri::ParseScheme
++---------------------------------------------------------------------*/
+NPT_Uri::SchemeId
+NPT_Uri::ParseScheme(const NPT_String& scheme)
+{
+ if (scheme == "http") {
+ return SCHEME_ID_HTTP;
+ } else if (scheme == "https") {
+ return SCHEME_ID_HTTPS;
+ } else {
+ return SCHEME_ID_UNKNOWN;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Uri::SetScheme
++---------------------------------------------------------------------*/
+void
+NPT_Uri::SetScheme(const char* scheme)
+{
+ m_Scheme = scheme;
+ m_Scheme.MakeLowercase();
+ m_SchemeId = ParseScheme(m_Scheme);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Uri::SetSchemeFromUri
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Uri::SetSchemeFromUri(const char* uri)
+{
+ const char* start = uri;
+ char c;
+ while ((c =*uri++)) {
+ if (c == ':') {
+ m_Scheme.Assign(start, (NPT_Size)(uri-start-1));
+ m_Scheme.MakeLowercase();
+ m_SchemeId = ParseScheme(m_Scheme);
+ return NPT_SUCCESS;
+ } else if ((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ (c == '+') ||
+ (c == '.') ||
+ (c == '-')) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ return NPT_ERROR_INVALID_SYNTAX;
+}
+
+/*----------------------------------------------------------------------
+Appendix A. Collected ABNF for URI
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ URI-reference = URI / relative-ref
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ host = IP-literal / IPv4address / reg-name
+ port = *DIGIT
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ h16 = 1*4HEXDIG
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ query = *( pchar / "/" / "?" )
+
+ fragment = *( pchar / "/" / "?" )
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ reserved = gen-delims / sub-delims
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+---------------------------------------------------------------------*/
+
+#define NPT_URI_ALWAYS_ENCODE " !\"<>\\^`{|}"
+
+/*----------------------------------------------------------------------
+| NPT_Uri::PathCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::PathCharsToEncode = NPT_URI_ALWAYS_ENCODE "?#[]";
+
+/*----------------------------------------------------------------------
+| NPT_Uri::QueryCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::QueryCharsToEncode = NPT_URI_ALWAYS_ENCODE "#[]";
+
+/*----------------------------------------------------------------------
+| NPT_Uri::FragmentCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::FragmentCharsToEncode = NPT_URI_ALWAYS_ENCODE "[]";
+
+/*----------------------------------------------------------------------
+| NPT_Uri::UnsafeCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::UnsafeCharsToEncode = NPT_URI_ALWAYS_ENCODE;
+
+/*----------------------------------------------------------------------
+| NPT_Uri::PercentEncode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Uri::PercentEncode(const char* str, const char* chars, bool encode_percents)
+{
+ NPT_String encoded;
+
+ // check args
+ if (str == NULL) return encoded;
+
+ // reserve at least the size of the current uri
+ encoded.Reserve(NPT_StringLength(str));
+
+ // process each character
+ char escaped[3];
+ escaped[0] = '%';
+ while (unsigned char c = *str++) {
+ bool encode = false;
+ if (encode_percents && c == '%') {
+ encode = true;
+ } else if (c < ' ' || c > '~') {
+ encode = true;
+ } else {
+ const char* match = chars;
+ while (*match) {
+ if (c == *match) {
+ encode = true;
+ break;
+ }
+ ++match;
+ }
+ }
+ if (encode) {
+ // encode
+ NPT_ByteToHex(c, &escaped[1], true);
+ encoded.Append(escaped, 3);
+ } else {
+ // no encoding required
+ encoded += c;
+ }
+ }
+
+ return encoded;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Uri::PercentDecode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Uri::PercentDecode(const char* str)
+{
+ NPT_String decoded;
+
+ // check args
+ if (str == NULL) return decoded;
+
+ // reserve at least the size of the current uri
+ decoded.Reserve(NPT_StringLength(str));
+
+ // process each character
+ while (unsigned char c = *str++) {
+ if (c == '%') {
+ // needs to be unescaped
+ unsigned char unescaped;
+ if (NPT_SUCCEEDED(NPT_HexToByte(str, unescaped))) {
+ decoded += unescaped;
+ str += 2;
+ } else {
+ // not a valid escape sequence, just keep the %
+ decoded += c;
+ }
+ } else {
+ // no unescaping required
+ decoded += c;
+ }
+ }
+
+ return decoded;
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::NPT_UrlQuery
++---------------------------------------------------------------------*/
+NPT_UrlQuery::NPT_UrlQuery(const char* query)
+{
+ Parse(query);
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::UrlEncode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_UrlQuery::UrlEncode(const char* str, bool encode_percents)
+{
+ NPT_String encoded = NPT_Uri::PercentEncode(
+ str,
+ ";/?:@&=+$," /* reserved as defined in RFC 2396 */
+ "\"#<>\\^`{|}", /* other unsafe chars */
+ encode_percents);
+ encoded.Replace(' ','+');
+
+ return encoded;
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::UrlDecode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_UrlQuery::UrlDecode(const char* str)
+{
+ NPT_String decoded(str);
+ decoded.Replace('+', ' ');
+ return NPT_Uri::PercentDecode(decoded);
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::Field::Field
++---------------------------------------------------------------------*/
+NPT_UrlQuery::Field::Field(const char* name, const char* value, bool encoded)
+{
+ if (encoded) {
+ m_Name = name;
+ m_Value = value;
+ } else {
+ m_Name = UrlEncode(name);
+ m_Value = UrlEncode(value);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_UrlQuery::ToString()
+{
+ NPT_String encoded;
+ bool separator = false;
+ for (NPT_List<Field>::Iterator it = m_Fields.GetFirstItem();
+ it;
+ ++it) {
+ Field& field = *it;
+ if (separator) encoded += "&";
+ separator = true;
+ encoded += field.m_Name;
+ encoded += "=";
+ encoded += field.m_Value;
+ }
+
+ return encoded;
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_UrlQuery::Parse(const char* query)
+{
+ const char* cursor = query;
+ NPT_String name;
+ NPT_String value;
+ bool in_name = true;
+ do {
+ if (*cursor == '\0' || *cursor == '&') {
+ AddField(name, value, true);
+ name.SetLength(0);
+ value.SetLength(0);
+ in_name = true;
+ } else if (*cursor == '=' && in_name) {
+ in_name = false;
+ } else {
+ if (in_name) {
+ name += *cursor;
+ } else {
+ value += *cursor;
+ }
+ }
+ } while (*cursor++);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::AddField
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_UrlQuery::AddField(const char* name, const char* value, bool encoded)
+{
+ return m_Fields.Add(Field(name, value, encoded));
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::SetField
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_UrlQuery::SetField(const char* name, const char* value, bool encoded)
+{
+ NPT_String ename;
+ if (encoded) {
+ ename = name;
+ } else {
+ ename = UrlEncode(name);
+ }
+ for (NPT_List<Field>::Iterator it = m_Fields.GetFirstItem();
+ it;
+ ++it) {
+ Field& field = *it;
+ if (field.m_Name == ename) {
+ if (encoded) {
+ field.m_Value = value;
+ } else {
+ field.m_Value = UrlEncode(value);
+ }
+ return NPT_SUCCESS;
+ }
+ }
+
+ // field not found, add it
+ return AddField(name, value, encoded);
+}
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery::GetField
++---------------------------------------------------------------------*/
+const char*
+NPT_UrlQuery::GetField(const char* name)
+{
+ NPT_String ename = UrlEncode(name);
+ for (NPT_List<Field>::Iterator it = m_Fields.GetFirstItem();
+ it;
+ ++it) {
+ Field& field = *it;
+ if (field.m_Name == ename) return field.m_Value;
+ }
+
+ // field not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef enum {
+ NPT_URL_PARSER_STATE_START,
+ NPT_URL_PARSER_STATE_SCHEME,
+ NPT_URL_PARSER_STATE_LEADING_SLASH,
+ NPT_URL_PARSER_STATE_HOST,
+ NPT_URL_PARSER_STATE_HOST_IPV6_ADDR,
+ NPT_URL_PARSER_STATE_PORT,
+ NPT_URL_PARSER_STATE_PATH,
+ NPT_URL_PARSER_STATE_QUERY
+} NPT_UrlParserState;
+
+/*----------------------------------------------------------------------
+| NPT_Url::NPT_Url
++---------------------------------------------------------------------*/
+NPT_Url::NPT_Url() :
+ m_HostIsIpv6Address(false),
+ m_Port(NPT_URL_INVALID_PORT),
+ m_Path("/"),
+ m_HasQuery(false),
+ m_HasFragment(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::NPT_Url
++---------------------------------------------------------------------*/
+NPT_Url::NPT_Url(const char* url, NPT_UInt16 default_port) :
+ m_HostIsIpv6Address(false),
+ m_Port(NPT_URL_INVALID_PORT),
+ m_HasQuery(false),
+ m_HasFragment(false)
+{
+ // try to parse
+ if (NPT_FAILED(Parse(url, default_port))) {
+ Reset();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::Parse(const char* url, NPT_UInt16 default_port)
+{
+ // check parameters
+ if (url == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // set the uri scheme
+ NPT_Result result = SetSchemeFromUri(url);
+ if (NPT_FAILED(result)) return result;
+
+ // set the default port
+ if (default_port) {
+ m_Port = default_port;
+ } else {
+ switch (m_SchemeId) {
+ case SCHEME_ID_HTTP: m_Port = NPT_URL_DEFAULT_HTTP_PORT; break;
+ case SCHEME_ID_HTTPS: m_Port = NPT_URL_DEFAULT_HTTPS_PORT; break;
+ default: break;
+ }
+ }
+
+ // move to the scheme-specific part
+ url += m_Scheme.GetLength()+1;
+
+ // intialize the parser
+ NPT_UrlParserState state = NPT_URL_PARSER_STATE_START;
+ const char* mark = url;
+
+ // parse the URL
+ char c;
+ do {
+ c = *url++;
+ switch (state) {
+ case NPT_URL_PARSER_STATE_START:
+ if (c == '/') {
+ state = NPT_URL_PARSER_STATE_LEADING_SLASH;
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case NPT_URL_PARSER_STATE_LEADING_SLASH:
+ if (c == '/') {
+ state = NPT_URL_PARSER_STATE_HOST;
+ mark = url;
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case NPT_URL_PARSER_STATE_HOST_IPV6_ADDR:
+ if (c == ']') {
+ state = NPT_URL_PARSER_STATE_HOST;
+ }
+ break;
+
+ case NPT_URL_PARSER_STATE_HOST:
+ if (c == '[' && url == mark+1) {
+ // start of an IPv6 address
+ state = NPT_URL_PARSER_STATE_HOST_IPV6_ADDR;
+ } else if (c == ':' || c == '/' || c == '\0' || c == '?' || c == '#') {
+ NPT_Size host_length = (NPT_Size)(url-1-mark);
+ if (host_length > 2 && mark[0] == '[' && mark[host_length-1] == ']') {
+ m_Host.Assign(mark+1, host_length-2);
+ m_HostIsIpv6Address = true;
+ } else {
+ m_Host.Assign(mark, host_length);
+ m_HostIsIpv6Address = false;
+ }
+ if (c == ':') {
+ mark = url;
+ m_Port = 0;
+ state = NPT_URL_PARSER_STATE_PORT;
+ } else {
+ mark = url-1;
+ state = NPT_URL_PARSER_STATE_PATH;
+ }
+ }
+ break;
+
+ case NPT_URL_PARSER_STATE_PORT:
+ if (c >= '0' && c <= '9') {
+ unsigned int val = m_Port*10+(c-'0');
+ if (val > 65535) {
+ m_Port = NPT_URL_INVALID_PORT;
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ m_Port = val;
+ } else if (c == '/' || c == '\0') {
+ mark = url-1;
+ state = NPT_URL_PARSER_STATE_PATH;
+ } else {
+ // invalid character
+ m_Port = NPT_URL_INVALID_PORT;
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case NPT_URL_PARSER_STATE_PATH:
+ if (*mark) {
+ return ParsePathPlus(mark);
+ }
+ break;
+
+ default:
+ break;
+ }
+ } while (c);
+
+ // if we get here, the path is implicit
+ m_Path = "/";
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::NPT_Url
++---------------------------------------------------------------------*/
+NPT_Url::NPT_Url(const char* scheme,
+ const char* host,
+ NPT_UInt16 port,
+ const char* path,
+ const char* query,
+ const char* fragment) :
+ m_Host(host),
+ m_HostIsIpv6Address(false),
+ m_Port(port),
+ m_Path(path),
+ m_HasQuery(query != NULL),
+ m_Query(query),
+ m_HasFragment(fragment != NULL),
+ m_Fragment(fragment)
+{
+ SetScheme(scheme);
+
+ // deal with IPv6 addresses
+ if (m_Host.StartsWith("[") && m_Host.EndsWith("]")) {
+ m_HostIsIpv6Address = true;
+ m_Host = m_Host.SubString(1, m_Host.GetLength()-2);
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::Reset
++---------------------------------------------------------------------*/
+void
+NPT_Url::Reset()
+{
+ m_Host.SetLength(0);
+ m_HostIsIpv6Address = false;
+ m_Port = 0;
+ m_Path.SetLength(0);
+ m_HasQuery = false;
+ m_Query.SetLength(0);
+ m_HasFragment = false;
+ m_Fragment.SetLength(0);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::IsValid
++---------------------------------------------------------------------*/
+bool
+NPT_Url::IsValid() const
+{
+ switch (m_SchemeId) {
+ case SCHEME_ID_HTTP:
+ case SCHEME_ID_HTTPS:
+ return m_Port != NPT_URL_INVALID_PORT && !m_Host.IsEmpty();
+ break;
+
+ default:
+ return !m_Scheme.IsEmpty();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::SetHost
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::SetHost(const char* host)
+{
+ const char* port;
+ if (*host == '[') {
+ const char* host_end = host+1;
+ while (*host_end && *host_end != ']') ++host_end;
+ if (*host_end != ']') {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ port = host_end+1;
+ if (*port && *port != ':') {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ m_Host.Assign(host+1, (NPT_Size)(host_end-host-1));
+ m_HostIsIpv6Address = true;
+ } else {
+ port = host;
+ while (*port && *port != ':') port++;
+ m_Host.Assign(host, (NPT_Size)(port-host));
+ m_HostIsIpv6Address = false;
+ }
+
+ if (*port) {
+ unsigned int port_number;
+ // parse the port number but ignore errors (be lenient)
+ if (NPT_SUCCEEDED(NPT_ParseInteger(port+1, port_number, false))) {
+ if (port_number > 65535) {
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+ m_Port = (NPT_UInt16)port_number;
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::SetPort
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::SetPort(NPT_UInt16 port)
+{
+ m_Port = port;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::SetPath
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::SetPath(const char* path, bool encoded)
+{
+ if (encoded) {
+ m_Path = path;
+ } else {
+ m_Path = PercentEncode(path, PathCharsToEncode);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::ParsePathPlus
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::ParsePathPlus(const char* path_plus)
+{
+ // check parameters
+ if (path_plus == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // reset any existing values
+ m_Path.SetLength(0);
+ m_Query.SetLength(0);
+ m_Fragment.SetLength(0);
+ m_HasQuery = false;
+ m_HasFragment = false;
+
+#ifdef _WIN32
+ // Skip the leading '/' if there is an absolute path starting with
+ // a drive letter on Windows.
+ if (path_plus[0] == '/' &&
+ ((path_plus[1] >= 'a' && path_plus[1] <= 'z') ||
+ (path_plus[1] >= 'A' && path_plus[1] <= 'Z')) &&
+ path_plus[2] == ':')
+ {
+ ++path_plus;
+ }
+#endif
+
+ // intialize the parser
+ NPT_UrlParserState state = NPT_URL_PARSER_STATE_PATH;
+ const char* mark = path_plus;
+
+ // parse the path+
+ char c;
+ do {
+ c = *path_plus++;
+ switch (state) {
+ case NPT_URL_PARSER_STATE_PATH:
+ if (c == '\0' || c == '?' || c == '#') {
+ if (path_plus-1 > mark) {
+ m_Path.Append(mark, (NPT_Size)(path_plus-1-mark));
+ }
+ if (c == '?') {
+ m_HasQuery = true;
+ state = NPT_URL_PARSER_STATE_QUERY;
+ mark = path_plus;
+ } else if (c == '#') {
+ m_HasFragment = true;
+ m_Fragment = path_plus;
+ return NPT_SUCCESS;
+ }
+ }
+ break;
+
+ case NPT_URL_PARSER_STATE_QUERY:
+ if (c == '\0' || c == '#') {
+ m_Query.Assign(mark, (NPT_Size)(path_plus-1-mark));
+ if (c == '#') {
+ m_HasFragment = true;
+ m_Fragment = path_plus;
+ }
+ return NPT_SUCCESS;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } while (c);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::SetQuery
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::SetQuery(const char* query, bool encoded)
+{
+ if (encoded) {
+ m_Query = query;
+ } else {
+ m_Query = PercentEncode(query, QueryCharsToEncode);
+ }
+ m_HasQuery = query!=NULL && NPT_StringLength(query)>0;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::SetFragment
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::SetFragment(const char* fragment, bool encoded)
+{
+ if (encoded) {
+ m_Fragment = fragment;
+ } else {
+ m_Fragment = PercentEncode(fragment, FragmentCharsToEncode);
+ }
+ m_HasFragment = fragment!=NULL;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::ToRequestString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Url::ToRequestString(bool with_fragment) const
+{
+ NPT_String result;
+ NPT_Size length = m_Path.GetLength()+1;
+ if (m_HasQuery) length += 1+m_Query.GetLength();
+ if (with_fragment) length += 1+m_Fragment.GetLength();
+ result.Reserve(length);
+
+ if (m_Path.IsEmpty()) {
+ result += "/";
+ } else {
+#if defined(_WIN32)
+ // prepend a '/' if the path starts with the drive letter on Windows
+ if (((m_Path[0] >= 'a' && m_Path[0] <= 'z') ||
+ (m_Path[0] >= 'A' && m_Path[0] <= 'Z')) &&
+ m_Path[1] == ':')
+ {
+ result += "/";
+ }
+#endif
+ result += m_Path;
+ }
+ if (m_HasQuery) {
+ result += "?";
+ result += m_Query;
+ }
+ if (with_fragment && m_HasFragment) {
+ result += "#";
+ result += m_Fragment;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::ToStringWithDefaultPort
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Url::ToStringWithDefaultPort(NPT_UInt16 default_port, bool with_fragment) const
+{
+ NPT_String result;
+ NPT_String request = ToRequestString(with_fragment);
+ NPT_Size length = m_Scheme.GetLength()+3+m_Host.GetLength()+6+request.GetLength();
+
+ if (m_HostIsIpv6Address) {
+ length += 2;
+ }
+
+ result.Reserve(length);
+ result += m_Scheme;
+ result += "://";
+ if (m_HostIsIpv6Address) {
+ result += "[";
+ }
+ result += m_Host;
+ if (m_HostIsIpv6Address) {
+ result += "]";
+ }
+ if (m_Port != default_port) {
+ NPT_String port = NPT_String::FromInteger(m_Port);
+ result += ":";
+ result += port;
+ }
+ result += request;
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Url::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Url::ToString(bool with_fragment) const
+{
+ return ToStringWithDefaultPort(0, with_fragment);
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptUri.h b/lib/libUPnP/Neptune/Source/Core/NptUri.h
new file mode 100644
index 0000000..f3661c0
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptUri.h
@@ -0,0 +1,322 @@
+/*****************************************************************
+|
+| Neptune - URI
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_URI_H_
+#define _NPT_URI_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptStrings.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const NPT_UInt16 NPT_URL_INVALID_PORT = 0;
+const NPT_UInt16 NPT_URL_DEFAULT_HTTP_PORT = 80;
+const NPT_UInt16 NPT_URL_DEFAULT_HTTPS_PORT = 443;
+
+/*----------------------------------------------------------------------
+| NPT_Uri
++---------------------------------------------------------------------*/
+class NPT_Uri {
+public:
+ // types
+ typedef enum {
+ SCHEME_ID_UNKNOWN,
+ SCHEME_ID_HTTP,
+ SCHEME_ID_HTTPS
+ } SchemeId;
+
+ // constants. use as a parameter to Encode()
+ static const char* const PathCharsToEncode;
+ static const char* const QueryCharsToEncode;
+ static const char* const FragmentCharsToEncode;
+ static const char* const UnsafeCharsToEncode;
+
+ // class methods
+ static NPT_String PercentEncode(const char* str, const char* chars, bool encode_percents=true);
+ static NPT_String PercentDecode(const char* str);
+ static SchemeId ParseScheme(const NPT_String& scheme);
+
+ // methods
+ NPT_Uri() : m_SchemeId(SCHEME_ID_UNKNOWN) {}
+ virtual ~NPT_Uri() {}
+ const NPT_String& GetScheme() const {
+ return m_Scheme;
+ }
+ void SetScheme(const char* scheme);
+ NPT_Result SetSchemeFromUri(const char* uri);
+ SchemeId GetSchemeId() const {
+ return m_SchemeId;
+ }
+
+protected:
+ // members
+ NPT_String m_Scheme;
+ SchemeId m_SchemeId;
+};
+
+/*----------------------------------------------------------------------
+| NPT_UrlQuery
++---------------------------------------------------------------------*/
+class NPT_UrlQuery
+{
+public:
+ // class methods
+ static NPT_String UrlEncode(const char* str, bool encode_percents=true);
+ static NPT_String UrlDecode(const char* str);
+
+ // types
+ struct Field {
+ Field(const char* name, const char* value, bool encoded);
+ NPT_String m_Name;
+ NPT_String m_Value;
+ };
+
+ // constructor
+ NPT_UrlQuery() {}
+ NPT_UrlQuery(const char* query);
+
+ // accessors
+ NPT_List<Field>& GetFields() { return m_Fields; }
+
+ // methods
+ NPT_Result Parse(const char* query);
+ NPT_Result SetField(const char* name, const char* value, bool encoded=false);
+ NPT_Result AddField(const char* name, const char* value, bool encoded=false);
+ const char* GetField(const char* name);
+ NPT_String ToString();
+
+private:
+ // members
+ NPT_List<Field> m_Fields;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Url
++---------------------------------------------------------------------*/
+class NPT_Url : public NPT_Uri {
+public:
+ /**
+ * Default constructor. This does not construct a valid URL, but an
+ * uninitialized one that can later be initialized to a valid URL by
+ * parsing or setting some of its fields.
+ */
+ NPT_Url();
+
+ /**
+ * Construct a URL by parsing an input string in its fully encoded form.
+ * If an error occurs during parsing (such as an invalid syntax), the
+ * URL will be in an invalid state (a call to IsValid() will return false).
+ *
+ * @param url The URL string in its encoded form
+ * @param default_port The default port number, or 0 if not specified
+ */
+ NPT_Url(const char* url, NPT_UInt16 default_port = 0);
+
+ /**
+ * Construct a URL from its components. When constructing a URL from
+ * components, the components are assumed to be passed in their non-encoded
+ * form, and will thus be encoded automatically.
+ *
+ * @param scheme The URL scheme
+ * @param host The host name (enclose with [ and ] for IPv6 addresses)
+ * @param port The port number
+ * @param path The path
+ * @param query The query, if any, or NULL
+ * @param fragment The fragment, if any, or NULL
+ */
+ NPT_Url(const char* scheme,
+ const char* host,
+ NPT_UInt16 port,
+ const char* path,
+ const char* query = NULL,
+ const char* fragment = NULL);
+
+ /**
+ * Parse a URL from its fully encoded form.
+ *
+ * @param url The URL string in its encoded form
+ * @param default port The defautl port number, or 0 if not specified
+ */
+ NPT_Result Parse(const char* url, NPT_UInt16 default_port = 0);
+
+ /**
+ * Parse just the path plus optional query and fragment from a fully encoded form.
+ *
+ * @param path_plus The URL path plus optional query and fragment
+ */
+ NPT_Result ParsePathPlus(const char* path_plus);
+
+ /**
+ * Returns the host part of the URL, in its encoded form
+ */
+ const NPT_String& GetHost() const { return m_Host; }
+
+ /**
+ * Returns the port number of the URL.
+ */
+ NPT_UInt16 GetPort() const { return m_Port; }
+
+ /**
+ * Returns the path part of the URL, in its encoded form
+ */
+ const NPT_String& GetPath() const { return m_Path; }
+
+ /**
+ * Returns the path part of the URL, in its encoded or decoded form
+ */
+ NPT_String GetPath(bool decoded) const { return decoded?NPT_Uri::PercentDecode(m_Path):m_Path;}
+
+ /**
+ * Returns the query part of the URL, in its encoded form
+ */
+ const NPT_String& GetQuery() const { return m_Query; }
+
+ /**
+ * Returns the fragment part of the URL, in its encoded form
+ */
+ const NPT_String& GetFragment() const { return m_Fragment; }
+
+ /**
+ * Returns whether the URL is valid or not. Invalid URLs are uninitialized or
+ * not fully initialized URLs.
+ *
+ * @return true if the URL is valid, false if it is not.
+ */
+ virtual bool IsValid() const;
+
+ /**
+ * Resets a URL to an uninitialized state.
+ */
+ void Reset();
+
+ /**
+ * Returns whether the URL has a query part or not.
+ *
+ * @return true if the URL has a query part, false if it does not.
+ */
+ bool HasQuery() const { return m_HasQuery; }
+
+ /**
+ * Returns whether the URL has a fragment part or not.
+ *
+ * @return true if the URL has a fragment part, false if it does not.
+ */
+ bool HasFragment() const { return m_HasFragment; }
+
+ /**
+ * Sets the host part of the URL.
+ *
+ * @param host The host part of the URL (enclose with [ and ] for IPv6 addresses)
+ */
+ NPT_Result SetHost(const char* host);
+
+ /**
+ * Sets the port number of the URL.
+ *
+ * @param port The port number of the URL
+ */
+ NPT_Result SetPort(NPT_UInt16 port);
+
+ /**
+ * Sets the path part of the URL.
+ *
+ * @param path The path part of the URL
+ * @param encoded Boolean flag indicating whether the path parameter is
+ * already encoded or not. If it is not already encoded, it will be
+ * automatically encoded.
+ */
+ NPT_Result SetPath(const char* path, bool encoded=false);
+
+ /**
+ * Sets the query part of the URL.
+ *
+ * @param query The query part of the URL
+ * @param encoded Boolean flag indicating whether the query parameter is
+ * already encoded or not. If it is not already encoded, it will be
+ * automatically encoded.
+ */
+ NPT_Result SetQuery(const char* query, bool encoded=false);
+
+ /**
+ * Sets the fragment part of the URL.
+ *
+ * @param query The fragment part of the URL
+ * @param encoded Boolean flag indicating whether the fragment parameter is
+ * already encoded or not. If it is not already encoded, it will be
+ * automatically encoded.
+ */
+ NPT_Result SetFragment(const char* fragment, bool encoded=false);
+
+ /**
+ * Return the string representation of the URL in a way that can be used in
+ * an HTTP request (i.e just the portion of the URL starting with the path)
+ *
+ * @param with_fragment Boolean flag specifiying whether the fragment part of
+ * the URL should be included in the returned string or not.
+ */
+ virtual NPT_String ToRequestString(bool with_fragment = false) const;
+
+ /**
+ * Return the string representation of the URL.
+ *
+ * @param default_port default port number for the scheme. If the port number of
+ * the URL is not equal to the default port, then port number is explicitely
+ * included in the string representation of the URL.
+ * @param with_fragment Boolean flag specifiying whether the fragment part of
+ * the URL should be included in the returned string or not.
+ */
+ virtual NPT_String ToStringWithDefaultPort(NPT_UInt16 default_port, bool with_fragment = true) const;
+
+ /**
+ * Return the string representation of the URL.
+ *
+ * @param with_fragment Boolean flag specifiying whether the fragment part of
+ * the URL should be included in the returned string or not.
+ */
+ virtual NPT_String ToString(bool with_fragment = true) const;
+
+protected:
+ // members
+ NPT_String m_Host;
+ bool m_HostIsIpv6Address;
+ NPT_UInt16 m_Port;
+ NPT_String m_Path;
+ bool m_HasQuery;
+ NPT_String m_Query;
+ bool m_HasFragment;
+ NPT_String m_Fragment;
+};
+
+#endif // _NPT_URI_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptUtils.cpp b/lib/libUPnP/Neptune/Source/Core/NptUtils.cpp
new file mode 100644
index 0000000..f427f8b
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptUtils.cpp
@@ -0,0 +1,957 @@
+/*****************************************************************
+|
+| Neptune - Utils
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <math.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptDebug.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+#if defined(NPT_CONFIG_HAVE_LIMITS_H)
+#include <limits.h>
+#endif
+
+#ifdef TARGET_WINDOWS_STORE
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+#endif
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_FORMAT_LOCAL_BUFFER_SIZE = 1024;
+const unsigned int NPT_FORMAT_BUFFER_INCREMENT = 4096;
+const unsigned int NPT_FORMAT_BUFFER_MAX_SIZE = 65536;
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt64Be
++---------------------------------------------------------------------*/
+NPT_UInt64
+NPT_BytesToInt64Be(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt64)bytes[0])<<56 ) |
+ ( ((NPT_UInt64)bytes[1])<<48 ) |
+ ( ((NPT_UInt64)bytes[2])<<40 ) |
+ ( ((NPT_UInt64)bytes[3])<<32 ) |
+ ( ((NPT_UInt64)bytes[4])<<24 ) |
+ ( ((NPT_UInt64)bytes[5])<<16 ) |
+ ( ((NPT_UInt64)bytes[6])<<8 ) |
+ ( ((NPT_UInt64)bytes[7]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt32Be
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_BytesToInt32Be(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt32)bytes[0])<<24 ) |
+ ( ((NPT_UInt32)bytes[1])<<16 ) |
+ ( ((NPT_UInt32)bytes[2])<<8 ) |
+ ( ((NPT_UInt32)bytes[3]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt24Be
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_BytesToInt24Be(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt32)bytes[0])<<16 ) |
+ ( ((NPT_UInt32)bytes[1])<<8 ) |
+ ( ((NPT_UInt32)bytes[2]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt16Be
++---------------------------------------------------------------------*/
+NPT_UInt16
+NPT_BytesToInt16Be(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt16)bytes[0])<<8 ) |
+ ( ((NPT_UInt16)bytes[1]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt64Le
++---------------------------------------------------------------------*/
+NPT_UInt64
+NPT_BytesToInt64Le(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt64)bytes[7])<<56 ) |
+ ( ((NPT_UInt64)bytes[6])<<48 ) |
+ ( ((NPT_UInt64)bytes[5])<<40 ) |
+ ( ((NPT_UInt64)bytes[4])<<32 ) |
+ ( ((NPT_UInt64)bytes[3])<<24 ) |
+ ( ((NPT_UInt64)bytes[2])<<16 ) |
+ ( ((NPT_UInt64)bytes[1])<<8 ) |
+ ( ((NPT_UInt64)bytes[0]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt32Le
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_BytesToInt32Le(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt32)bytes[3])<<24 ) |
+ ( ((NPT_UInt32)bytes[2])<<16 ) |
+ ( ((NPT_UInt32)bytes[1])<<8 ) |
+ ( ((NPT_UInt32)bytes[0]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt24Le
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_BytesToInt24Le(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt32)bytes[2])<<16 ) |
+ ( ((NPT_UInt32)bytes[1])<<8 ) |
+ ( ((NPT_UInt32)bytes[0]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesToInt16Le
++---------------------------------------------------------------------*/
+NPT_UInt16
+NPT_BytesToInt16Le(const unsigned char* bytes)
+{
+ return
+ ( ((NPT_UInt16)bytes[1])<<8 ) |
+ ( ((NPT_UInt16)bytes[0]) );
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt64Be
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt64Be(unsigned char* buffer, NPT_UInt64 value)
+{
+ buffer[0] = (unsigned char)(value>>56) & 0xFF;
+ buffer[1] = (unsigned char)(value>>48) & 0xFF;
+ buffer[2] = (unsigned char)(value>>40) & 0xFF;
+ buffer[3] = (unsigned char)(value>>32) & 0xFF;
+ buffer[4] = (unsigned char)(value>>24) & 0xFF;
+ buffer[5] = (unsigned char)(value>>16) & 0xFF;
+ buffer[6] = (unsigned char)(value>> 8) & 0xFF;
+ buffer[7] = (unsigned char)(value ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt32Be
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt32Be(unsigned char* buffer, NPT_UInt32 value)
+{
+ buffer[0] = (unsigned char)(value>>24) & 0xFF;
+ buffer[1] = (unsigned char)(value>>16) & 0xFF;
+ buffer[2] = (unsigned char)(value>> 8) & 0xFF;
+ buffer[3] = (unsigned char)(value ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt24Be
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt24Be(unsigned char* buffer, NPT_UInt32 value)
+{
+ buffer[0] = (unsigned char)(value>>16) & 0xFF;
+ buffer[1] = (unsigned char)(value>> 8) & 0xFF;
+ buffer[2] = (unsigned char)(value ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt16Be
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt16Be(unsigned char* buffer, NPT_UInt16 value)
+{
+ buffer[0] = (unsigned char)((value>> 8) & 0xFF);
+ buffer[1] = (unsigned char)((value ) & 0xFF);
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt64Le
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt64Le(unsigned char* buffer, NPT_UInt64 value)
+{
+ buffer[7] = (unsigned char)(value>>56) & 0xFF;
+ buffer[6] = (unsigned char)(value>>48) & 0xFF;
+ buffer[5] = (unsigned char)(value>>40) & 0xFF;
+ buffer[4] = (unsigned char)(value>>32) & 0xFF;
+ buffer[3] = (unsigned char)(value>>24) & 0xFF;
+ buffer[2] = (unsigned char)(value>>16) & 0xFF;
+ buffer[1] = (unsigned char)(value>> 8) & 0xFF;
+ buffer[0] = (unsigned char)(value ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt32Le
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt32Le(unsigned char* buffer, NPT_UInt32 value)
+{
+ buffer[3] = (unsigned char)(value>>24) & 0xFF;
+ buffer[2] = (unsigned char)(value>>16) & 0xFF;
+ buffer[1] = (unsigned char)(value>> 8) & 0xFF;
+ buffer[0] = (unsigned char)(value ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt24Le
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt24Le(unsigned char* buffer, NPT_UInt32 value)
+{
+ buffer[2] = (unsigned char)(value>>16) & 0xFF;
+ buffer[1] = (unsigned char)(value>> 8) & 0xFF;
+ buffer[0] = (unsigned char)(value ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+| NPT_BytesFromInt16Le
++---------------------------------------------------------------------*/
+void
+NPT_BytesFromInt16Le(unsigned char* buffer, NPT_UInt16 value)
+{
+ buffer[1] = (unsigned char)((value>> 8) & 0xFF);
+ buffer[0] = (unsigned char)((value ) & 0xFF);
+}
+
+#if !defined(NPT_CONFIG_HAVE_SNPRINTF)
+/*----------------------------------------------------------------------
+| NPT_FormatString
++---------------------------------------------------------------------*/
+int
+NPT_FormatString(char* /*str*/, NPT_Size /*size*/, const char* /*format*/, ...)
+{
+ NPT_ASSERT(0); // not implemented yet
+ return 0;
+}
+#endif // NPT_CONFIG_HAVE_SNPRINTF
+
+/*----------------------------------------------------------------------
+| NPT_NibbleToHex
++---------------------------------------------------------------------*/
+char
+NPT_NibbleToHex(unsigned int nibble, bool uppercase /* = true */)
+{
+ NPT_ASSERT(nibble < 16);
+ if (uppercase) {
+ return (nibble < 10) ? ('0' + nibble) : ('A' + (nibble-10));
+ } else {
+ return (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_HexToNibble
++---------------------------------------------------------------------*/
+int
+NPT_HexToNibble(char hex)
+{
+ if (hex >= 'a' && hex <= 'f') {
+ return ((hex - 'a') + 10);
+ } else if (hex >= 'A' && hex <= 'F') {
+ return ((hex - 'A') + 10);
+ } else if (hex >= '0' && hex <= '9') {
+ return (hex - '0');
+ } else {
+ return -1;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_ByteToHex
++---------------------------------------------------------------------*/
+void
+NPT_ByteToHex(NPT_Byte b, char* buffer, bool uppercase)
+{
+ buffer[0] = NPT_NibbleToHex((b>>4) & 0x0F, uppercase);
+ buffer[1] = NPT_NibbleToHex(b & 0x0F, uppercase);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HexToByte
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HexToByte(const char* buffer, NPT_Byte& b)
+{
+ int nibble_0 = NPT_HexToNibble(buffer[0]);
+ if (nibble_0 < 0) return NPT_ERROR_INVALID_SYNTAX;
+
+ int nibble_1 = NPT_HexToNibble(buffer[1]);
+ if (nibble_1 < 0) return NPT_ERROR_INVALID_SYNTAX;
+
+ b = (nibble_0 << 4) | nibble_1;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HexToBytes
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HexToBytes(const char* hex,
+ NPT_DataBuffer& bytes)
+{
+ // check the size
+ NPT_Size len = NPT_StringLength(hex);
+ if ((len%2) != 0) return NPT_ERROR_INVALID_PARAMETERS;
+ NPT_Size bytes_size = len / 2;
+ NPT_Result result = bytes.SetDataSize(bytes_size);
+ if (NPT_FAILED(result)) return result;
+
+ // decode
+ for (NPT_Ordinal i=0; i<bytes_size; i++) {
+ result = NPT_HexToByte(hex+(i*2), *(bytes.UseData()+i));
+ if (NPT_FAILED(result)) return result;
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_HexString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_HexString(const unsigned char* data,
+ NPT_Size data_size,
+ const char* separator,
+ bool uppercase)
+{
+ NPT_String result;
+
+ // quick check
+ if (data == NULL || data_size == 0) return result;
+
+ // set the result size
+ NPT_Size separator_length = separator?NPT_StringLength(separator):0;
+ result.SetLength(data_size*2+(data_size-1)*separator_length);
+
+ // build the string
+ const unsigned char* src = data;
+ char* dst = result.UseChars();
+ while (data_size--) {
+ NPT_ByteToHex(*src++, dst, uppercase);
+ dst += 2;
+ if (data_size) {
+ NPT_CopyMemory(dst, separator, separator_length);
+ dst += separator_length;
+ }
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseFloat
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseFloat(const char* str, float& result, bool relaxed)
+{
+ // safe default value
+ result = 0.0f;
+
+ // check params
+ if (str == NULL || *str == '\0') {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // ignore leading whitespace
+ if (relaxed) {
+ while (*str == ' ' || *str == '\t') {
+ str++;
+ }
+ }
+ if (*str == '\0') {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // check for sign
+ bool negative = false;
+ if (*str == '-') {
+ // negative number
+ negative = true;
+ str++;
+ } else if (*str == '+') {
+ // skip the + sign
+ str++;
+ }
+
+ // parse the digits
+ bool after_radix = false;
+ bool empty = true;
+ float value = 0.0f;
+ float decimal = 10.0f;
+ char c;
+ while ((c = *str++)) {
+ if (c == '.') {
+ if (after_radix || (*str < '0' || *str > '9')) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ } else {
+ after_radix = true;
+ }
+ } else if (c >= '0' && c <= '9') {
+ empty = false;
+ if (after_radix) {
+ value += (float)(c-'0')/decimal;
+ decimal *= 10.0f;
+ } else {
+ value = 10.0f*value + (float)(c-'0');
+ }
+ } else if (c == 'e' || c == 'E') {
+ // exponent
+ if (*str == '+' || *str == '-' || (*str >= '0' && *str <= '9')) {
+ int exponent = 0;
+ if (NPT_SUCCEEDED(NPT_ParseInteger(str, exponent, relaxed))) {
+ value *= (float)pow(10.0f, (float)exponent);
+ break;
+ } else {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ } else {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ } else {
+ if (relaxed) {
+ break;
+ } else {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ }
+ }
+
+ // check that the value was non empty
+ if (empty) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // return the result
+ result = negative ? -value : value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger64(const char* str, NPT_Int64& result, bool relaxed, NPT_Cardinal* chars_used)
+{
+ // safe default value
+ result = 0;
+ if (chars_used) *chars_used = 0;
+
+ if (str == NULL) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // ignore leading whitespace
+ if (relaxed) {
+ while (*str == ' ' || *str == '\t') {
+ str++;
+ if (chars_used) (*chars_used)++;
+ }
+ }
+ if (*str == '\0') {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // check for sign
+ bool negative = false;
+ if (*str == '-') {
+ // negative number
+ negative = true;
+ str++;
+ if (chars_used) (*chars_used)++;
+ } else if (*str == '+') {
+ // skip the + sign
+ str++;
+ if (chars_used) (*chars_used)++;
+ }
+
+ // check for overflows
+ NPT_Int64 max = NPT_INT64_MAX/10;
+
+ // adjust the max for overflows when the value is negative
+ if (negative && ((NPT_INT64_MAX%10) == /* DISABLES CODE */ (9))) ++max;
+
+ // parse the digits
+ bool empty = true;
+ NPT_Int64 value = 0;
+ char c;
+ while ((c = *str++)) {
+ if (c >= '0' && c <= '9') {
+ if (value < 0 || value > max) return NPT_ERROR_OVERFLOW;
+ value = 10*value + (c-'0');
+ if (value < 0 && (!negative || value != NPT_INT64_MIN)) return NPT_ERROR_OVERFLOW;
+ empty = false;
+ if (chars_used) (*chars_used)++;
+ } else {
+ if (relaxed) {
+ break;
+ } else {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ }
+ }
+
+ // check that the value was non empty
+ if (empty) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // return the result
+ result = negative ? -value : value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger64(const char* str, NPT_UInt64& result, bool relaxed, NPT_Cardinal* chars_used)
+{
+ // safe default value
+ result = 0;
+ if (chars_used) *chars_used = 0;
+
+ if (str == NULL) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // ignore leading whitespace
+ if (relaxed) {
+ while (*str == ' ' || *str == '\t') {
+ str++;
+ if (chars_used) (*chars_used)++;
+ }
+ }
+ if (*str == '\0') {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // parse the digits
+ bool empty = true;
+ NPT_UInt64 value = 0;
+ char c;
+ while ((c = *str++)) {
+ if (c >= '0' && c <= '9') {
+ NPT_UInt64 new_value;
+ if (value > NPT_UINT64_MAX/10) return NPT_ERROR_OVERFLOW;
+ new_value = 10*value + (c-'0');
+ if (new_value < value) return NPT_ERROR_OVERFLOW;
+ value = new_value;
+ empty = false;
+ if (chars_used) (*chars_used)++;
+ } else {
+ if (relaxed) {
+ break;
+ } else {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ }
+ }
+
+ // check that the value was non empty
+ if (empty) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // return the result
+ result = value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger32(const char* str, NPT_Int32& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+ NPT_Int64 value_64;
+ NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+ value = 0;
+ if (NPT_SUCCEEDED(result)) {
+ if (value_64 < NPT_INT32_MIN || value_64 > NPT_INT32_MAX) {
+ return NPT_ERROR_OVERFLOW;
+ }
+ value = (NPT_Int32)value_64;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger32(const char* str, NPT_UInt32& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+ NPT_UInt64 value_64;
+ NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+ value = 0;
+ if (NPT_SUCCEEDED(result)) {
+ if (value_64 > (NPT_UInt64)NPT_UINT32_MAX) return NPT_ERROR_OVERFLOW;
+ value = (NPT_UInt32)value_64;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger(const char* str, long& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+ NPT_Int64 value_64;
+ NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+ value = 0;
+ if (NPT_SUCCEEDED(result)) {
+#if NPT_ULONG_MAX != NPT_UINT64_MAX
+ if (value_64 < NPT_LONG_MIN || value_64 > NPT_LONG_MAX) {
+ return NPT_ERROR_OVERFLOW;
+ }
+#endif
+ value = (long)value_64;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger(const char* str, unsigned long& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+ NPT_UInt64 value_64;
+ NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+ value = 0;
+ if (NPT_SUCCEEDED(result)) {
+#if NPT_ULONG_MAX != NPT_UINT64_MAX
+ if (value_64 > NPT_ULONG_MAX) {
+ return NPT_ERROR_OVERFLOW;
+ }
+#endif
+ value = (unsigned long)value_64;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger(const char* str, int& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+ NPT_Int64 value_64;
+ NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+ value = 0;
+ if (NPT_SUCCEEDED(result)) {
+ if (value_64 < NPT_INT_MIN || value_64 > NPT_INT_MAX) {
+ return NPT_ERROR_OVERFLOW;
+ }
+ value = (int)value_64;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ParseInteger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseInteger(const char* str, unsigned int& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+ NPT_UInt64 value_64;
+ NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+ value = 0;
+ if (NPT_SUCCEEDED(result)) {
+ if (value_64 > NPT_UINT_MAX) {
+ return NPT_ERROR_OVERFLOW;
+ }
+ value = (unsigned int)value_64;
+ }
+ return result;
+}
+
+#if !defined(NPT_CONFIG_HAVE_STRCPY)
+/*----------------------------------------------------------------------
+| NPT_CopyString
++---------------------------------------------------------------------*/
+void
+NPT_CopyString(char* dst, const char* src)
+{
+ while(*dst++ = *src++);
+}
+#endif
+
+/*----------------------------------------------------------------------
+| NPT_FormatOutput
++---------------------------------------------------------------------*/
+void
+NPT_FormatOutput(void (*function)(void* parameter, const char* message),
+ void* function_parameter,
+ const char* format,
+ va_list args)
+{
+ char local_buffer[NPT_FORMAT_LOCAL_BUFFER_SIZE];
+ unsigned int buffer_size = NPT_FORMAT_LOCAL_BUFFER_SIZE;
+ char* buffer = local_buffer;
+
+ for(;;) {
+ int result;
+
+ /* try to format the message (it might not fit) */
+ result = NPT_FormatStringVN(buffer, buffer_size-1, format, args);
+ buffer[buffer_size-1] = 0; /* force a NULL termination */
+ if (result >= 0) break;
+
+ /* the buffer was too small, try something bigger */
+ buffer_size = (buffer_size+NPT_FORMAT_BUFFER_INCREMENT)*2;
+ if (buffer_size > NPT_FORMAT_BUFFER_MAX_SIZE) break;
+ if (buffer != local_buffer) delete[] buffer;
+ buffer = new char[buffer_size];
+ if (buffer == NULL) return;
+ }
+
+ (*function)(function_parameter, buffer);
+ if (buffer != local_buffer) delete[] buffer;
+}
+
+/*----------------------------------------------------------------------
+| local types
++---------------------------------------------------------------------*/
+typedef enum {
+ NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME,
+ NPT_MIME_PARAMETER_PARSER_STATE_IN_NAME,
+ NPT_MIME_PARAMETER_PARSER_STATE_NEED_EQUALS,
+ NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE,
+ NPT_MIME_PARAMETER_PARSER_STATE_IN_VALUE,
+ NPT_MIME_PARAMETER_PARSER_STATE_IN_QUOTED_VALUE,
+ NPT_MIME_PARAMETER_PARSER_STATE_NEED_SEPARATOR
+} NPT_MimeParameterParserState;
+
+/*----------------------------------------------------------------------
+| NPT_ParseMimeParameters
+|
+| From RFC 822 and RFC 2045
+|
+| ; ( Octal, Decimal.)
+| CHAR = <any ASCII character> ; ( 0-177, 0.-127.)
+| ALPHA = <any ASCII alphabetic character>
+| ; (101-132, 65.- 90.)
+| ; (141-172, 97.-122.)
+| DIGIT = <any ASCII decimal digit> ; ( 60- 71, 48.- 57.)
+| CTL = <any ASCII control ; ( 0- 37, 0.- 31.)
+| character and DEL> ; ( 177, 127.)
+| CR = <ASCII CR, carriage return> ; ( 15, 13.)
+| LF = <ASCII LF, linefeed> ; ( 12, 10.)
+| SPACE = <ASCII SP, space> ; ( 40, 32.)
+| HTAB = <ASCII HT, horizontal-tab> ; ( 11, 9.)
+| <"> = <ASCII quote mark> ; ( 42, 34.)
+| CRLF = CR LF
+|
+| LWSP-char = SPACE / HTAB ; semantics = SPACE
+|
+| linear-white-space = 1*([CRLF] LWSP-char) ; semantics = SPACE
+| ; CRLF => folding
+|
+| parameter := attribute "=" value
+|
+| attribute := token
+| ; Matching of attributes
+| ; is ALWAYS case-insensitive.
+|
+| value := token / quoted-string
+|
+| token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, or tspecials>
+|
+| tspecials := "(" / ")" / "<" / ">" / "@" /
+| "," / ";" / ":" / "\" / <">
+| "/" / "[" / "]" / "?" / "="
+|
+| quoted-string = <"> *(qtext/quoted-pair) <">; Regular qtext or
+| ; quoted chars.
+|
+| qtext = <any CHAR excepting <">, ; => may be folded
+| "\" & CR, and including
+| linear-white-space>
+|
+| quoted-pair = "\" CHAR ; may quote any char
+|
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseMimeParameters(const char* encoded,
+ NPT_Map<NPT_String, NPT_String>& parameters)
+{
+ // check parameters
+ if (encoded == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // reserve some space
+ NPT_String param_name;
+ NPT_String param_value;
+ param_name.Reserve(64);
+ param_value.Reserve(64);
+
+ NPT_MimeParameterParserState state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME;
+ bool quoted_char = false;
+ for (;;) {
+ char c = *encoded++;
+ if (!quoted_char && (c == 0x0A || c == 0x0D)) continue; // ignore EOL chars
+ switch (state) {
+ case NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME:
+ if (c == '\0') break; // END
+ if (c == ' ' || c == '\t') continue; // ignore leading whitespace
+ if (c < ' ') return NPT_ERROR_INVALID_SYNTAX; // CTLs are invalid
+ param_name += c; // we're not strict: accept all other chars
+ state = NPT_MIME_PARAMETER_PARSER_STATE_IN_NAME;
+ break;
+
+ case NPT_MIME_PARAMETER_PARSER_STATE_IN_NAME:
+ if (c < ' ') return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+ if (c == ' ') {
+ state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_EQUALS;
+ } else if (c == '=') {
+ state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE;
+ } else {
+ param_name += c; // we're not strict: accept all other chars
+ }
+ break;
+
+ case NPT_MIME_PARAMETER_PARSER_STATE_NEED_EQUALS:
+ if (c < ' ') return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+ if (c == ' ' || c == '\t') continue; // ignore leading whitespace
+ if (c != '=') return NPT_ERROR_INVALID_SYNTAX;
+ state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE;
+ break;
+
+ case NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE:
+ if (c < ' ') return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+ if (c == ' ' || c == '\t') continue; // ignore leading whitespace
+ if (c == '"') {
+ state = NPT_MIME_PARAMETER_PARSER_STATE_IN_QUOTED_VALUE;
+ } else {
+ param_value += c; // we're not strict: accept all other chars
+ state = NPT_MIME_PARAMETER_PARSER_STATE_IN_VALUE;
+ }
+ break;
+
+ case NPT_MIME_PARAMETER_PARSER_STATE_IN_QUOTED_VALUE:
+ if (quoted_char) {
+ quoted_char = false;
+ if (c == '\0') return NPT_ERROR_INVALID_SYNTAX;
+ param_value += c; // accept all chars
+ break;
+ } else if (c == '\\') {
+ quoted_char = true;
+ break;
+ } else if (c == '"') {
+ // add the parameter to the map
+ param_name.TrimRight();
+ param_value.TrimRight();
+ parameters[param_name] = param_value;
+ param_name.SetLength(0);
+ param_value.SetLength(0);
+ state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_SEPARATOR;
+ } else if (c < ' ') {
+ return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+ } else {
+ param_value += c; // we're not strict: accept all other chars
+ }
+ break;
+
+ case NPT_MIME_PARAMETER_PARSER_STATE_IN_VALUE:
+ if (c == '\0' || c == ';') {
+ // add the parameter to the map
+ param_name.TrimRight();
+ param_value.TrimRight();
+ parameters[param_name] = param_value;
+ param_name.SetLength(0);
+ param_value.SetLength(0);
+ state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME;
+ } else if (c < ' ') {
+ // CTLs are invalid
+ return NPT_ERROR_INVALID_SYNTAX;
+ } else {
+ param_value += c; // we're not strict: accept all other chars
+ }
+ break;
+
+ case NPT_MIME_PARAMETER_PARSER_STATE_NEED_SEPARATOR:
+ if (c == '\0') break;
+ if (c < ' ') return NPT_ERROR_INVALID_SYNTAX; // CTLs are invalid
+ if (c == ' ' || c == '\t') continue; // ignore whitespace
+ if (c != ';') return NPT_ERROR_INVALID_SYNTAX;
+ state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME;
+ break;
+ }
+ if (c == '\0') break; // end of buffer
+ }
+
+ return NPT_SUCCESS;
+}
+
+#ifdef TARGET_WINDOWS_STORE
+std::wstring win32ConvertUtf8ToW(const std::string &text)
+{
+ if (text.empty())
+ {
+ return L"";
+ }
+
+ int bufSize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text.c_str(), -1, NULL, 0);
+ if (bufSize == 0)
+ return L"";
+ wchar_t *converted = new wchar_t[bufSize];
+ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text.c_str(), -1, converted, bufSize) != bufSize)
+ {
+ delete[] converted;
+ return L"";
+ }
+
+ std::wstring Wret(converted);
+ delete[] converted;
+
+ return Wret;
+}
+#endif
diff --git a/lib/libUPnP/Neptune/Source/Core/NptUtils.h b/lib/libUPnP/Neptune/Source/Core/NptUtils.h
new file mode 100644
index 0000000..89b2e29
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptUtils.h
@@ -0,0 +1,235 @@
+/*****************************************************************
+|
+| Neptune Utils
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_UTILS_H_
+#define _NPT_UTILS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptStrings.h"
+#include "NptMap.h"
+#include "NptDataBuffer.h"
+#include "NptHash.h"
+
+#if defined (NPT_CONFIG_HAVE_STDIO_H)
+#include <stdio.h>
+#endif
+
+#if defined (NPT_CONFIG_HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STDARG_H)
+#include <stdarg.h>
+#endif
+
+#if defined(TARGET_WINDOWS_STORE)
+#include <string>
+#endif
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define NPT_ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
+
+/*----------------------------------------------------------------------
+| byte I/O
++---------------------------------------------------------------------*/
+extern void NPT_BytesFromInt64Be(unsigned char* buffer, NPT_UInt64 value);
+extern void NPT_BytesFromInt32Be(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt24Be(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt16Be(unsigned char* buffer, NPT_UInt16 value);
+extern NPT_UInt64 NPT_BytesToInt64Be(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt32Be(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt24Be(const unsigned char* buffer);
+extern NPT_UInt16 NPT_BytesToInt16Be(const unsigned char* buffer);
+
+extern void NPT_BytesFromInt64Le(unsigned char* buffer, NPT_UInt64 value);
+extern void NPT_BytesFromInt32Le(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt24Le(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt16Le(unsigned char* buffer, NPT_UInt16 value);
+extern NPT_UInt64 NPT_BytesToInt64Le(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt32Le(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt24Le(const unsigned char* buffer);
+extern NPT_UInt16 NPT_BytesToInt16Le(const unsigned char* buffer);
+
+/*----------------------------------------------------------------------
+| conversion utilities
++---------------------------------------------------------------------*/
+extern NPT_Result
+NPT_ParseFloat(const char* str, float& result, bool relaxed = true);
+
+extern NPT_Result
+NPT_ParseInteger(const char* str, long& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger(const char* str, unsigned long& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger(const char* str, int& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger(const char* str, unsigned int& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger32(const char* str, NPT_Int32& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger32(const char* str, NPT_UInt32& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger64(const char* str, NPT_Int64& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result
+NPT_ParseInteger64(const char* str, NPT_UInt64& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+/*----------------------------------------------------------------------
+| formatting
++---------------------------------------------------------------------*/
+void
+NPT_FormatOutput(void (*function)(void* parameter, const char* message),
+ void* function_parameter,
+ const char* format,
+ va_list args);
+
+void NPT_ByteToHex(NPT_Byte b, char* buffer, bool uppercase=false);
+NPT_Result NPT_HexToByte(const char* buffer, NPT_Byte& b);
+NPT_Result NPT_HexToBytes(const char* hex, NPT_DataBuffer& bytes);
+NPT_String NPT_HexString(const unsigned char* data,
+ NPT_Size data_size,
+ const char* separator = NULL,
+ bool uppercase=false);
+char NPT_NibbleToHex(unsigned int nibble, bool uppercase = true);
+int NPT_HexToNibble(char hex);
+
+/*----------------------------------------------------------------------
+| parsing
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ParseMimeParameters(const char* encoded,
+ NPT_Map<NPT_String, NPT_String>& parameters);
+
+/*----------------------------------------------------------------------
+| environment variables
++---------------------------------------------------------------------*/
+class NPT_Environment {
+public:
+ static NPT_Result Get(const char* name, NPT_String& value);
+ static NPT_Result Set(const char* name, const char* value);
+};
+// compat for older APIs
+#define NPT_GetEnvironment(_x,_y) NPT_Environment::Get(_x,_y)
+
+/*----------------------------------------------------------------------
+| string utils
++---------------------------------------------------------------------*/
+#if defined (NPT_CONFIG_HAVE_STDIO_H)
+#include <stdio.h>
+#endif
+
+#if defined (NPT_CONFIG_HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#if defined (NPT_CONFIG_HAVE_SNPRINTF)
+#define NPT_FormatString NPT_snprintf
+#else
+int NPT_FormatString(char* str, NPT_Size size, const char* format, ...);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_VSNPRINTF)
+#define NPT_FormatStringVN(s,c,f,a) NPT_vsnprintf(s,c,f,a)
+#else
+extern int NPT_FormatStringVN(char *buffer, size_t count, const char *format, va_list argptr);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_MEMCPY)
+#define NPT_CopyMemory memcpy
+#else
+extern void NPT_CopyMemory(void* dest, void* src, NPT_Size size);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRCMP)
+#define NPT_StringsEqual(s1, s2) (strcmp((s1), (s2)) == 0)
+#else
+extern int NPT_StringsEqual(const char* s1, const char* s2);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRNCMP)
+#define NPT_StringsEqualN(s1, s2, n) (strncmp((s1), (s2), (n)) == 0)
+#else
+extern int NPT_StringsEqualN(const char* s1, const char* s2, unsigned long size);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRLEN)
+#define NPT_StringLength(s) (NPT_Size)(strlen(s))
+#else
+extern unsigned long NPT_StringLength(const char* s);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRCPY)
+#define NPT_CopyString(dst, src) ((void)NPT_strcpy((dst), (src)))
+#else
+extern void NPT_CopyString(char* dst, const char* src);
+#endif
+
+/**
+ * Copy up to n characters from src to dst.
+ * The destination buffer will be null-terminated, so it must
+ * have enough space for n+1 characters (n from the source plus
+ * the null terminator).
+ */
+#if defined(NPT_CONFIG_HAVE_STRNCPY)
+#define NPT_CopyStringN(dst, src, n) \
+do { ((void)NPT_strncpy((dst), (src), n)); (dst)[(n)] = '\0'; } while(0)
+#else
+extern int NPT_CopyStringN(char* dst, const char* src, unsigned long n);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_MEMSET)
+#define NPT_SetMemory memset
+#else
+extern void NPT_SetMemory(void* dest, int c, NPT_Size size);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_MEMCMP)
+#define NPT_MemoryEqual(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
+#else
+extern int NPT_MemoryEqual(const void* s1, const void* s2, unsigned long n);
+#endif
+
+#if defined(TARGET_WINDOWS_STORE)
+std::wstring win32ConvertUtf8ToW(const std::string &text);
+#endif
+
+#endif // _NPT_UTILS_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptVersion.h b/lib/libUPnP/Neptune/Source/Core/NptVersion.h
new file mode 100644
index 0000000..ad34d90
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptVersion.h
@@ -0,0 +1,41 @@
+/*****************************************************************
+|
+| Neptune - Version Info
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_VERSION_H_
+#define _NPT_VERSION_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#define NPT_NEPTUNE_VERSION 0x01010300
+#define NPT_NEPTUNE_VERSION_STRING "1.1.3"
+
+#endif // _NPT_VERSION_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptXml.cpp b/lib/libUPnP/Neptune/Source/Core/NptXml.cpp
new file mode 100644
index 0000000..d6b95ca
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptXml.cpp
@@ -0,0 +1,2611 @@
+/*****************************************************************
+|
+| Neptune - Xml Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptXml.h"
+#include "NptUtils.h"
+#include "NptMap.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+| local compilation flags
++---------------------------------------------------------------------*/
+//#define NPT_XML_PARSER_DEBUG
+#ifdef NPT_XML_PARSER_DEBUG
+#define NPT_XML_Debug_0(s) NPT_Debug(s)
+#define NPT_XML_Debug_1(s,x0) NPT_Debug(s,x0)
+#define NPT_XML_Debug_2(s,x0,x1) NPT_Debug(s,x0,x1)
+#define NPT_XML_Debug_3(s,x0,x1,x2) NPT_Debug(s,x0,x1,x2)
+#define NPT_XML_Debug_4(s,x0,x1,x2,x3) NPT_Debug(s,x0,x1,x2,x3)
+#else
+#define NPT_XML_Debug_0(s)
+#define NPT_XML_Debug_1(s,x0)
+#define NPT_XML_Debug_2(s,x0,x1)
+#define NPT_XML_Debug_3(s,x0,x1,x2)
+#define NPT_XML_Debug_4(s,x0,x1,x2,x3)
+#endif
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+static const NPT_String
+NPT_XmlNamespaceUri_Xml("http://www.w3.org/XML/1998/namespace");
+
+/*----------------------------------------------------------------------
+| NPT_XmlAttributeFinder
++---------------------------------------------------------------------*/
+class NPT_XmlAttributeFinder
+{
+public:
+ // if 'namespc' is NULL, we're looking for ANY namespace
+ // if 'namespc' is '\0', we're looking for NO namespace
+ // if 'namespc' is non-empty, look for that SPECIFIC namespace
+ NPT_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->m_Name == m_Name) {
+ if (m_Namespace) {
+ const NPT_String& prefix = attribute->GetPrefix();
+ if (m_Namespace[0] == '\0') {
+ // match if the attribute has NO namespace
+ return prefix.IsEmpty();
+ } else {
+ // match if the attribute has the SPECIFIC namespace
+ // we're looking for
+ if (prefix.IsEmpty()) {
+ // attributes without a prefix don't have a namespace
+ return false;
+ } else {
+ const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
+ return namespc && *namespc == m_Namespace;
+ }
+ }
+ } else {
+ // ANY namespace will match
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+private:
+ const NPT_XmlElementNode& m_Element;
+ const char* m_Name;
+ const char* m_Namespace;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlAttributeFinderWithPrefix
++---------------------------------------------------------------------*/
+class NPT_XmlAttributeFinderWithPrefix
+{
+public:
+ NPT_XmlAttributeFinderWithPrefix(const char* prefix, const char* name) :
+ m_Prefix(prefix?prefix:""), m_Name(name) {}
+
+ bool operator()(const NPT_XmlAttribute* const & attribute) const {
+ return attribute->m_Prefix == m_Prefix && attribute->m_Name == m_Name;
+ }
+
+private:
+ const char* m_Prefix;
+ const char* m_Name;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlTagFinder
++---------------------------------------------------------------------*/
+class NPT_XmlTagFinder
+{
+public:
+ // if 'namespc' is NULL, we're looking for ANY namespace
+ // if 'namespc' is '\0', we're looking for NO namespace
+ // if 'namespc' is non-empty, look for that SPECIFIC namespace
+ NPT_XmlTagFinder(const char* tag, const char* namespc) :
+ m_Tag(tag), m_Namespace(namespc) {}
+
+ bool operator()(const NPT_XmlNode* const & node) const {
+ const NPT_XmlElementNode* element = node->AsElementNode();
+ if (element && element->m_Tag == m_Tag) {
+ if (m_Namespace) {
+ // look for a SPECIFIC namespace or NO namespace
+ const NPT_String* namespc = element->GetNamespace();
+ if (namespc) {
+ // the element has a namespace, match if it is equal to
+ // what we're looking for
+ return *namespc == m_Namespace;
+ } else {
+ // the element does not have a namespace, match if we're
+ // looking for NO namespace
+ return m_Namespace[0] == '\0';
+ }
+ } else {
+ // ANY namespace will match
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+private:
+ const char* m_Tag;
+ const char* m_Namespace;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlTextFinder
++---------------------------------------------------------------------*/
+class NPT_XmlTextFinder
+{
+public:
+ bool operator()(const NPT_XmlNode* const & node) const {
+ return node->AsTextNode() != NULL;
+ }
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceCollapser
++---------------------------------------------------------------------*/
+class NPT_XmlNamespaceCollapser
+{
+public:
+ NPT_XmlNamespaceCollapser(NPT_XmlElementNode* element) :
+ m_Root(element) {}
+
+ void operator()(NPT_XmlNode*& node) const {
+ NPT_XmlElementNode* element = node->AsElementNode();
+ if (element == NULL) return;
+
+ // collapse the namespace for this element
+ CollapseNamespace(element, element->GetPrefix());
+
+ // collapse the namespaces for the attributes
+ NPT_List<NPT_XmlAttribute*>::Iterator item = element->GetAttributes().GetFirstItem();
+ while (item) {
+ NPT_XmlAttribute* attribute = *item;
+ CollapseNamespace(element, attribute->GetPrefix());
+ ++item;
+ }
+
+ // recurse to the children
+ element->GetChildren().Apply(*this);
+ }
+
+private:
+ // methods
+ void CollapseNamespace(NPT_XmlElementNode* element, const NPT_String& prefix) const;
+
+ // members
+ NPT_XmlElementNode* m_Root;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceCollapser::CollapseNamespace
++---------------------------------------------------------------------*/
+void
+NPT_XmlNamespaceCollapser::CollapseNamespace(NPT_XmlElementNode* element,
+ const NPT_String& prefix) const
+{
+ if (m_Root->m_NamespaceMap == NULL ||
+ (m_Root->m_NamespaceMap->GetNamespaceUri(prefix) == NULL && prefix != "xml")) {
+ // the root element does not have that prefix in the map
+ const NPT_String* uri = element->GetNamespaceUri(prefix);
+ if (uri) m_Root->SetNamespaceUri(prefix, uri->GetChars());
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAttribute::NPT_XmlAttribute
++---------------------------------------------------------------------*/
+NPT_XmlAttribute::NPT_XmlAttribute(const char* name, const char* value) :
+ m_Value(value)
+{
+ const char* cursor = name;
+ while (char c = *cursor++) {
+ if (c == ':') {
+ unsigned int prefix_length = (unsigned int)(cursor-name)-1;
+ m_Prefix.Assign(name, prefix_length);
+ name = cursor;
+ break;
+ }
+ }
+ m_Name = name;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::NPT_XmlElementNode
++---------------------------------------------------------------------*/
+NPT_XmlElementNode::NPT_XmlElementNode(const char* prefix, const char* tag) :
+ NPT_XmlNode(ELEMENT),
+ m_Prefix(prefix),
+ m_Tag(tag),
+ m_NamespaceMap(NULL),
+ m_NamespaceParent(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::NPT_XmlElementNode
++---------------------------------------------------------------------*/
+NPT_XmlElementNode::NPT_XmlElementNode(const char* tag) :
+ NPT_XmlNode(ELEMENT),
+ m_NamespaceMap(NULL),
+ m_NamespaceParent(NULL)
+{
+ const char* cursor = tag;
+ while (char c = *cursor++) {
+ if (c == ':') {
+ unsigned int prefix_length = (unsigned int)(cursor-tag)-1;
+ m_Prefix.Assign(tag, prefix_length);
+ tag = cursor;
+ break;
+ }
+ }
+ m_Tag = tag;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::~NPT_XmlElementNode
++---------------------------------------------------------------------*/
+NPT_XmlElementNode::~NPT_XmlElementNode()
+{
+ m_Children.Apply(NPT_ObjectDeleter<NPT_XmlNode>());
+ m_Attributes.Apply(NPT_ObjectDeleter<NPT_XmlAttribute>());
+ delete m_NamespaceMap;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::SetParent
++---------------------------------------------------------------------*/
+void
+NPT_XmlElementNode::SetParent(NPT_XmlNode* parent)
+{
+ // update our parent
+ m_Parent = parent;
+
+ // update out namespace linkage
+ NPT_XmlElementNode* parent_element =
+ parent?parent->AsElementNode():NULL;
+ NPT_XmlElementNode* namespace_parent;
+ if (parent_element) {
+ namespace_parent =
+ parent_element->m_NamespaceMap ?
+ parent_element:
+ parent_element->m_NamespaceParent;
+ } else {
+ namespace_parent = NULL;
+ }
+ if (namespace_parent != m_NamespaceParent) {
+ m_NamespaceParent = namespace_parent;
+ RelinkNamespaceMaps();
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::AddChild
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::AddChild(NPT_XmlNode* child)
+{
+ if (child == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+ child->SetParent(this);
+ return m_Children.Add(child);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::GetChild
++---------------------------------------------------------------------*/
+NPT_XmlElementNode*
+NPT_XmlElementNode::GetChild(const char* tag, const char* namespc, NPT_Ordinal n) const
+{
+ // remap the requested namespace to match the semantics of the finder
+ // and allow for "" to also mean NO namespace
+ if (namespc == NULL || namespc[0] == '\0') {
+ namespc = ""; // for the finder, empty string means NO namespace
+ } else if (namespc[0] == '*' && namespc[1] == '\0') {
+ namespc = NULL; // for the finder, NULL means ANY namespace
+ }
+
+ // find the child
+ NPT_List<NPT_XmlNode*>::Iterator item;
+ item = m_Children.Find(NPT_XmlTagFinder(tag, namespc), n);
+ return item?(*item)->AsElementNode():NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::AddAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::AddAttribute(const char* name,
+ const char* value)
+{
+ if (name == NULL || value == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+ return m_Attributes.Add(new NPT_XmlAttribute(name, value));
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::SetAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::SetAttribute(const char* prefix,
+ const char* name,
+ const char* value)
+{
+ if (name == NULL || value == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ /* see if this attribute is already set */
+ NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+ attribute = m_Attributes.Find(NPT_XmlAttributeFinderWithPrefix(prefix, name));
+ if (attribute) {
+ // an attribute with this name and prefix already exists,
+ // change its value
+ (*attribute)->SetValue(value);
+ return NPT_SUCCESS;
+ }
+ return m_Attributes.Add(new NPT_XmlAttribute(prefix, name, value));
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::SetAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::SetAttribute(const char* name, const char* value)
+{
+ return SetAttribute(NULL, name, value);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::GetAttribute
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetAttribute(const char* name, const char* namespc) const
+{
+ // remap the requested namespace to match the semantics of the finder
+ // and allow for "" to also mean NO namespace
+ if (namespc == NULL || namespc[0] == '\0') {
+ namespc = ""; // for the finder, empty string means NO namespace
+ } else if (namespc[0] == '*' && namespc[1] == '\0') {
+ namespc = NULL; // for the finder, NULL means ANY namespace
+ }
+
+ // find the attribute
+ NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+ attribute = m_Attributes.Find(NPT_XmlAttributeFinder(*this, name, namespc));
+ if (attribute) {
+ return &(*attribute)->GetValue();
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::AddText
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::AddText(const char* text)
+{
+ return AddChild(new NPT_XmlTextNode(NPT_XmlTextNode::CHARACTER_DATA, text));
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::GetText
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetText(NPT_Ordinal n) const
+{
+ NPT_List<NPT_XmlNode*>::Iterator node;
+ node = m_Children.Find(NPT_XmlTextFinder(), n);
+ return node?&(*node)->AsTextNode()->GetString():NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::MakeStandalone
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::MakeStandalone()
+{
+ NPT_XmlNamespaceCollapser collapser(this);
+ NPT_XmlNode* node_pointer = this;
+ collapser(node_pointer);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::RelinkNamespaceMaps
++---------------------------------------------------------------------*/
+void
+NPT_XmlElementNode::RelinkNamespaceMaps()
+{
+ // update our children so that they can inherit the right
+ // namespace map
+ NPT_List<NPT_XmlNode*>::Iterator item = m_Children.GetFirstItem();
+ while (item) {
+ NPT_XmlElementNode* element = (*item)->AsElementNode();
+ if (element) {
+ if (m_NamespaceMap) {
+ // we have a map, so our children point to us
+ element->SetNamespaceParent(this);
+ } else {
+ // we don't have a map, so our children point to
+ // where we also point
+ element->SetNamespaceParent(m_NamespaceParent);
+ }
+ }
+ ++item;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::SetNamespaceParent
++---------------------------------------------------------------------*/
+void
+NPT_XmlElementNode::SetNamespaceParent(NPT_XmlElementNode* parent)
+{
+ m_NamespaceParent = parent;
+ RelinkNamespaceMaps();
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::SetNamespaceUri
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::SetNamespaceUri(const char* prefix, const char* uri)
+{
+ // ensure that we have a namespace map
+ if (m_NamespaceMap == NULL) {
+ m_NamespaceMap = new NPT_XmlNamespaceMap();
+ RelinkNamespaceMaps();
+ }
+
+ return m_NamespaceMap->SetNamespaceUri(prefix, uri);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::GetNamespaceUri
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetNamespaceUri(const char* prefix) const
+{
+ if (m_NamespaceMap) {
+ // look in our namespace map first
+ const NPT_String* namespc = m_NamespaceMap->GetNamespaceUri(prefix);
+ if (namespc) {
+ if (namespc->IsEmpty()) {
+ return NULL;
+ } else {
+ return namespc;
+ }
+ }
+ }
+
+ // look into our parent's namespace map
+ if (m_NamespaceParent) {
+ return m_NamespaceParent->GetNamespaceUri(prefix);
+ } else {
+ // check if this is a well-known namespace
+ if (prefix[0] == 'x' &&
+ prefix[1] == 'm' &&
+ prefix[2] == 'l' &&
+ prefix[3] == '\0') {
+ return &NPT_XmlNamespaceUri_Xml;
+ }
+
+ // not found
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::GetNamespace
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetNamespace() const
+{
+ return GetNamespaceUri(m_Prefix);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode::GetNamespacePrefix
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetNamespacePrefix(const char* uri) const
+{
+ NPT_XmlNamespaceMap* namespace_map =
+ m_NamespaceMap?
+ m_NamespaceMap:
+ (m_NamespaceParent?
+ m_NamespaceParent->m_NamespaceMap:
+ NULL);
+
+ if (namespace_map) {
+ return namespace_map->GetNamespacePrefix(uri);
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlTextNode::NPT_XmlTextNode
++---------------------------------------------------------------------*/
+NPT_XmlTextNode::NPT_XmlTextNode(TokenType token_type, const char* text) :
+ NPT_XmlNode(TEXT),
+ m_TokenType(token_type),
+ m_Text(text)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator
++---------------------------------------------------------------------*/
+class NPT_XmlAccumulator {
+public:
+ NPT_XmlAccumulator();
+ ~NPT_XmlAccumulator();
+ void Append(char c);
+ void Append(const char* s);
+ void AppendUTF8(unsigned int c);
+ void Reset() { m_Valid = 0; }
+ const char* GetString();
+ NPT_Size GetSize() const { return m_Valid; }
+ const unsigned char* GetBuffer() const { return m_Buffer; }
+
+private:
+ // methods
+ void Allocate(NPT_Size size);
+
+ // members
+ unsigned char* m_Buffer;
+ NPT_Size m_Allocated;
+ NPT_Size m_Valid;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::NPT_XmlAccumulator
++---------------------------------------------------------------------*/
+NPT_XmlAccumulator::NPT_XmlAccumulator() :
+ m_Buffer(NULL),
+ m_Allocated(0),
+ m_Valid(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::~NPT_XmlAccumulator
++---------------------------------------------------------------------*/
+NPT_XmlAccumulator::~NPT_XmlAccumulator()
+{
+ delete[] m_Buffer;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::Allocate
++---------------------------------------------------------------------*/
+void
+NPT_XmlAccumulator::Allocate(NPT_Size size)
+{
+ // check if we have enough
+ if (m_Allocated >= size) return;
+
+ // compute new size
+ do {
+ m_Allocated = m_Allocated ? m_Allocated * 2 : 32;
+ } while (m_Allocated < size);
+
+ // reallocate
+ unsigned char* new_buffer = new unsigned char[m_Allocated];
+ NPT_CopyMemory(new_buffer, m_Buffer, m_Valid);
+ delete[] m_Buffer;
+ m_Buffer = new_buffer;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::Append
++---------------------------------------------------------------------*/
+inline void
+NPT_XmlAccumulator::Append(char c)
+{
+ NPT_Size needed = m_Valid+1;
+ if (needed > m_Allocated) Allocate(needed);
+ m_Buffer[m_Valid++] = c;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::Append
++---------------------------------------------------------------------*/
+void
+NPT_XmlAccumulator::Append(const char* s)
+{
+ char c;
+ while ((c = *s++)) Append(c);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::AppendUTF8
++---------------------------------------------------------------------*/
+inline void
+NPT_XmlAccumulator::AppendUTF8(unsigned int c)
+{
+ NPT_Size needed = m_Valid+4; // allocate 4 more chars
+ if (needed > m_Allocated) Allocate(needed);
+
+ if (c <= 0x7F) {
+ // 000000-00007F -> 1 char = 0xxxxxxx
+ m_Buffer[m_Valid++] = (char)c;
+ } else if (c <= 0x7FF) {
+ // 000080-0007FF -> 2 chars = 110zzzzx 10xxxxxx
+ m_Buffer[m_Valid++] = 0xC0|(c>>6 );
+ m_Buffer[m_Valid++] = 0x80|(c&0x3F);
+ } else if (c <= 0xFFFF) {
+ // 000800-00FFFF -> 3 chars = 1110zzzz 10zxxxxx 10xxxxxx
+ m_Buffer[m_Valid++] = 0xE0| (c>>12 );
+ m_Buffer[m_Valid++] = 0x80|((c&0xFC0)>>6);
+ m_Buffer[m_Valid++] = 0x80| (c&0x3F );
+ } else if (c <= 0x10FFFF) {
+ // 010000-10FFFF -> 4 chars = 11110zzz 10zzxxxx 10xxxxxx 10xxxxxx
+ m_Buffer[m_Valid++] = 0xF0| (c>>18 );
+ m_Buffer[m_Valid++] = 0x80|((c&0x3F000)>>12);
+ m_Buffer[m_Valid++] = 0x80|((c&0xFC0 )>> 6);
+ m_Buffer[m_Valid++] = 0x80| (c&0x3F );
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAccumulator::GetString
++---------------------------------------------------------------------*/
+inline const char*
+NPT_XmlAccumulator::GetString()
+{
+ // ensure that the buffer is NULL terminated
+ Allocate(m_Valid+1);
+ m_Buffer[m_Valid] = '\0';
+ return (const char*)m_Buffer;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceMap::~NPT_XmlNamespaceMap
++---------------------------------------------------------------------*/
+NPT_XmlNamespaceMap::~NPT_XmlNamespaceMap()
+{
+ m_Entries.Apply(NPT_ObjectDeleter<Entry>());
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceMap::SetNamespaceUri
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlNamespaceMap::SetNamespaceUri(const char* prefix, const char* uri)
+{
+ NPT_List<Entry*>::Iterator item = m_Entries.GetFirstItem();
+ while (item) {
+ if ((*item)->m_Prefix == prefix) {
+ // the prefix is already in the map, update the value
+ (*item)->m_Uri = uri;
+ return NPT_SUCCESS;
+ }
+ ++item;
+ }
+
+ // the prefix is not in the map, add it
+ return m_Entries.Add(new Entry(prefix, uri));
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceMap::GetNamespaceUri
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlNamespaceMap::GetNamespaceUri(const char* prefix)
+{
+ NPT_List<Entry*>::Iterator item = m_Entries.GetFirstItem();
+ while (item) {
+ if ((*item)->m_Prefix == prefix) {
+ // match
+ return &(*item)->m_Uri;
+ }
+ ++item;
+ }
+
+ // the prefix is not in the map
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceMap::GetNamespacePrefix
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlNamespaceMap::GetNamespacePrefix(const char* uri)
+{
+ NPT_List<Entry*>::Iterator item = m_Entries.GetFirstItem();
+ while (item) {
+ if ((*item)->m_Uri == uri) {
+ // match
+ return &(*item)->m_Prefix;
+ }
+ ++item;
+ }
+
+ // the uri is not in the map
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| character map
+|
+| flags:
+| 1 --> any char
+| 2 --> whitespace
+| 4 --> name
+| 8 --> content
+| 16 --> value
++---------------------------------------------------------------------*/
+#define NPT_XML_USE_CHAR_MAP
+#if defined(NPT_XML_USE_CHAR_MAP)
+// NOTE: this table is generated by the ruby script 'XmlCharMap.rb'
+static const unsigned char NPT_XmlCharMap[256] = {
+ 0, // 0 0x00
+ 0, // 1 0x01
+ 0, // 2 0x02
+ 0, // 3 0x03
+ 0, // 4 0x04
+ 0, // 5 0x05
+ 0, // 6 0x06
+ 0, // 7 0x07
+ 0, // 8 0x08
+ 1|2|8|16, // 9 0x09
+ 1|2|8|16, // 10 0x0a
+ 0, // 11 0x0b
+ 0, // 12 0x0c
+ 1|2|8|16, // 13 0x0d
+ 0, // 14 0x0e
+ 0, // 15 0x0f
+ 0, // 16 0x10
+ 0, // 17 0x11
+ 0, // 18 0x12
+ 0, // 19 0x13
+ 0, // 20 0x14
+ 0, // 21 0x15
+ 0, // 22 0x16
+ 0, // 23 0x17
+ 0, // 24 0x18
+ 0, // 25 0x19
+ 0, // 26 0x1a
+ 0, // 27 0x1b
+ 0, // 28 0x1c
+ 0, // 29 0x1d
+ 0, // 30 0x1e
+ 0, // 31 0x1f
+ 1|2|8|16, // 32 0x20 ' '
+ 1|8|16, // 33 0x21 '!'
+ 1|8|16, // 34 0x22 '"'
+ 1|8|16, // 35 0x23 '#'
+ 1|8|16, // 36 0x24 '$'
+ 1|8|16, // 37 0x25 '%'
+ 1, // 38 0x26 '&'
+ 1|8|16, // 39 0x27 '''
+ 1|8|16, // 40 0x28 '('
+ 1|8|16, // 41 0x29 ')'
+ 1|8|16, // 42 0x2a '*'
+ 1|8|16, // 43 0x2b '+'
+ 1|8|16, // 44 0x2c ','
+ 1|4|8|16, // 45 0x2d '-'
+ 1|4|8|16, // 46 0x2e '.'
+ 1|8|16, // 47 0x2f '/'
+ 1|4|8|16, // 48 0x30 '0'
+ 1|4|8|16, // 49 0x31 '1'
+ 1|4|8|16, // 50 0x32 '2'
+ 1|4|8|16, // 51 0x33 '3'
+ 1|4|8|16, // 52 0x34 '4'
+ 1|4|8|16, // 53 0x35 '5'
+ 1|4|8|16, // 54 0x36 '6'
+ 1|4|8|16, // 55 0x37 '7'
+ 1|4|8|16, // 56 0x38 '8'
+ 1|4|8|16, // 57 0x39 '9'
+ 1|4|8|16, // 58 0x3a ':'
+ 1|8|16, // 59 0x3b ';'
+ 1, // 60 0x3c '<'
+ 1|8|16, // 61 0x3d '='
+ 1|8|16, // 62 0x3e '>'
+ 1|8|16, // 63 0x3f '?'
+ 1|8|16, // 64 0x40 '@'
+ 1|4|8|16, // 65 0x41 'A'
+ 1|4|8|16, // 66 0x42 'B'
+ 1|4|8|16, // 67 0x43 'C'
+ 1|4|8|16, // 68 0x44 'D'
+ 1|4|8|16, // 69 0x45 'E'
+ 1|4|8|16, // 70 0x46 'F'
+ 1|4|8|16, // 71 0x47 'G'
+ 1|4|8|16, // 72 0x48 'H'
+ 1|4|8|16, // 73 0x49 'I'
+ 1|4|8|16, // 74 0x4a 'J'
+ 1|4|8|16, // 75 0x4b 'K'
+ 1|4|8|16, // 76 0x4c 'L'
+ 1|4|8|16, // 77 0x4d 'M'
+ 1|4|8|16, // 78 0x4e 'N'
+ 1|4|8|16, // 79 0x4f 'O'
+ 1|4|8|16, // 80 0x50 'P'
+ 1|4|8|16, // 81 0x51 'Q'
+ 1|4|8|16, // 82 0x52 'R'
+ 1|4|8|16, // 83 0x53 'S'
+ 1|4|8|16, // 84 0x54 'T'
+ 1|4|8|16, // 85 0x55 'U'
+ 1|4|8|16, // 86 0x56 'V'
+ 1|4|8|16, // 87 0x57 'W'
+ 1|4|8|16, // 88 0x58 'X'
+ 1|4|8|16, // 89 0x59 'Y'
+ 1|4|8|16, // 90 0x5a 'Z'
+ 1|8|16, // 91 0x5b '['
+ 1|8|16, // 92 0x5c '\'
+ 1|8|16, // 93 0x5d ']'
+ 1|8|16, // 94 0x5e '^'
+ 1|4|8|16, // 95 0x5f '_'
+ 1|8|16, // 96 0x60 '`'
+ 1|4|8|16, // 97 0x61 'a'
+ 1|4|8|16, // 98 0x62 'b'
+ 1|4|8|16, // 99 0x63 'c'
+ 1|4|8|16, // 100 0x64 'd'
+ 1|4|8|16, // 101 0x65 'e'
+ 1|4|8|16, // 102 0x66 'f'
+ 1|4|8|16, // 103 0x67 'g'
+ 1|4|8|16, // 104 0x68 'h'
+ 1|4|8|16, // 105 0x69 'i'
+ 1|4|8|16, // 106 0x6a 'j'
+ 1|4|8|16, // 107 0x6b 'k'
+ 1|4|8|16, // 108 0x6c 'l'
+ 1|4|8|16, // 109 0x6d 'm'
+ 1|4|8|16, // 110 0x6e 'n'
+ 1|4|8|16, // 111 0x6f 'o'
+ 1|4|8|16, // 112 0x70 'p'
+ 1|4|8|16, // 113 0x71 'q'
+ 1|4|8|16, // 114 0x72 'r'
+ 1|4|8|16, // 115 0x73 's'
+ 1|4|8|16, // 116 0x74 't'
+ 1|4|8|16, // 117 0x75 'u'
+ 1|4|8|16, // 118 0x76 'v'
+ 1|4|8|16, // 119 0x77 'w'
+ 1|4|8|16, // 120 0x78 'x'
+ 1|4|8|16, // 121 0x79 'y'
+ 1|4|8|16, // 122 0x7a 'z'
+ 1|8|16, // 123 0x7b '{'
+ 1|8|16, // 124 0x7c '|'
+ 1|8|16, // 125 0x7d '}'
+ 1|8|16, // 126 0x7e '~'
+ 1|8|16, // 127 0x7f
+ 1|8|16, // 128 0x80
+ 1|8|16, // 129 0x81
+ 1|8|16, // 130 0x82
+ 1|8|16, // 131 0x83
+ 1|8|16, // 132 0x84
+ 1|8|16, // 133 0x85
+ 1|8|16, // 134 0x86
+ 1|8|16, // 135 0x87
+ 1|8|16, // 136 0x88
+ 1|8|16, // 137 0x89
+ 1|8|16, // 138 0x8a
+ 1|8|16, // 139 0x8b
+ 1|8|16, // 140 0x8c
+ 1|8|16, // 141 0x8d
+ 1|8|16, // 142 0x8e
+ 1|8|16, // 143 0x8f
+ 1|8|16, // 144 0x90
+ 1|8|16, // 145 0x91
+ 1|8|16, // 146 0x92
+ 1|8|16, // 147 0x93
+ 1|8|16, // 148 0x94
+ 1|8|16, // 149 0x95
+ 1|8|16, // 150 0x96
+ 1|8|16, // 151 0x97
+ 1|8|16, // 152 0x98
+ 1|8|16, // 153 0x99
+ 1|8|16, // 154 0x9a
+ 1|8|16, // 155 0x9b
+ 1|8|16, // 156 0x9c
+ 1|8|16, // 157 0x9d
+ 1|8|16, // 158 0x9e
+ 1|8|16, // 159 0x9f
+ 1|8|16, // 160 0xa0
+ 1|8|16, // 161 0xa1
+ 1|8|16, // 162 0xa2
+ 1|8|16, // 163 0xa3
+ 1|8|16, // 164 0xa4
+ 1|8|16, // 165 0xa5
+ 1|8|16, // 166 0xa6
+ 1|8|16, // 167 0xa7
+ 1|8|16, // 168 0xa8
+ 1|8|16, // 169 0xa9
+ 1|8|16, // 170 0xaa
+ 1|8|16, // 171 0xab
+ 1|8|16, // 172 0xac
+ 1|8|16, // 173 0xad
+ 1|8|16, // 174 0xae
+ 1|8|16, // 175 0xaf
+ 1|8|16, // 176 0xb0
+ 1|8|16, // 177 0xb1
+ 1|8|16, // 178 0xb2
+ 1|8|16, // 179 0xb3
+ 1|8|16, // 180 0xb4
+ 1|8|16, // 181 0xb5
+ 1|8|16, // 182 0xb6
+ 1|8|16, // 183 0xb7
+ 1|8|16, // 184 0xb8
+ 1|8|16, // 185 0xb9
+ 1|8|16, // 186 0xba
+ 1|8|16, // 187 0xbb
+ 1|8|16, // 188 0xbc
+ 1|8|16, // 189 0xbd
+ 1|8|16, // 190 0xbe
+ 1|8|16, // 191 0xbf
+ 1|4|8|16, // 192 0xc0
+ 1|4|8|16, // 193 0xc1
+ 1|4|8|16, // 194 0xc2
+ 1|4|8|16, // 195 0xc3
+ 1|4|8|16, // 196 0xc4
+ 1|4|8|16, // 197 0xc5
+ 1|4|8|16, // 198 0xc6
+ 1|4|8|16, // 199 0xc7
+ 1|4|8|16, // 200 0xc8
+ 1|4|8|16, // 201 0xc9
+ 1|4|8|16, // 202 0xca
+ 1|4|8|16, // 203 0xcb
+ 1|4|8|16, // 204 0xcc
+ 1|4|8|16, // 205 0xcd
+ 1|4|8|16, // 206 0xce
+ 1|4|8|16, // 207 0xcf
+ 1|4|8|16, // 208 0xd0
+ 1|4|8|16, // 209 0xd1
+ 1|4|8|16, // 210 0xd2
+ 1|4|8|16, // 211 0xd3
+ 1|4|8|16, // 212 0xd4
+ 1|4|8|16, // 213 0xd5
+ 1|4|8|16, // 214 0xd6
+ 1|8|16, // 215 0xd7
+ 1|4|8|16, // 216 0xd8
+ 1|4|8|16, // 217 0xd9
+ 1|4|8|16, // 218 0xda
+ 1|4|8|16, // 219 0xdb
+ 1|4|8|16, // 220 0xdc
+ 1|4|8|16, // 221 0xdd
+ 1|4|8|16, // 222 0xde
+ 1|4|8|16, // 223 0xdf
+ 1|4|8|16, // 224 0xe0
+ 1|4|8|16, // 225 0xe1
+ 1|4|8|16, // 226 0xe2
+ 1|4|8|16, // 227 0xe3
+ 1|4|8|16, // 228 0xe4
+ 1|4|8|16, // 229 0xe5
+ 1|4|8|16, // 230 0xe6
+ 1|4|8|16, // 231 0xe7
+ 1|4|8|16, // 232 0xe8
+ 1|4|8|16, // 233 0xe9
+ 1|4|8|16, // 234 0xea
+ 1|4|8|16, // 235 0xeb
+ 1|4|8|16, // 236 0xec
+ 1|4|8|16, // 237 0xed
+ 1|4|8|16, // 238 0xee
+ 1|4|8|16, // 239 0xef
+ 1|4|8|16, // 240 0xf0
+ 1|4|8|16, // 241 0xf1
+ 1|4|8|16, // 242 0xf2
+ 1|4|8|16, // 243 0xf3
+ 1|4|8|16, // 244 0xf4
+ 1|4|8|16, // 245 0xf5
+ 1|4|8|16, // 246 0xf6
+ 1|8|16, // 247 0xf7
+ 1|4|8|16, // 248 0xf8
+ 1|4|8|16, // 249 0xf9
+ 1|4|8|16, // 250 0xfa
+ 1|4|8|16, // 251 0xfb
+ 1|4|8|16, // 252 0xfc
+ 1|4|8|16, // 253 0xfd
+ 1|4|8|16, // 254 0xfe
+ 1|4|8|16 // 255 0xff
+};
+#endif // defined(NPT_XML_USE_CHAR_MAP)
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#if defined (NPT_XML_USE_CHAR_MAP)
+#define NPT_XML_CHAR_IS_ANY_CHAR(c) (NPT_XmlCharMap[c] & 1)
+#define NPT_XML_CHAR_IS_WHITESPACE(c) (NPT_XmlCharMap[c] & 2)
+#define NPT_XML_CHAR_IS_NAME_CHAR(c) (NPT_XmlCharMap[c] & 4)
+#define NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c) (NPT_XML_CHAR_IS_NAME_CHAR((c)) || ((c) == '#'))
+#define NPT_XML_CHAR_IS_CONTENT_CHAR(c) (NPT_XmlCharMap[c] & 8)
+#define NPT_XML_CHAR_IS_VALUE_CHAR(c) (NPT_XmlCharMap[c] & 16)
+#else
+#define NPT_XML_CHAR_IS_WHITESPACE(c) \
+((c) == ' ' || (c) == '\t' || (c) == 0x0D || (c) == 0x0A)
+
+#define NPT_XML_CHAR_IS_ANY_CHAR(c) \
+(NPT_XML_CHAR_IS_WHITESPACE((c)) || ((c) >= 0x20))
+
+#define NPT_XML_CHAR_IS_DIGIT(c) \
+((c) >= '0' && (c) <= '9')
+
+#define NPT_XML_CHAR_IS_LETTER(c) \
+(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') || ((c) >= 0xC0 && (c) <= 0xD6) || ((c) >= 0xD8 && (c) <= 0xF6) || ((c) >= 0xF8))
+
+#define NPT_XML_CHAR_IS_NAME_CHAR(c) \
+(NPT_XML_CHAR_IS_DIGIT((c)) || NPT_XML_CHAR_IS_LETTER((c)) || (c) == '.' || (c) == '-' || (c) == '_' || (c) == ':')
+
+#define NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c) \
+(NPT_XML_CHAR_IS_NAME_CHAR((c)) || ((c) == '#'))
+
+#define NPT_XML_CHAR_IS_CONTENT_CHAR(c) \
+(NPT_XML_CHAR_IS_ANY_CHAR((c)) && ((c) != '&') && ((c) != '<'))
+
+#define NPT_XML_CHAR_IS_VALUE_CHAR(c) \
+(NPT_XML_CHAR_IS_ANY_CHAR((c)) && ((c) != '&') && ((c) != '<'))
+
+#endif // defined(NPT_XML_USE_CHAR_MAP)
+
+/*----------------------------------------------------------------------
+| NPT_XmlStringIsWhitespace
++---------------------------------------------------------------------*/
+static bool
+NPT_XmlStringIsWhitespace(const char* s, NPT_Size size)
+{
+ for (NPT_Size x=0; x<size; x++) {
+ if (!NPT_XML_CHAR_IS_WHITESPACE((int)s[x])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlProcessor class
++---------------------------------------------------------------------*/
+class NPT_XmlProcessor {
+public:
+ // constructor and destructor
+ NPT_XmlProcessor(NPT_XmlParser* parser);
+
+ // methods
+ NPT_Result ProcessBuffer(const char* buffer, NPT_Size size);
+ void Reset();
+
+private:
+ // types
+ typedef enum {
+ CONTEXT_NONE,
+ CONTEXT_OPEN_TAG,
+ CONTEXT_CLOSE_TAG,
+ CONTEXT_ATTRIBUTE,
+ CONTEXT_VALUE_SINGLE_QUOTE,
+ CONTEXT_VALUE_DOUBLE_QUOTE
+ } Context;
+
+ typedef enum {
+ STATE_IN_INIT,
+ STATE_IN_BOM_EF,
+ STATE_IN_BOM_BB,
+ STATE_IN_WHITESPACE,
+ STATE_IN_NAME,
+ STATE_IN_NAME_SPECIAL,
+ STATE_IN_VALUE_START,
+ STATE_IN_VALUE,
+ STATE_IN_TAG_START,
+ STATE_IN_EMPTY_TAG_END,
+ STATE_IN_CONTENT,
+ STATE_IN_PROCESSING_INSTRUCTION_START,
+ STATE_IN_PROCESSING_INSTRUCTION,
+ STATE_IN_PROCESSING_INSTRUCTION_END,
+ STATE_IN_COMMENT,
+ STATE_IN_COMMENT_END_1,
+ STATE_IN_COMMENT_END_2,
+ STATE_IN_DTD,
+ STATE_IN_DTD_MARKUP_DECL,
+ STATE_IN_DTD_MARKUP_DECL_END,
+ STATE_IN_CDATA,
+ STATE_IN_CDATA_END_1,
+ STATE_IN_CDATA_END_2,
+ STATE_IN_SPECIAL,
+ STATE_IN_ENTITY_REF
+ } State;
+
+ // members
+ NPT_XmlParser* m_Parser;
+ State m_State;
+ Context m_Context;
+ bool m_SkipNewline;
+ NPT_XmlAccumulator m_Name;
+ NPT_XmlAccumulator m_Value;
+ NPT_XmlAccumulator m_Text;
+ NPT_XmlAccumulator m_Entity;
+
+ // methods
+#ifdef NPT_XML_PARSER_DEBUG
+ const char* StateName(State state) {
+ switch (state) {
+ case STATE_IN_INIT: return "IN_INIT";
+ case STATE_IN_BOM_EF: return "IN_BOM_EF";
+ case STATE_IN_BOM_BB: return "IN_BOM_BB";
+ case STATE_IN_WHITESPACE: return "IN_WHITESPACE";
+ case STATE_IN_NAME: return "IN_NAME";
+ case STATE_IN_NAME_SPECIAL: return "IN_NAME_SPECIAL";
+ case STATE_IN_VALUE_START: return "IN_VALUE_START";
+ case STATE_IN_VALUE: return "IN_VALUE";
+ case STATE_IN_TAG_START: return "IN_TAG_START";
+ case STATE_IN_EMPTY_TAG_END: return "IN_EMPTY_TAG_END";
+ case STATE_IN_CONTENT: return "IN_CONTENT";
+ case STATE_IN_PROCESSING_INSTRUCTION_START: return "IN_PROCESSING_INSTRUCTION_START";
+ case STATE_IN_PROCESSING_INSTRUCTION: return "IN_PROCESSING_INSTRUCTION";
+ case STATE_IN_PROCESSING_INSTRUCTION_END: return "IN_PROCESSING_INSTRUCTION_END";
+ case STATE_IN_COMMENT: return "IN_COMMENT";
+ case STATE_IN_COMMENT_END_1: return "IN_COMMENT_END_1";
+ case STATE_IN_COMMENT_END_2: return "IN_COMMENT_END_2";
+ case STATE_IN_DTD: return "IN_DTD";
+ case STATE_IN_DTD_MARKUP_DECL: return "IN_DTD_MARKUP_DECL";
+ case STATE_IN_DTD_MARKUP_DECL_END: return "IN_DTD_MARKUP_DECL_END";
+ case STATE_IN_CDATA: return "IN_CDATA";
+ case STATE_IN_CDATA_END_1: return "IN_CDATA_END_1";
+ case STATE_IN_CDATA_END_2: return "IN_CDATA_END_2";
+ case STATE_IN_SPECIAL: return "IN_SPECIAL";
+ case STATE_IN_ENTITY_REF: return "IN_ENTITY_REF";
+ }
+ return "UNKNOWN";
+ }
+
+ const char* ContextName(Context context) {
+ switch (context) {
+ case CONTEXT_NONE: return "NONE";
+ case CONTEXT_OPEN_TAG: return "OPEN_TAG";
+ case CONTEXT_CLOSE_TAG: return "CLOSE_TAG";
+ case CONTEXT_ATTRIBUTE: return "ATTRIBUTE";
+ case CONTEXT_VALUE_SINGLE_QUOTE: return "VALUE_SINGLE_QUOTE";
+ case CONTEXT_VALUE_DOUBLE_QUOTE: return "VALUE_DOUBLE_QUOTE";
+ }
+ return "UNKNOWN";
+ }
+#endif /* NPT_XML_PARSER_DEBUG */
+
+ inline void SetState(State state) {
+ NPT_XML_Debug_3("\nstate transition: %s to %s [ctx=%s]\n",
+ StateName(m_State),
+ StateName(state),
+ ContextName(m_Context));
+ m_State = state;
+ }
+
+ inline void SetState(State state, Context context) {
+ NPT_XML_Debug_4("\nstate transition: %s [ctx=%s] to %s [ctx=%s]\n",
+ StateName(m_State),
+ ContextName(m_Context),
+ StateName(state),
+ ContextName(context));
+ m_State = state;
+ m_Context = context;
+ }
+
+ NPT_Result ResolveEntity(NPT_XmlAccumulator& source,
+ NPT_XmlAccumulator& destination);
+ NPT_Result FlushPendingText();
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlProcessor::NPT_XmlProcessor
++---------------------------------------------------------------------*/
+NPT_XmlProcessor::NPT_XmlProcessor(NPT_XmlParser* parser) :
+ m_Parser(parser),
+ m_State(STATE_IN_INIT),
+ m_Context(CONTEXT_NONE),
+ m_SkipNewline(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlProcessor::Reset
++---------------------------------------------------------------------*/
+void
+NPT_XmlProcessor::Reset()
+{
+ m_State = STATE_IN_INIT;
+ m_Context = CONTEXT_NONE;
+ m_SkipNewline = false;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlProcessor::ResolveEntity
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlProcessor::ResolveEntity(NPT_XmlAccumulator& source,
+ NPT_XmlAccumulator& destination)
+{
+ const char* entity = (const char*)source.GetString();
+
+ if (NPT_StringsEqual(entity, "lt")) {
+ destination.Append('<');
+ } else if (NPT_StringsEqual(entity, "gt")) {
+ destination.Append('>');
+ } else if (NPT_StringsEqual(entity, "amp")) {
+ destination.Append('&');
+ } else if (NPT_StringsEqual(entity, "quot")) {
+ destination.Append('"');
+ } else if (NPT_StringsEqual(entity, "apos")) {
+ destination.Append('\'');
+ } else if (entity[0] == '#') {
+ int i=1;
+ int base = 10;
+ if (entity[1] == 'x') {
+ i++;
+ base = 16;
+ }
+ int parsed = 0;
+ while (char c = entity[i++]) {
+ int digit = -1;
+ if (c>='0' && c<='9') {
+ digit = c-'0';
+ } else if (base == 16) {
+ if (c >= 'a' && c <= 'f') {
+ digit = 10+c-'a';
+ } else if (c >= 'A' && c <= 'F') {
+ digit = 10+c-'A';
+ }
+ }
+ if (digit == -1) {
+ // invalid char, leave the entity unparsed
+ destination.Append(source.GetString());
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ parsed = base*parsed+digit;
+ }
+ destination.AppendUTF8(parsed);
+ } else {
+ // unknown entity, leave as-is
+ destination.Append(source.GetString());
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlProcessor::FlushPendingText
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlProcessor::FlushPendingText()
+{
+ if (m_Text.GetSize() > 0) {
+ NPT_CHECK(m_Parser->OnCharacterData(m_Text.GetString(),
+ m_Text.GetSize()));
+ m_Text.Reset();
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlProcessor::ProcessBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlProcessor::ProcessBuffer(const char* buffer, NPT_Size size)
+{
+ unsigned char c;
+
+ while (size-- && (c = *buffer++)) {
+ NPT_XML_Debug_1("[%c]", (c == '\n' || c == '\r') ? '#' : c);
+
+ // normalize line ends
+ if (m_SkipNewline) {
+ m_SkipNewline = false;
+ if (c == '\n') continue;
+ }
+ if (c == '\r') {
+ m_SkipNewline = true;
+ c = '\n';
+ }
+
+ // process the character
+ switch (m_State) {
+ case STATE_IN_INIT:
+ if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ SetState(STATE_IN_WHITESPACE);
+ break;
+ } else if (c == '<') {
+ SetState(STATE_IN_TAG_START);
+ break;
+ } else if (c == 0xEF) {
+ SetState(STATE_IN_BOM_EF);
+ break;
+ }
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ case STATE_IN_BOM_EF:
+ if (c == 0xBB) {
+ SetState(STATE_IN_BOM_BB);
+ break;
+ }
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ case STATE_IN_BOM_BB:
+ if (c == 0xBF) {
+ SetState(STATE_IN_WHITESPACE);
+ break;
+ }
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ case STATE_IN_WHITESPACE:
+ if (NPT_XML_CHAR_IS_WHITESPACE(c)) break;
+ switch (m_Context) {
+ case CONTEXT_NONE:
+ if (c == '<') {
+ SetState(STATE_IN_TAG_START);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case CONTEXT_ATTRIBUTE:
+ if (c == '/') {
+ SetState(STATE_IN_EMPTY_TAG_END, CONTEXT_NONE);
+ } else if (c == '>') {
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else if (NPT_XML_CHAR_IS_NAME_CHAR(c)) {
+ m_Name.Reset();
+ m_Name.Append(c);
+ SetState(STATE_IN_NAME);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case CONTEXT_CLOSE_TAG:
+ if (c == '>') {
+ NPT_CHECK(FlushPendingText());
+ NPT_CHECK(m_Parser->OnEndElement(m_Name.GetString()));
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ default:
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_NAME:
+ if (NPT_XML_CHAR_IS_NAME_CHAR(c)) {
+ m_Name.Append(c);
+ break;
+ }
+ switch (m_Context) {
+ case CONTEXT_ATTRIBUTE:
+ if (c == '=') {
+ m_Value.Reset();
+ SetState(STATE_IN_VALUE_START);
+ } else if (!NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case CONTEXT_OPEN_TAG:
+ if (c == '>' || c == '/' || NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ NPT_CHECK(FlushPendingText());
+ NPT_CHECK(m_Parser->OnStartElement(m_Name.GetString()));
+ m_Name.Reset();
+ if (c == '>') {
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else if (c == '/') {
+ SetState(STATE_IN_EMPTY_TAG_END);
+ } else {
+ SetState(STATE_IN_WHITESPACE, CONTEXT_ATTRIBUTE);
+ }
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case CONTEXT_CLOSE_TAG:
+ if (c == '>') {
+ NPT_CHECK(FlushPendingText());
+ NPT_CHECK(m_Parser->OnEndElement(m_Name.GetString()));
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ SetState(STATE_IN_WHITESPACE);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ default:
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_NAME_SPECIAL:
+ if (NPT_XML_CHAR_IS_NAME_CHAR(c) || (c == '[')) {
+ m_Name.Append(c);
+
+ const unsigned char* nb = m_Name.GetBuffer();
+ if (m_Name.GetSize() == 2) {
+ if (nb[0] == '-' &&
+ nb[1] == '-') {
+ m_Name.Reset();
+ SetState(STATE_IN_COMMENT, CONTEXT_NONE);
+ break;
+ }
+ } else if (m_Name.GetSize() == 7) {
+ if (nb[0] == '[' &&
+ nb[1] == 'C' &&
+ nb[2] == 'D' &&
+ nb[3] == 'A' &&
+ nb[4] == 'T' &&
+ nb[5] == 'A' &&
+ nb[6] == '[') {
+ m_Name.Reset();
+ SetState(STATE_IN_CDATA, CONTEXT_NONE);
+ break;
+ }
+ }
+ break;
+ }
+ if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ const char* special = m_Name.GetString();
+ if (special && NPT_StringsEqual(special, "DOCTYPE")) {
+ SetState(STATE_IN_DTD, CONTEXT_NONE);
+ } else {
+ SetState(STATE_IN_SPECIAL, CONTEXT_NONE);
+ }
+ m_Name.Reset();
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_VALUE_START:
+ if (NPT_XML_CHAR_IS_WHITESPACE(c)) break;
+ if (c == '"') {
+ m_Value.Reset();
+ SetState(STATE_IN_VALUE, CONTEXT_VALUE_DOUBLE_QUOTE);
+ } else if (c == '\'') {
+ m_Value.Reset();
+ SetState(STATE_IN_VALUE, CONTEXT_VALUE_SINGLE_QUOTE);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_VALUE:
+ if ((c == '"' && m_Context == CONTEXT_VALUE_DOUBLE_QUOTE) ||
+ (c == '\'' && m_Context == CONTEXT_VALUE_SINGLE_QUOTE)) {
+ NPT_CHECK(m_Parser->OnElementAttribute(m_Name.GetString(),
+ m_Value.GetString()));
+ SetState(STATE_IN_WHITESPACE, CONTEXT_ATTRIBUTE);
+ } else if (c == '&') {
+ m_Entity.Reset();
+ SetState(STATE_IN_ENTITY_REF);
+ } else if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ m_Value.Append(' ');
+ } else if (NPT_XML_CHAR_IS_VALUE_CHAR(c)) {
+ m_Value.Append(c);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_TAG_START:
+ m_Name.Reset();
+ if (c == '!') {
+ SetState(STATE_IN_NAME_SPECIAL, CONTEXT_NONE);
+ } else if (c == '?') {
+ SetState(STATE_IN_PROCESSING_INSTRUCTION, CONTEXT_NONE);
+ } else if (c == '/') {
+ SetState(STATE_IN_NAME, CONTEXT_CLOSE_TAG);
+ } else if (NPT_XML_CHAR_IS_NAME_CHAR(c)) {
+ m_Name.Append(c);
+ SetState(STATE_IN_NAME, CONTEXT_OPEN_TAG);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_EMPTY_TAG_END:
+ if (c == '>') {
+ NPT_CHECK(FlushPendingText());
+ NPT_CHECK(m_Parser->OnEndElement(NULL));
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_ENTITY_REF:
+ switch (m_Context) {
+ case CONTEXT_VALUE_SINGLE_QUOTE:
+ case CONTEXT_VALUE_DOUBLE_QUOTE:
+ if (c == ';') {
+ NPT_CHECK(ResolveEntity(m_Entity, m_Value));
+ SetState(STATE_IN_VALUE);
+ } else if (NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c)) {
+ m_Entity.Append(c);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case CONTEXT_NONE:
+ if (c == ';') {
+ NPT_CHECK(ResolveEntity(m_Entity, m_Text));
+ SetState(STATE_IN_CONTENT);
+ } else if (NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c)) {
+ m_Entity.Append(c);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ default:
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_COMMENT:
+ if (c == '-') {
+ SetState(STATE_IN_COMMENT_END_1);
+ } else if (!NPT_XML_CHAR_IS_ANY_CHAR(c)) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_COMMENT_END_1:
+ if (c == '-') {
+ SetState(STATE_IN_COMMENT_END_2);
+ } else if (NPT_XML_CHAR_IS_ANY_CHAR(c)) {
+ SetState(STATE_IN_COMMENT);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_COMMENT_END_2:
+ if (c == '>') {
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_CONTENT:
+ if (c == '<') {
+ SetState(STATE_IN_TAG_START, CONTEXT_NONE);
+ } else if (c == '&') {
+ m_Entity.Reset();
+ SetState(STATE_IN_ENTITY_REF);
+ } else {
+ m_Text.Append(c);
+ }
+ break;
+
+ case STATE_IN_PROCESSING_INSTRUCTION_START:
+ break;
+
+ case STATE_IN_PROCESSING_INSTRUCTION_END:
+ if (c == '>') {
+ SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+ } else {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_PROCESSING_INSTRUCTION:
+ if (c == '?') {
+ SetState(STATE_IN_PROCESSING_INSTRUCTION_END);
+ }
+ break;
+
+ case STATE_IN_DTD:
+ if (NPT_XML_CHAR_IS_WHITESPACE(c)) break;
+ if (c == '[') {
+ SetState(STATE_IN_DTD_MARKUP_DECL);
+ } else if (c == '>') {
+ SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+ }
+ break;
+
+ case STATE_IN_DTD_MARKUP_DECL:
+ if (c == ']') {
+ SetState(STATE_IN_DTD_MARKUP_DECL_END);
+ }
+ break;
+
+ case STATE_IN_DTD_MARKUP_DECL_END:
+ if (c == '>') {
+ SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+ } else if (!NPT_XML_CHAR_IS_WHITESPACE(c)) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+ break;
+
+ case STATE_IN_CDATA:
+ if (c == ']') {
+ SetState(STATE_IN_CDATA_END_1);
+ } else {
+ m_Text.Append(c);
+ }
+ break;
+
+ case STATE_IN_CDATA_END_1:
+ if (c == ']') {
+ SetState(STATE_IN_CDATA_END_2);
+ } else {
+ m_Text.Append(']');
+ m_Text.Append(c);
+ SetState(STATE_IN_CDATA);
+ }
+ break;
+
+ case STATE_IN_CDATA_END_2:
+ if (c == '>') {
+ SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+ } else {
+ m_Text.Append("]]");
+ m_Text.Append(c);
+ SetState(STATE_IN_CDATA);
+ }
+ break;
+
+ case STATE_IN_SPECIAL:
+ if (c == '>') {
+ SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+ }
+ break;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::NPT_XmlParser
++---------------------------------------------------------------------*/
+NPT_XmlParser::NPT_XmlParser(bool keep_whitespace /* = false */) :
+ m_Root(NULL),
+ m_CurrentElement(NULL),
+ m_KeepWhitespace(keep_whitespace)
+{
+ m_Processor = new NPT_XmlProcessor(this);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::~NPT_XmlParser
++---------------------------------------------------------------------*/
+NPT_XmlParser::~NPT_XmlParser()
+{
+ Reset();
+ delete m_CurrentElement;
+ delete m_Processor;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::Reset
++---------------------------------------------------------------------*/
+void
+NPT_XmlParser::Reset()
+{
+ // delete anything that has been created
+ NPT_XmlNode* walker = m_CurrentElement;
+ while (walker && walker->GetParent()) {
+ walker = walker->GetParent();
+ }
+ delete walker;
+ m_CurrentElement = NULL;
+
+ m_Processor->Reset();
+
+ m_Root = NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(NPT_InputStream& stream,
+ NPT_Size& size,
+ NPT_XmlNode*& node,
+ bool incremental /* = false */)
+{
+ NPT_Result result;
+
+ // start with a known state
+ m_Root = NULL;
+ node = NULL;
+ if (!incremental) {
+ Reset();
+ }
+
+ // use a buffer on the stack
+ char buffer[1024];
+
+ // read a buffer and parse it until the end of the stream
+ NPT_Size max_bytes_to_read = size;
+ size = 0;
+ do {
+ NPT_Size bytes_read;
+ NPT_Size bytes_to_read = sizeof(buffer);
+ if (max_bytes_to_read != 0 &&
+ size+bytes_to_read > max_bytes_to_read) {
+ bytes_to_read = max_bytes_to_read-size;
+ }
+ result = stream.Read(buffer, bytes_to_read, &bytes_read);
+ if (NPT_SUCCEEDED(result)) {
+ // update the counter
+ size += bytes_read;
+
+ // parse the buffer
+ result = m_Processor->ProcessBuffer(buffer, bytes_read);
+ if (NPT_FAILED(result)) break;
+ } else {
+ break;
+ }
+ } while(NPT_SUCCEEDED(result) &&
+ (max_bytes_to_read == 0 || size < max_bytes_to_read));
+
+ // return a tree if we have one
+ node = m_Root;
+ if (incremental) {
+ return result;
+ } else {
+ if (NPT_FAILED(result) && result != NPT_ERROR_EOS) {
+ delete m_Root;
+ m_Root = NULL;
+ node = NULL;
+ return result;
+ } else {
+ return m_Root?NPT_SUCCESS:NPT_ERROR_XML_NO_ROOT;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(NPT_InputStream& stream,
+ NPT_XmlNode*& node,
+ bool incremental /* = false */)
+{
+ NPT_Size max_read = 0; // no limit
+ return Parse(stream, max_read, node, incremental);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(const char* xml,
+ NPT_XmlNode*& node,
+ bool incremental /* = false */)
+{
+ NPT_Size size = NPT_StringLength(xml);
+
+ return Parse(xml, size, node, incremental);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(const char* xml,
+ NPT_Size size,
+ NPT_XmlNode*& node,
+ bool incremental /* = false */)
+{
+ // start with a known state
+ m_Root = NULL;
+ node = NULL;
+ if (!incremental) {
+ Reset();
+ }
+
+ // parse the buffer
+ NPT_Result result = m_Processor->ProcessBuffer(xml, size);
+
+ // return a tree if we have one
+ node = m_Root;
+ if (incremental) {
+ return result;
+ } else {
+ if (NPT_FAILED(result)) {
+ delete m_Root;
+ m_Root = NULL;
+ node = NULL;
+ return result;
+ } else {
+ return m_Root?NPT_SUCCESS:NPT_ERROR_XML_NO_ROOT;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::OnStartElement
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::OnStartElement(const char* name)
+{
+ NPT_XML_Debug_1("\nNPT_XmlParser::OnStartElement: %s\n", name);
+
+ // we cannot start an element if we already have a root
+ if (m_Root) {
+ return NPT_ERROR_XML_MULTIPLE_ROOTS;
+ }
+
+ // create new node
+ NPT_XmlElementNode* node = new NPT_XmlElementNode(name);
+
+ // add node to tree
+ if (m_CurrentElement) {
+ // add the new node
+ m_CurrentElement->AddChild(node);
+ }
+ m_CurrentElement = node;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::OnElementAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::OnElementAttribute(const char* name, const char* value)
+{
+ NPT_XML_Debug_2("\nNPT_XmlParser::OnElementAttribute: name=%s, value='%s'\n",
+ name, value);
+
+ if (m_CurrentElement == NULL) {
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // check if this is a namespace attribute
+ if (name[0] == 'x' &&
+ name[1] == 'm' &&
+ name[2] == 'l' &&
+ name[3] == 'n' &&
+ name[4] == 's' &&
+ (name[5] == '\0' || name[5] == ':')) {
+ // namespace definition
+ m_CurrentElement->SetNamespaceUri((name[5] == ':')?name+6:"", value);
+ } else {
+ m_CurrentElement->AddAttribute(name, value);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::OnEndElement
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::OnEndElement(const char* name)
+{
+ NPT_XML_Debug_1("\nNPT_XmlParser::OnEndElement: %s\n", name ? name : "NULL");
+
+ if (m_CurrentElement == NULL) return NPT_ERROR_XML_TAG_MISMATCH;
+
+ // check that the name matches (if there is a name)
+ if (name) {
+ const char* prefix = name;
+ unsigned int prefix_length = 0;
+ const char* tag = name;
+ const char* cursor = name;
+ while (char c = *cursor++) {
+ if (c == ':') {
+ prefix_length = (unsigned int)(cursor-name)-1;
+ tag = cursor;
+ }
+ }
+ // check that the name and prefix length match
+ if (m_CurrentElement->GetTag() != tag ||
+ m_CurrentElement->GetPrefix().GetLength() != prefix_length) {
+ return NPT_ERROR_XML_TAG_MISMATCH;
+ }
+
+ // check the prefix
+ const char* current_prefix = m_CurrentElement->GetPrefix().GetChars();
+ for (unsigned int i=0; i<prefix_length; i++) {
+ if (current_prefix[i] != prefix[i]) {
+ return NPT_ERROR_XML_TAG_MISMATCH;
+ }
+ }
+ }
+
+ // pop up the stack
+ NPT_XmlNode* parent = m_CurrentElement->GetParent();
+ if (parent) {
+ m_CurrentElement = parent->AsElementNode();
+ } else {
+ if (m_Root) {
+ // this should never happen
+ delete m_CurrentElement;
+ m_CurrentElement = NULL;
+ return NPT_ERROR_XML_MULTIPLE_ROOTS;
+ } else {
+ m_Root = m_CurrentElement;
+ m_CurrentElement = NULL;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser::OnCharacterData
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::OnCharacterData(const char* data, NPT_Size size)
+{
+ NPT_XML_Debug_1("\nNPT_XmlParser::OnCharacterData: %s\n", data);
+
+ // check that we have a current element
+ if (m_CurrentElement == NULL) {
+ // we do not allow non-whitespace outside an element content
+ if (!NPT_XmlStringIsWhitespace(data, size)) {
+ return NPT_ERROR_XML_INVALID_NESTING;
+ }
+
+ // ignore whitespace
+ return NPT_SUCCESS;
+ }
+
+ // ignore whitespace if applicable
+ if (m_KeepWhitespace || !NPT_XmlStringIsWhitespace(data, size)) {
+ // add the text to the current element
+ m_CurrentElement->AddText(data);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlAttributeWriter
++---------------------------------------------------------------------*/
+class NPT_XmlAttributeWriter
+{
+public:
+ NPT_XmlAttributeWriter(NPT_XmlSerializer& serializer) : m_Serializer(serializer) {}
+ void operator()(NPT_XmlAttribute*& attribute) const {
+ m_Serializer.Attribute(attribute->GetPrefix(),
+ attribute->GetName(),
+ attribute->GetValue());
+ }
+
+private:
+ // members
+ NPT_XmlSerializer& m_Serializer;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeWriter
++---------------------------------------------------------------------*/
+class NPT_XmlNodeWriter
+{
+public:
+ NPT_XmlNodeWriter(NPT_XmlSerializer& serializer) :
+ m_Serializer(serializer), m_AttributeWriter(serializer) {
+ m_Serializer.StartDocument();
+ }
+ void operator()(NPT_XmlNode*& node) const {
+ if (NPT_XmlElementNode* element = node->AsElementNode()) {
+ const NPT_String& prefix = element->GetPrefix();
+ const NPT_String& tag = element->GetTag();
+ m_Serializer.StartElement(prefix, tag);
+ element->GetAttributes().Apply(m_AttributeWriter);
+
+ // emit namespace attributes
+ if (element->m_NamespaceMap) {
+ NPT_List<NPT_XmlNamespaceMap::Entry*>::Iterator item =
+ element->m_NamespaceMap->m_Entries.GetFirstItem();
+ while (item) {
+ if ((*item)->m_Prefix.IsEmpty()) {
+ // default namespace
+ m_Serializer.Attribute(NULL, "xmlns", (*item)->m_Uri);
+ } else {
+ // namespace with prefix
+ m_Serializer.Attribute("xmlns", (*item)->m_Prefix, (*item)->m_Uri);
+ }
+ ++item;
+ }
+ }
+
+ element->GetChildren().Apply(*this);
+ m_Serializer.EndElement(prefix, tag);
+ } else if (NPT_XmlTextNode* text = node->AsTextNode()) {
+ m_Serializer.Text(text->GetString());
+ }
+ }
+
+private:
+ // members
+ NPT_XmlSerializer& m_Serializer;
+ NPT_XmlAttributeWriter m_AttributeWriter;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter
++---------------------------------------------------------------------*/
+class NPT_XmlNodeCanonicalWriter
+{
+public:
+ // types
+ struct MapChainLink {
+ MapChainLink(MapChainLink* parent) : m_Parent(parent) {}
+ MapChainLink* m_Parent;
+ NPT_Map<NPT_String, NPT_String> m_RenderedNamespaces;
+ };
+
+ // constructor
+ NPT_XmlNodeCanonicalWriter(NPT_XmlSerializer& serializer,
+ MapChainLink* map_chain = NULL) :
+ m_MapChain(map_chain),
+ m_Serializer(serializer) {
+ m_Serializer.StartDocument();
+ }
+ void operator()(NPT_XmlNode*& node) const;
+
+private:
+ // types
+ struct SortedAttributeList {
+ // types
+ struct Entry {
+ const NPT_String* m_NamespaceUri;
+ const NPT_XmlAttribute* m_Attribute;
+ };
+
+ // methods
+ void Add(const NPT_String* namespace_uri,
+ const NPT_XmlAttribute* attribute);
+ void Emit(NPT_XmlSerializer& serializer);
+
+ // members
+ NPT_List<Entry> m_Entries;
+ };
+
+ struct SortedNamespaceList {
+ // types
+ struct Entry {
+ const NPT_String* m_NamespacePrefix;
+ const NPT_String* m_NamespaceUri;
+ };
+
+ // methods
+ void Add(const NPT_String* prefix, const NPT_String* uri);
+ void Emit(NPT_XmlSerializer& serializer);
+
+ // members
+ NPT_List<Entry> m_Entries;
+ };
+
+ // methods
+ const NPT_String* GetNamespaceRenderedForPrefix(const NPT_String& prefix) const;
+
+ // members
+ MapChainLink* m_MapChain;
+ NPT_XmlSerializer& m_Serializer;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter::SortedAttributeList::Add
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedAttributeList::Add(
+ const NPT_String* namespace_uri,
+ const NPT_XmlAttribute* attribute)
+{
+ // transform empty strings into NULL pointers
+ if (namespace_uri && namespace_uri->IsEmpty()) namespace_uri = NULL;
+
+ // find the namespace insertion position
+ NPT_List<Entry>::Iterator entry = m_Entries.GetFirstItem();
+ for (; entry; ++entry) {
+ // decide if we insert now or move on
+ const NPT_String* other_namespace_uri = entry->m_NamespaceUri;
+ if (namespace_uri &&
+ (other_namespace_uri == NULL || *namespace_uri > *other_namespace_uri)) {
+ // this namespace uri is greater than the other, skip
+ continue;
+ } else if ((namespace_uri == NULL && other_namespace_uri == NULL) ||
+ (namespace_uri && other_namespace_uri &&
+ *namespace_uri == *other_namespace_uri)) {
+ // namespace uris match, compare the names
+ const NPT_XmlAttribute* other_attribute = entry->m_Attribute;
+ if (attribute->GetName() > other_attribute->GetName()) continue;
+ }
+ break;
+ }
+
+ Entry new_entry = {namespace_uri, attribute};
+ m_Entries.Insert(entry, new_entry);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter::SortedAttributeList::Emit
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedAttributeList::Emit(NPT_XmlSerializer& serializer)
+{
+ for (NPT_List<Entry>::Iterator i = m_Entries.GetFirstItem(); i; ++i) {
+ serializer.Attribute(i->m_Attribute->GetPrefix(),
+ i->m_Attribute->GetName(),
+ i->m_Attribute->GetValue());
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Add
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Add(const NPT_String* prefix,
+ const NPT_String* uri)
+{
+ // find the namespace insertion position
+ NPT_List<Entry>::Iterator entry = m_Entries.GetFirstItem();
+ if (prefix && !prefix->IsEmpty()) {
+ for (; entry; ++entry) {
+ // decide if we insert now or move on
+ if (entry->m_NamespacePrefix && *prefix <= *entry->m_NamespacePrefix) {
+ break;
+ }
+ }
+ } else {
+ prefix = NULL;
+ }
+
+ Entry new_entry = {prefix, uri};
+ m_Entries.Insert(entry, new_entry);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Emit
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Emit(NPT_XmlSerializer& serializer)
+{
+ for (NPT_List<Entry>::Iterator i = m_Entries.GetFirstItem(); i; ++i) {
+ const NPT_String* key = i->m_NamespacePrefix;
+ const NPT_String* value = i->m_NamespaceUri;
+ if (key == NULL) {
+ serializer.Attribute(NULL, "xmlns", *value);
+ } else if (*key != "xml" || *value != NPT_XmlNamespaceUri_Xml) {
+ serializer.Attribute("xmlns", *key, *value);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter::GetNamespaceRenderedForPrefix
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlNodeCanonicalWriter::GetNamespaceRenderedForPrefix(const NPT_String& prefix) const
+{
+ for (MapChainLink* link = m_MapChain;
+ link;
+ link = link->m_Parent) {
+ NPT_String* uri;
+ if (NPT_SUCCEEDED(link->m_RenderedNamespaces.Get(prefix, uri))) {
+ return uri;
+ }
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlNodeCanonicalWriter::operator()
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::operator()(NPT_XmlNode*& node) const
+{
+ MapChainLink map_link(m_MapChain);
+
+ if (NPT_XmlElementNode* element = node->AsElementNode()) {
+ const NPT_String& prefix = element->GetPrefix();
+ const NPT_String& tag = element->GetTag();
+
+ // process namespaces
+ const NPT_String* namespace_uri = element->GetNamespace();
+ const NPT_String* rendered = GetNamespaceRenderedForPrefix(prefix);
+ if (namespace_uri && namespace_uri->IsEmpty()) namespace_uri = NULL;
+ if (prefix.IsEmpty()) {
+ // default namespace
+ if (rendered == NULL) {
+ // default namespace not rendered
+ if (namespace_uri) {
+ map_link.m_RenderedNamespaces.Put("", *namespace_uri);
+ }
+ } else {
+ // default namespace already rendered
+ const char* compare;
+ if (namespace_uri) {
+ compare = namespace_uri->GetChars();
+ } else {
+ compare = "";
+ }
+ if (*rendered != compare) {
+ // the rendered default namespace had a different uri
+ map_link.m_RenderedNamespaces.Put("", compare);
+ }
+ }
+ } else {
+ // explicit namespace
+ // NOTE: namespace_uri should not be an empty string, but we test just
+ // in case the XML document is not compliant
+ if (namespace_uri && (rendered == NULL || *rendered != *namespace_uri)) {
+ // namespace prefix not rendered or rendered with a different value
+ map_link.m_RenderedNamespaces.Put(prefix, *namespace_uri);
+ }
+ }
+
+ // process attributes
+ SortedAttributeList prefixed_attributes;
+ SortedAttributeList naked_attributes;
+ for (NPT_List<NPT_XmlAttribute*>::Iterator attribute = element->GetAttributes().GetFirstItem();
+ attribute;
+ ++attribute) {
+ const NPT_String& a_prefix = (*attribute)->GetPrefix();
+ if (a_prefix.IsEmpty()) {
+ // naked attribute
+ naked_attributes.Add(NULL, *attribute);
+ } else {
+ // decide if we need to render this namespace declaration
+ namespace_uri = element->GetNamespaceUri(a_prefix);
+ if (namespace_uri) {
+ rendered = GetNamespaceRenderedForPrefix(a_prefix);;
+ if (rendered == NULL || *rendered != *namespace_uri) {
+ // namespace not rendered or rendered with a different value
+ map_link.m_RenderedNamespaces.Put(a_prefix, *namespace_uri);
+ }
+ prefixed_attributes.Add(namespace_uri, *attribute);
+ }
+ }
+ }
+
+ // start of element
+ m_Serializer.StartElement(prefix, tag);
+
+ // namespace declarations
+ if (map_link.m_RenderedNamespaces.GetEntryCount()) {
+ SortedNamespaceList namespaces;
+ NPT_List<NPT_Map<NPT_String, NPT_String>::Entry*>::Iterator entry =
+ map_link.m_RenderedNamespaces.GetEntries().GetFirstItem();
+ while (entry) {
+ const NPT_String& key = (*entry)->GetKey();
+ const NPT_String& value = (*entry)->GetValue();
+ namespaces.Add(&key, &value);
+ ++entry;
+ }
+ namespaces.Emit(m_Serializer);
+ }
+
+ // attributes
+ naked_attributes.Emit(m_Serializer);
+ prefixed_attributes.Emit(m_Serializer);
+
+ // children
+ MapChainLink* chain;
+ if (map_link.m_RenderedNamespaces.GetEntryCount()) {
+ chain = &map_link;
+ } else {
+ chain = m_MapChain;
+ }
+ element->GetChildren().Apply(NPT_XmlNodeCanonicalWriter(m_Serializer, chain));
+
+ // end of element
+ m_Serializer.EndElement(prefix, tag);
+ } else if (NPT_XmlTextNode* text = node->AsTextNode()) {
+ m_Serializer.Text(text->GetString());
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::NPT_XmlSerializer
++---------------------------------------------------------------------*/
+NPT_XmlSerializer::NPT_XmlSerializer(NPT_OutputStream* output,
+ NPT_Cardinal indentation,
+ bool shrink_empty_elements,
+ bool add_xml_decl) :
+ m_Output(output),
+ m_ElementPending(false),
+ m_Depth(0),
+ m_Indentation(indentation),
+ m_ElementHasText(false),
+ m_ShrinkEmptyElements(shrink_empty_elements),
+ m_AddXmlDecl(add_xml_decl)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::~NPT_XmlSerializer
++---------------------------------------------------------------------*/
+NPT_XmlSerializer::~NPT_XmlSerializer()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::StartDocument
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::StartDocument()
+{
+ if (!m_AddXmlDecl) return NPT_SUCCESS;
+
+ return m_Output->WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::EndDocument
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::EndDocument()
+{
+ return m_ElementPending?NPT_ERROR_INVALID_STATE:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::EscapeChar
++---------------------------------------------------------------------*/
+void
+NPT_XmlSerializer::EscapeChar(unsigned char c, char* text)
+{
+ *text++ = '&';
+ *text++ = '#';
+ *text++ = 'x';
+ int c0 = c>>4;
+ int c1 = c&0xF;
+ if (c0) {
+ *text++ = c0 >= 10 ? 'A'+(c0-10) : '0'+c0;
+ }
+ *text++ = c1 >= 10 ? 'A'+(c1-10) : '0'+c1;
+ *text++ = ';';
+ *text = '\0';
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::ProcessPending
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::ProcessPending()
+{
+ if (!m_ElementPending) return NPT_SUCCESS;
+ m_ElementPending = false;
+ return m_Output->Write(">", 1);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::OutputEscapedString
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::OutputEscapedString(const char* text, bool attribute)
+{
+ const char* start = text;
+ char escaped[7];
+ while (char c = *text) {
+ const char* insert = NULL;
+ switch (c) {
+ case '\r': {
+ EscapeChar(c, escaped);
+ insert = escaped;
+ break;
+ }
+ case '\n':
+ case '\t':
+ if (attribute) {
+ EscapeChar(c, escaped);
+ insert = escaped;
+ }
+ break;
+
+ case '&' : insert = "&amp;"; break;
+ case '<' : insert = "&lt;"; break;
+ case '>' : if (!attribute) insert = "&gt;"; break;
+ case '"' : if (attribute) insert = "&quot;"; break;
+ default :
+ break;
+ }
+ if (insert) {
+ // output pending chars
+ if (start != text) m_Output->WriteFully(start, (NPT_Size)(text-start));
+ m_Output->WriteString(insert);
+ start = ++text;
+ } else {
+ ++text;
+ }
+ }
+ if (start != text) {
+ m_Output->WriteFully(start, (NPT_Size)(text-start));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::OutputIndentation
++---------------------------------------------------------------------*/
+void
+NPT_XmlSerializer::OutputIndentation(bool start)
+{
+ if (m_Depth || !start) m_Output->Write("\r\n", 2);
+
+ // ensure we have enough chars in the prefix string
+ unsigned int prefix_length = m_Indentation*m_Depth;
+ if (m_IndentationPrefix.GetLength() < prefix_length) {
+ unsigned int needed = prefix_length-m_IndentationPrefix.GetLength();
+ for (unsigned int i=0; i<needed; i+=16) {
+ m_IndentationPrefix.Append(" ", 16);
+ }
+ }
+
+ // print the indentation prefix
+ m_Output->WriteFully(m_IndentationPrefix.GetChars(), prefix_length);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::StartElement
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::StartElement(const char* prefix, const char* name)
+{
+ ProcessPending();
+ if (m_Indentation) OutputIndentation(true);
+ m_ElementPending = true;
+ m_ElementHasText = false;
+ m_Depth++;
+ m_Output->Write("<", 1);
+ if (prefix && prefix[0]) {
+ m_Output->WriteString(prefix);
+ m_Output->Write(":", 1);
+ }
+ return m_Output->WriteString(name);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::EndElement
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::EndElement(const char* prefix, const char* name)
+{
+ m_Depth--;
+
+ if (m_ElementPending) {
+ // this element has no children
+ m_ElementPending = false;
+ if (m_ShrinkEmptyElements) {
+ return m_Output->WriteFully("/>", 2);
+ } else {
+ m_Output->Write(">",1);
+ }
+ }
+
+ if (m_Indentation && !m_ElementHasText) OutputIndentation(false);
+ m_ElementHasText = false;
+ m_Output->WriteFully("</", 2);
+ if (prefix && prefix[0]) {
+ m_Output->WriteString(prefix);
+ m_Output->Write(":", 1);
+ }
+ m_Output->WriteString(name);
+ return m_Output->Write(">", 1);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::Attribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::Attribute(const char* prefix, const char* name, const char* value)
+{
+ m_Output->Write(" ", 1);
+ if (prefix && prefix[0]) {
+ m_Output->WriteString(prefix);
+ m_Output->Write(":", 1);
+ }
+ m_Output->WriteString(name);
+ m_Output->WriteFully("=\"", 2);
+ OutputEscapedString(value, true);
+ return m_Output->Write("\"", 1);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::Text
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::Text(const char* text)
+{
+ ProcessPending();
+ m_ElementHasText = true;
+ return OutputEscapedString(text, false);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::CdataSection
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::CdataSection(const char* data)
+{
+ ProcessPending();
+ m_ElementHasText = true;
+ m_Output->WriteFully("<![CDATA[", 9);
+ m_Output->WriteString(data);
+ return m_Output->WriteFully("]]>", 3);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer::Comment
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlSerializer::Comment(const char* comment)
+{
+ ProcessPending();
+ m_Output->WriteFully("<!--", 4);
+ m_Output->WriteString(comment);
+ return m_Output->WriteFully("-->", 3);
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlWriter::Serialize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlWriter::Serialize(NPT_XmlNode& node,
+ NPT_OutputStream& output,
+ bool add_xml_decl)
+{
+ NPT_XmlSerializer serializer(&output, m_Indentation, true, add_xml_decl);
+ NPT_XmlNodeWriter node_writer(serializer);
+ NPT_XmlNode* node_pointer = &node;
+ node_writer(node_pointer);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XmlCanonicalizer::Serialize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlCanonicalizer::Serialize(NPT_XmlNode& node,
+ NPT_OutputStream& output,
+ bool add_xml_decl)
+{
+ // create a serializer with no indentation and no shrinking of empty elements
+ NPT_XmlSerializer serializer(&output, 0, false, add_xml_decl);
+
+ // serialize the node
+ NPT_XmlNodeCanonicalWriter node_writer(serializer);
+ NPT_XmlNode* node_pointer = &node;
+ node_writer(node_pointer);
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Neptune/Source/Core/NptXml.h b/lib/libUPnP/Neptune/Source/Core/NptXml.h
new file mode 100644
index 0000000..cd06a88
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptXml.h
@@ -0,0 +1,391 @@
+/*****************************************************************
+|
+| Neptune - Xml Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_XML_H_
+#define _NPT_XML_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptList.h"
+#include "NptStrings.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_XML_INVALID_NESTING = NPT_ERROR_BASE_XML - 0;
+const int NPT_ERROR_XML_TAG_MISMATCH = NPT_ERROR_BASE_XML - 1;
+const int NPT_ERROR_XML_NO_ROOT = NPT_ERROR_BASE_XML - 2;
+const int NPT_ERROR_XML_MULTIPLE_ROOTS = NPT_ERROR_BASE_XML - 3;
+
+#define NPT_XML_ANY_NAMESPACE "*"
+#define NPT_XML_NO_NAMESPACE NULL
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class NPT_XmlProcessor;
+
+/*----------------------------------------------------------------------
+| NPT_XmlAttribute
++---------------------------------------------------------------------*/
+class NPT_XmlAttribute
+{
+ public:
+ // methods
+ NPT_XmlAttribute(const char* name, const char* value);
+ NPT_XmlAttribute(const char* prefix, const char* name, const char* value) :
+ m_Prefix(prefix), m_Name(name), m_Value(value) {}
+ const NPT_String& GetPrefix() const { return m_Prefix; }
+ const NPT_String& GetName() const { return m_Name; }
+ const NPT_String& GetValue() const { return m_Value; }
+ void SetValue(const char* value) { m_Value = value; }
+
+ private:
+ // members
+ NPT_String m_Prefix;
+ NPT_String m_Name;
+ NPT_String m_Value;
+
+ NPT_XmlAttribute(const NPT_XmlAttribute& attribute) :
+ m_Prefix(attribute.m_Prefix),
+ m_Name(attribute.m_Name),
+ m_Value(attribute.m_Value) {}
+ NPT_XmlAttribute& operator=(const NPT_XmlAttribute& a);
+
+ // friends
+ friend class NPT_XmlAttributeFinder;
+ friend class NPT_XmlAttributeFinderWithPrefix;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNamespaceMap
++---------------------------------------------------------------------*/
+class NPT_XmlNamespaceMap
+{
+public:
+ // destructor
+ ~NPT_XmlNamespaceMap();
+
+ // methods
+ NPT_Result SetNamespaceUri(const char* prefix, const char* uri);
+ const NPT_String* GetNamespaceUri(const char* prefix);
+ const NPT_String* GetNamespacePrefix(const char* uri);
+
+private:
+ // types
+ class Entry {
+ public:
+ // constructor
+ Entry(const char* prefix, const char* uri) :
+ m_Prefix(prefix), m_Uri(uri) {}
+
+ // members
+ NPT_String m_Prefix;
+ NPT_String m_Uri;
+ };
+
+ // members
+ NPT_List<Entry*> m_Entries;
+
+ // friends
+ friend class NPT_XmlWriter;
+ friend class NPT_XmlNodeWriter;
+ friend class NPT_XmlNodeCanonicalWriter;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlNode
++---------------------------------------------------------------------*/
+class NPT_XmlElementNode;
+class NPT_XmlTextNode;
+class NPT_XmlNode
+{
+ public:
+ // types
+ typedef enum {
+ DOCUMENT,
+ ELEMENT,
+ TEXT
+ } Type;
+
+ // methods
+ NPT_XmlNode(Type type) : m_Type(type), m_Parent(NULL) {}
+ virtual ~NPT_XmlNode() {}
+ Type GetType() const { return m_Type; }
+ NPT_XmlNode* GetParent() const { return m_Parent; }
+
+ // type casting
+ virtual NPT_XmlElementNode* AsElementNode() { return NULL; }
+ virtual const NPT_XmlElementNode* AsElementNode() const { return NULL; }
+ virtual NPT_XmlTextNode* AsTextNode() { return NULL; }
+ virtual const NPT_XmlTextNode* AsTextNode() const { return NULL; }
+
+ protected:
+ // methods
+ virtual void SetParent(NPT_XmlNode* parent) { m_Parent = parent; }
+
+ // members
+ Type m_Type;
+ NPT_XmlNode* m_Parent;
+
+ // friends
+ friend class NPT_XmlNodeFinder;
+ friend class NPT_XmlSerializer;
+ friend class NPT_XmlWriter;
+ friend class NPT_XmlElementNode; // to allow access to SetParent()
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlElementNode
++---------------------------------------------------------------------*/
+class NPT_XmlElementNode : public NPT_XmlNode
+{
+ public:
+ // methods
+ NPT_XmlElementNode(const char* tag);
+ NPT_XmlElementNode(const char* prefix, const char* tag);
+ ~NPT_XmlElementNode() override;
+ NPT_List<NPT_XmlNode*>& GetChildren() { return m_Children; }
+ const NPT_List<NPT_XmlNode*>&
+ GetChildren() const { return m_Children; }
+ NPT_XmlElementNode* GetChild(const char* tag,
+ const char* namespc = NPT_XML_NO_NAMESPACE,
+ NPT_Ordinal n=0) const;
+ NPT_Result AddChild(NPT_XmlNode* child);
+ NPT_Result SetAttribute(const char* prefix,
+ const char* name,
+ const char* value);
+ NPT_Result SetAttribute(const char* name,
+ const char* value);
+ NPT_Result AddText(const char* text);
+ NPT_List<NPT_XmlAttribute*>&
+ GetAttributes() { return m_Attributes; }
+ const NPT_List<NPT_XmlAttribute*>&
+ GetAttributes() const { return m_Attributes; }
+ const NPT_String* GetAttribute(const char* name,
+ const char* namespc = NPT_XML_NO_NAMESPACE) const;
+ const NPT_String& GetPrefix() const { return m_Prefix; }
+ const NPT_String& GetTag() const { return m_Tag; }
+ const NPT_String* GetText(NPT_Ordinal n=0) const;
+
+ // bring all the namespace definitions used in this element of one of its descendants
+ // into the namespace map of this element so that it may be serialized as a
+ // standalone element without any prefixes with undefined namespace uris
+ NPT_Result MakeStandalone();
+
+ // namespace methods
+ const NPT_String* GetNamespace() const;
+ NPT_Result SetNamespaceUri(const char* prefix, const char* uri);
+ const NPT_String* GetNamespaceUri(const char* prefix) const;
+ const NPT_String* GetNamespacePrefix(const char* uri) const;
+
+ // type casting
+ NPT_XmlElementNode* AsElementNode() override { return this; }
+ const NPT_XmlElementNode* AsElementNode() const override { return this; }
+
+protected:
+ // methods
+ void SetParent(NPT_XmlNode* parent) override;
+ void SetNamespaceParent(NPT_XmlElementNode* parent);
+ void RelinkNamespaceMaps();
+
+ NPT_Result AddAttribute(const char* name, const char* value);
+
+ // members
+ NPT_String m_Prefix;
+ NPT_String m_Tag;
+ NPT_List<NPT_XmlNode*> m_Children;
+ NPT_List<NPT_XmlAttribute*> m_Attributes;
+ NPT_XmlNamespaceMap* m_NamespaceMap;
+ NPT_XmlElementNode* m_NamespaceParent;
+
+ // friends
+ friend class NPT_XmlTagFinder;
+ friend class NPT_XmlSerializer;
+ friend class NPT_XmlWriter;
+ friend class NPT_XmlNodeWriter;
+ friend class NPT_XmlNodeCanonicalWriter;
+ friend class NPT_XmlParser;
+ friend class NPT_XmlProcessor;
+ friend class NPT_XmlNamespaceCollapser;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlTextNode
++---------------------------------------------------------------------*/
+class NPT_XmlTextNode : public NPT_XmlNode
+{
+ public:
+ // types
+ typedef enum {
+ CHARACTER_DATA,
+ IGNORABLE_WHITESPACE,
+ CDATA_SECTION,
+ ENTITY_REFERENCE,
+ COMMENT
+ } TokenType;
+
+ // constructor
+ NPT_XmlTextNode(TokenType token_type, const char* text);
+
+ // methods
+ const NPT_String& GetString() const { return m_Text; }
+ TokenType GetTokenType() const { return m_TokenType; }
+
+ // type casting
+ NPT_XmlTextNode* AsTextNode() override { return this; }
+ const NPT_XmlTextNode* AsTextNode() const override { return this; }
+
+ private:
+ // members
+ TokenType m_TokenType;
+ NPT_String m_Text;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlParser
++---------------------------------------------------------------------*/
+class NPT_XmlParser
+{
+ public:
+ // methods
+ NPT_XmlParser(bool keep_whitespace = true);
+ virtual ~NPT_XmlParser();
+ virtual NPT_Result Parse(const char* xml,
+ NPT_XmlNode*& tree,
+ bool incremental=false);
+ virtual NPT_Result Parse(const char* xml,
+ NPT_Size size,
+ NPT_XmlNode*& tree,
+ bool incremental=false);
+ virtual NPT_Result Parse(NPT_InputStream& stream,
+ NPT_XmlNode*& tree,
+ bool incremental=false);
+ virtual NPT_Result Parse(NPT_InputStream& stream,
+ NPT_Size& size,
+ NPT_XmlNode*& tree,
+ bool incremental=false);
+
+ protected:
+ // NPT_XmlHandler methods
+ NPT_Result OnStartElement(const char* name);
+ NPT_Result OnElementAttribute(const char* name, const char* value);
+ NPT_Result OnEndElement(const char* name);
+ NPT_Result OnCharacterData(const char* data, NPT_Size size);
+ void RemoveIgnorableWhitespace();
+
+ // members
+ NPT_XmlProcessor* m_Processor;
+ NPT_XmlElementNode* m_Root;
+ NPT_XmlElementNode* m_CurrentElement;
+ bool m_KeepWhitespace;
+
+private:
+ void Reset();
+
+ // friends
+ friend class NPT_XmlProcessor;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlSerializer
++---------------------------------------------------------------------*/
+class NPT_XmlSerializer
+{
+public:
+ // methods
+ NPT_XmlSerializer(NPT_OutputStream* output,
+ NPT_Cardinal indentation = 0,
+ bool shrink_empty_elements = true,
+ bool add_xml_decl = false);
+ virtual ~NPT_XmlSerializer();
+ virtual NPT_Result StartDocument();
+ virtual NPT_Result EndDocument();
+ virtual NPT_Result StartElement(const char* prefix, const char* name);
+ virtual NPT_Result EndElement(const char* prefix, const char* name);
+ virtual NPT_Result Attribute(const char* prefix, const char* name, const char* value);
+ virtual NPT_Result Text(const char* text);
+ virtual NPT_Result CdataSection(const char* data);
+ virtual NPT_Result Comment(const char* comment);
+
+protected:
+ // methods
+ void EscapeChar(unsigned char c, char* text);
+ NPT_Result ProcessPending();
+ NPT_Result OutputEscapedString(const char* text, bool attribute);
+ void OutputIndentation(bool start);
+
+ // members
+ NPT_OutputStream* m_Output;
+ bool m_ElementPending;
+ NPT_Cardinal m_Depth;
+ NPT_Cardinal m_Indentation;
+ NPT_String m_IndentationPrefix;
+ bool m_ElementHasText;
+ bool m_ShrinkEmptyElements;
+ bool m_AddXmlDecl;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlWriter
++---------------------------------------------------------------------*/
+class NPT_XmlWriter
+{
+public:
+ // constructor
+ explicit NPT_XmlWriter(NPT_Cardinal indentation = 0) : m_Indentation(indentation) {}
+
+ // methods
+ NPT_Result Serialize(NPT_XmlNode& node,
+ NPT_OutputStream& stream,
+ bool add_xml_decl = false);
+
+private:
+ // members
+ NPT_Cardinal m_Indentation;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XmlCanonicalizer
++---------------------------------------------------------------------*/
+class NPT_XmlCanonicalizer
+{
+public:
+ // methods
+ NPT_Result Serialize(NPT_XmlNode& node,
+ NPT_OutputStream& stream,
+ bool add_xml_decl = false);
+};
+
+#endif // _NPT_XML_H_
diff --git a/lib/libUPnP/Neptune/Source/Core/NptZip.cpp b/lib/libUPnP/Neptune/Source/Core/NptZip.cpp
new file mode 100644
index 0000000..0ee50fd
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptZip.cpp
@@ -0,0 +1,886 @@
+/*****************************************************************
+|
+| Neptune - Zip Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptZip.h"
+#include "NptLogging.h"
+#include "NptUtils.h"
+
+#if defined(NPT_CONFIG_ENABLE_ZIP)
+#include "zlib.h"
+#endif
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.zip")
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+static const NPT_UInt32 NPT_ZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50;
+static const NPT_UInt32 NPT_ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06064b50;
+static const NPT_UInt32 NPT_ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE = 0x07064b50;
+static const NPT_UInt32 NPT_ZIP_CENTRAL_FILE_HEADER_SIGNATURE = 0x02014b50;
+//static const NPT_UInt32 NPT_ZIP_LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
+static const NPT_UInt16 NPT_ZIP_EXT_DATA_TYPE_ZIP64 = 0x0001;
+
+static const NPT_UInt32 NPT_ZIP_MAX_DIRECTORY_SIZE = 0x1000000; // 16 MB
+static const NPT_UInt32 NPT_ZIP_MAX_ENTRY_COUNT = 0x100000; // 1M entries
+
+/*----------------------------------------------------------------------
+| NPT_ZipFile::NPT_ZipFile
++---------------------------------------------------------------------*/
+NPT_ZipFile::NPT_ZipFile()
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipFile::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipFile::Parse(NPT_InputStream& stream, NPT_ZipFile*& file)
+{
+ // defautl return value
+ file = NULL;
+
+ // check that we know the size of the stream
+ NPT_LargeSize stream_size = 0;
+ NPT_Result result = stream.GetSize(stream_size);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("cannot get stream size (%d)", result);
+ return result;
+ }
+ if (stream_size < 22) {
+ NPT_LOG_WARNING("input stream too short");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ // seek to the most likely start of the end of central directory record
+ unsigned int max_eocdr_size = 22+65536;
+ if (max_eocdr_size > stream_size) {
+ max_eocdr_size = (unsigned int)stream_size;
+ }
+ unsigned char eocdr[22];
+ bool record_found = false;
+ NPT_Position position = 0;
+ for (unsigned int i=0; i<max_eocdr_size; i++) {
+ position = stream_size-22-i;
+ result = stream.Seek(position);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("seek failed (%d)", result);
+ return result;
+ }
+ result = stream.ReadFully(eocdr, 22);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("read failed (%d)", result);
+ return result;
+ }
+ NPT_UInt32 signature = NPT_BytesToInt32Le(eocdr);
+ if (signature == NPT_ZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE) {
+ record_found = true;
+ break;
+ }
+ }
+ if (!record_found) {
+ NPT_LOG_WARNING("eocd record not found at end of stream");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ // parse the eocdr
+ NPT_UInt32 this_disk = NPT_BytesToInt16Le(&eocdr[ 4]);
+ NPT_UInt32 start_disk = NPT_BytesToInt16Le(&eocdr[ 6]);
+ NPT_UInt64 this_disk_entry_count = NPT_BytesToInt16Le(&eocdr[ 8]);
+ NPT_UInt64 total_entry_count = NPT_BytesToInt16Le(&eocdr[10]);
+ NPT_UInt64 central_directory_size = NPT_BytesToInt32Le(&eocdr[12]);
+ NPT_Position central_directory_offset = NPT_BytesToInt32Le(&eocdr[16]);
+
+ // format check
+ if (this_disk != 0 || start_disk != 0) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ if (this_disk_entry_count != total_entry_count) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+
+ // check if this is a zip64 file
+ if (central_directory_offset == 0xFFFFFFFF) {
+ unsigned char zip64_locator[20];
+ result = stream.Seek(position-20);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("seek failed (%d)", result);
+ return result;
+ }
+ result = stream.ReadFully(zip64_locator, 20);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("read failed (%d)", result);
+ return result;
+ }
+
+ NPT_UInt32 signature = NPT_BytesToInt32Le(&zip64_locator[0]);
+ if (signature != NPT_ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE) {
+ NPT_LOG_WARNING("zip64 directory locator signature not found");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+ NPT_UInt32 zip64_disk_start = NPT_BytesToInt32Le(&zip64_locator[ 4]);
+ NPT_UInt64 zip64_directory_offset = NPT_BytesToInt64Le(&zip64_locator[ 8]);
+ NPT_UInt32 zip64_disk_count = NPT_BytesToInt32Le(&zip64_locator[16]);
+
+ // format check
+ if (zip64_disk_start != 0 || zip64_disk_count != 1) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+
+ // size check
+ if (zip64_directory_offset > stream_size) {
+ NPT_LOG_WARNING("zip64 directory offset too large");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ // load and parse the eocdr64
+ unsigned char eocdr64[56];
+ result = stream.Seek(zip64_directory_offset);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("seek failed (%d)", result);
+ return result;
+ }
+ result = stream.ReadFully(eocdr64, 56);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("read failed (%d)", result);
+ return result;
+ }
+
+ signature = NPT_BytesToInt32Le(&eocdr64[0]);
+ if (signature != NPT_ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE) {
+ NPT_LOG_WARNING("zip64 directory signature not found");
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ this_disk = NPT_BytesToInt32Le(&eocdr64[16]);
+ start_disk = NPT_BytesToInt32Le(&eocdr64[20]);
+ this_disk_entry_count = NPT_BytesToInt64Le(&eocdr64[24]);
+ total_entry_count = NPT_BytesToInt64Le(&eocdr64[32]);
+ central_directory_size = NPT_BytesToInt64Le(&eocdr64[40]);
+ central_directory_offset = NPT_BytesToInt64Le(&eocdr64[48]);
+ }
+
+ // format check
+ if (this_disk != 0 || start_disk != 0) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ if (this_disk_entry_count != total_entry_count) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+
+ // check that the size looks reasonable
+ if (central_directory_size > NPT_ZIP_MAX_DIRECTORY_SIZE) {
+ NPT_LOG_WARNING("central directory larger than max supported");
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+ if (total_entry_count > NPT_ZIP_MAX_ENTRY_COUNT) {
+ NPT_LOG_WARNING("central directory larger than max supported");
+ return NPT_ERROR_OUT_OF_RANGE;
+ }
+
+ // read the central directory
+ NPT_DataBuffer central_directory_buffer;
+ result = central_directory_buffer.SetDataSize((NPT_Size)central_directory_size);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("central directory too large (%lld)", central_directory_size);
+ return result;
+ }
+ result = stream.Seek(central_directory_offset);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("seek failed (%d)", result);
+ return result;
+ }
+ result = stream.ReadFully(central_directory_buffer.UseData(), (NPT_Size)central_directory_size);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("failed to read central directory (%d)", result);
+ return result;
+ }
+
+ // create a new file object
+ file = new NPT_ZipFile();
+ file->m_Entries.Reserve((NPT_Cardinal)total_entry_count);
+
+ // parse all entries
+ const unsigned char* buffer = (const unsigned char*)central_directory_buffer.GetData();
+ NPT_Size buffer_size = central_directory_buffer.GetDataSize();
+ for (unsigned int i=0; i<total_entry_count; i++) {
+ if (buffer_size < 4) break;
+ NPT_UInt32 signature = NPT_BytesToInt32Le(buffer);
+ if (signature != NPT_ZIP_CENTRAL_FILE_HEADER_SIGNATURE) {
+ NPT_LOG_WARNING("unexpected signature in central directory");
+ break;
+ }
+
+ NPT_ZipFile::Entry entry(buffer, buffer_size);
+ if (entry.m_DirectoryEntrySize == 0) {
+ NPT_LOG_WARNING("invalid entry data");
+ break;
+ }
+ if (entry.m_DirectoryEntrySize > central_directory_size ||
+ entry.m_DirectoryEntrySize > buffer_size) {
+ NPT_LOG_WARNING_1("entry size too large (%d)", entry.m_DirectoryEntrySize);
+ break;
+ }
+
+ file->GetEntries().Add(entry);
+
+ central_directory_size -= entry.m_DirectoryEntrySize;
+ buffer += entry.m_DirectoryEntrySize;
+ buffer_size -= entry.m_DirectoryEntrySize;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipFile::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipFile::GetInputStream(Entry& entry, NPT_InputStreamReference& zip_stream, NPT_InputStream*& file_stream)
+{
+ // default return value
+ file_stream = NULL;
+
+ // we don't support encrypted files
+ if (entry.m_Flags & NPT_ZIP_FILE_FLAG_ENCRYPTED) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+
+ // check that we support the compression method
+#if NPT_CONFIG_ENABLE_ZIP
+ if (entry.m_CompressionMethod != NPT_ZIP_FILE_COMPRESSION_METHOD_NONE &&
+ entry.m_CompressionMethod != NPT_ZIP_FILE_COMPRESSION_METHOD_DEFLATE) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+#else
+ if (entry.m_CompressionMethod != NPT_ZIP_FILE_COMPRESSION_METHOD_NONE) {
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+#endif
+
+ // seek to the start of the file entry
+ NPT_Result result = zip_stream->Seek(entry.m_RelativeOffset);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("seek failed (%d)", result);
+ return result;
+ }
+
+ // read the fixed part of the header
+ unsigned char header[30];
+ result = zip_stream->ReadFully(header, 30);
+ if (NPT_FAILED(result)) {
+ NPT_LOG_WARNING_1("read failed (%d)", result);
+ return result;
+ }
+
+ NPT_UInt16 file_name_length = NPT_BytesToInt16Le(&header[26]);
+ NPT_UInt16 extra_field_length = NPT_BytesToInt16Le(&header[28]);
+
+ unsigned int header_size = 30+file_name_length+extra_field_length;
+ NPT_LargeSize zip_stream_size = 0;
+ zip_stream->GetSize(zip_stream_size);
+ if (entry.m_RelativeOffset+header_size+entry.m_CompressedSize > zip_stream_size) {
+ // something's wrong here
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ file_stream = new NPT_SubInputStream(zip_stream, entry.m_RelativeOffset+header_size, entry.m_CompressedSize);
+
+#if NPT_CONFIG_ENABLE_ZIP
+ if (entry.m_CompressionMethod == NPT_ZIP_FILE_COMPRESSION_METHOD_DEFLATE) {
+ NPT_InputStreamReference file_stream_ref(file_stream);
+ file_stream = new NPT_ZipInflatingInputStream(file_stream_ref, true);
+ }
+#endif
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipFile::Entry::Entry
++---------------------------------------------------------------------*/
+NPT_ZipFile::Entry::Entry(const unsigned char* data, NPT_Size data_available) :
+ m_Flags(0),
+ m_CompressionMethod(0),
+ m_Crc32(0),
+ m_CompressedSize(0),
+ m_UncompressedSize(0),
+ m_DiskNumber(0),
+ m_InternalFileAttributes(0),
+ m_ExternalFileAttributes(0),
+ m_RelativeOffset(0),
+ m_DirectoryEntrySize(0)
+{
+ if (data_available < 46) return;
+
+ m_Flags = NPT_BytesToInt16Le(data+ 8);
+ m_CompressionMethod = NPT_BytesToInt16Le(data+10);
+ m_Crc32 = NPT_BytesToInt32Le(data+16);
+ m_CompressedSize = NPT_BytesToInt32Le(data+20);
+ m_UncompressedSize = NPT_BytesToInt32Le(data+24);
+ m_DiskNumber = NPT_BytesToInt16Le(data+34);
+ m_InternalFileAttributes = NPT_BytesToInt32Le(data+36);
+ m_ExternalFileAttributes = NPT_BytesToInt32Le(data+38);
+ m_RelativeOffset = NPT_BytesToInt32Le(data+42);
+
+ NPT_UInt16 file_name_length = NPT_BytesToInt16Le(data+28);
+ NPT_UInt16 extra_field_length = NPT_BytesToInt16Le(data+30);
+ NPT_UInt16 file_comment_length = NPT_BytesToInt16Le(data+32);
+
+ m_DirectoryEntrySize = 46+file_name_length+extra_field_length+file_comment_length;
+ if (m_DirectoryEntrySize > data_available) {
+ m_DirectoryEntrySize = 0;
+ return;
+ }
+
+ // extract the file name
+ m_Name.Assign((const char*)data+46, file_name_length);
+
+ // check for a zip64 extension
+ const unsigned char* ext_data = data+46+file_name_length;
+ unsigned int ext_data_size = extra_field_length;
+ while (ext_data_size >= 4) {
+ unsigned int ext_id = NPT_BytesToInt16Le(ext_data);
+ unsigned int ext_size = NPT_BytesToInt16Le(ext_data+2);
+
+ if (ext_id == NPT_ZIP_EXT_DATA_TYPE_ZIP64) {
+ const unsigned char* local_data = ext_data+4;
+ if (m_UncompressedSize == 0xFFFFFFFF) {
+ m_UncompressedSize = NPT_BytesToInt64Le(local_data);
+ local_data += 8;
+ }
+ if (m_CompressedSize == 0xFFFFFFFF) {
+ m_CompressedSize = NPT_BytesToInt64Le(local_data);
+ local_data += 8;
+ }
+ if (m_RelativeOffset == 0xFFFFFFFF) {
+ m_RelativeOffset = NPT_BytesToInt64Le(local_data);
+ local_data += 8;
+ }
+ if (m_DiskNumber == 0xFFFF) {
+ m_DiskNumber = NPT_BytesToInt32Le(local_data);
+ local_data += 4;
+ }
+ }
+
+ ext_data += 4+ext_size;
+ if (ext_data_size >= 4+ext_size) {
+ ext_data_size -= 4+ext_size;
+ } else {
+ ext_data_size = 0;
+ }
+ }
+}
+
+#if defined(NPT_CONFIG_ENABLE_ZIP)
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_ZIP_DEFAULT_BUFFER_SIZE = 4096;
+
+/*----------------------------------------------------------------------
+| NPT_Zip::MapError
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Zip::MapError(int err)
+{
+ switch (err) {
+ case Z_OK: return NPT_SUCCESS;
+ case Z_STREAM_END: return NPT_ERROR_EOS;
+ case Z_DATA_ERROR:
+ case Z_STREAM_ERROR: return NPT_ERROR_INVALID_FORMAT;
+ case Z_MEM_ERROR: return NPT_ERROR_OUT_OF_MEMORY;
+ case Z_VERSION_ERROR: return NPT_ERROR_INTERNAL;
+ case Z_NEED_DICT: return NPT_ERROR_NOT_SUPPORTED;
+ default: return NPT_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflateState
++---------------------------------------------------------------------*/
+class NPT_ZipInflateState {
+public:
+ NPT_ZipInflateState(bool raw = false);
+ ~NPT_ZipInflateState();
+ z_stream m_Stream;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflateState::NPT_ZipInflateState
++---------------------------------------------------------------------*/
+NPT_ZipInflateState::NPT_ZipInflateState(bool raw)
+{
+ // initialize the state
+ NPT_SetMemory(&m_Stream, 0, sizeof(m_Stream));
+
+ // initialize the decompressor
+ inflateInit2(&m_Stream, raw?-15:15+32); // 15 = default window bits, +32 = automatic header
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflateState::~NPT_ZipInflateState
++---------------------------------------------------------------------*/
+NPT_ZipInflateState::~NPT_ZipInflateState()
+{
+ inflateEnd(&m_Stream);
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflateState
++---------------------------------------------------------------------*/
+class NPT_ZipDeflateState {
+public:
+ NPT_ZipDeflateState(int compression_level,
+ NPT_Zip::Format format);
+ ~NPT_ZipDeflateState();
+ z_stream m_Stream;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflateState::NPT_ZipDeflateState
++---------------------------------------------------------------------*/
+NPT_ZipDeflateState::NPT_ZipDeflateState(int compression_level,
+ NPT_Zip::Format format)
+{
+ // check parameters
+ if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
+ compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
+ compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT;
+ }
+
+ // initialize the state
+ NPT_SetMemory(&m_Stream, 0, sizeof(m_Stream));
+
+ // initialize the compressor
+ deflateInit2(&m_Stream,
+ compression_level,
+ Z_DEFLATED,
+ 15 + (format == NPT_Zip::GZIP ? 16 : 0),
+ 8,
+ Z_DEFAULT_STRATEGY);
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflateState::~NPT_ZipDeflateState
++---------------------------------------------------------------------*/
+NPT_ZipDeflateState::~NPT_ZipDeflateState()
+{
+ deflateEnd(&m_Stream);
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::NPT_ZipInflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipInflatingInputStream::NPT_ZipInflatingInputStream(NPT_InputStreamReference& source, bool raw) :
+ m_Source(source),
+ m_Position(0),
+ m_State(new NPT_ZipInflateState(raw)),
+ m_Buffer(NPT_ZIP_DEFAULT_BUFFER_SIZE)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::~NPT_ZipInflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipInflatingInputStream::~NPT_ZipInflatingInputStream()
+{
+ delete m_State;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipInflatingInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ // check state and parameters
+ if (m_State == NULL) return NPT_ERROR_INVALID_STATE;
+ if (buffer == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // default values
+ if (bytes_read) *bytes_read = 0;
+
+ // setup the output buffer
+ m_State->m_Stream.next_out = (Bytef*)buffer;
+ m_State->m_Stream.avail_out = (uInt)bytes_to_read;
+
+ while (m_State->m_Stream.avail_out) {
+ // decompress what we can
+ int err = inflate(&m_State->m_Stream, Z_NO_FLUSH);
+
+ if (err == Z_STREAM_END) {
+ // we decompressed everything
+ break;
+ } else if (err == Z_OK) {
+ // we got something
+ continue;
+ } else if (err == Z_BUF_ERROR) {
+ // we need more input data
+ NPT_Size input_bytes_read = 0;
+ NPT_Result result = m_Source->Read(m_Buffer.UseData(), m_Buffer.GetBufferSize(), &input_bytes_read);
+ if (NPT_FAILED(result)) return result;
+
+ // setup the input buffer
+ m_Buffer.SetDataSize(input_bytes_read);
+ m_State->m_Stream.next_in = m_Buffer.UseData();
+ m_State->m_Stream.avail_in = m_Buffer.GetDataSize();
+
+ } else {
+ return NPT_Zip::MapError(err);
+ }
+ }
+
+ // report how much we could decompress
+ NPT_Size progress = bytes_to_read - m_State->m_Stream.avail_out;
+ if (bytes_read) {
+ *bytes_read = progress;
+ }
+ m_Position += progress;
+
+ return progress == 0 ? NPT_ERROR_EOS:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipInflatingInputStream::Seek(NPT_Position /* offset */)
+{
+ // we can't seek
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipInflatingInputStream::Tell(NPT_Position& offset)
+{
+ offset = m_Position;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipInflatingInputStream::GetSize(NPT_LargeSize& size)
+{
+ // the size is not predictable
+ size = 0;
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipInflatingInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ // we don't know
+ available = 0;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipDeflatingInputStream::NPT_ZipDeflatingInputStream(
+ NPT_InputStreamReference& source,
+ int compression_level,
+ NPT_Zip::Format format) :
+ m_Source(source),
+ m_Position(0),
+ m_Eos(false),
+ m_State(new NPT_ZipDeflateState(compression_level, format)),
+ m_Buffer(NPT_ZIP_DEFAULT_BUFFER_SIZE)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::~NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipDeflatingInputStream::~NPT_ZipDeflatingInputStream()
+{
+ delete m_State;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipDeflatingInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ // check state and parameters
+ if (m_State == NULL) return NPT_ERROR_INVALID_STATE;
+ if (buffer == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+ if (bytes_to_read == 0) return NPT_SUCCESS;
+
+ // default values
+ if (bytes_read) *bytes_read = 0;
+
+ // setup the output buffer
+ m_State->m_Stream.next_out = (Bytef*)buffer;
+ m_State->m_Stream.avail_out = (uInt)bytes_to_read;
+
+ while (m_State->m_Stream.avail_out) {
+ // compress what we can
+ int err = deflate(&m_State->m_Stream, m_Eos?Z_FINISH:Z_NO_FLUSH);
+
+ if (err == Z_STREAM_END) {
+ // we compressed everything
+ break;
+ } else if (err == Z_OK) {
+ // we got something
+ continue;
+ } else if (err == Z_BUF_ERROR) {
+ // we need more input data
+ NPT_Size input_bytes_read = 0;
+ NPT_Result result = m_Source->Read(m_Buffer.UseData(), m_Buffer.GetBufferSize(), &input_bytes_read);
+ if (result == NPT_ERROR_EOS) {
+ m_Eos = true;
+ } else {
+ if (NPT_FAILED(result)) return result;
+ }
+
+ // setup the input buffer
+ m_Buffer.SetDataSize(input_bytes_read);
+ m_State->m_Stream.next_in = m_Buffer.UseData();
+ m_State->m_Stream.avail_in = m_Buffer.GetDataSize();
+
+ } else {
+ return NPT_Zip::MapError(err);
+ }
+ }
+
+ // report how much we could compress
+ NPT_Size progress = bytes_to_read - m_State->m_Stream.avail_out;
+ if (bytes_read) {
+ *bytes_read = progress;
+ }
+ m_Position += progress;
+
+ return progress == 0 ? NPT_ERROR_EOS:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipDeflatingInputStream::Seek(NPT_Position /* offset */)
+{
+ // we can't seek
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipDeflatingInputStream::Tell(NPT_Position& offset)
+{
+ offset = m_Position;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipDeflatingInputStream::GetSize(NPT_LargeSize& size)
+{
+ // the size is not predictable
+ size = 0;
+ return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_ZipDeflatingInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ // we don't know
+ available = 0;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_Zip::Deflate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Zip::Deflate(const NPT_DataBuffer& in,
+ NPT_DataBuffer& out,
+ int compression_level,
+ Format format /* = ZLIB */)
+{
+ // default return state
+ out.SetDataSize(0);
+
+ // check parameters
+ if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
+ compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // setup the stream
+ z_stream stream;
+ NPT_SetMemory(&stream, 0, sizeof(stream));
+ stream.next_in = (Bytef*)in.GetData();
+ stream.avail_in = (uInt)in.GetDataSize();
+
+ // setup the memory functions
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ // initialize the compressor
+ int err = deflateInit2(&stream,
+ compression_level,
+ Z_DEFLATED,
+ 15 + (format == GZIP ? 16 : 0),
+ 8,
+ Z_DEFAULT_STRATEGY);
+ if (err != Z_OK) return MapError(err);
+
+ // reserve an output buffer known to be large enough
+ out.Reserve((NPT_Size)deflateBound(&stream, stream.avail_in) + (format==GZIP?10:0));
+ stream.next_out = out.UseData();
+ stream.avail_out = out.GetBufferSize();
+
+ // decompress
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return MapError(err);
+ }
+
+ // update the output size
+ out.SetDataSize((NPT_Size)stream.total_out);
+
+ // cleanup
+ err = deflateEnd(&stream);
+ return MapError(err);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Zip::Inflate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Zip::Inflate(const NPT_DataBuffer& in,
+ NPT_DataBuffer& out,
+ bool raw)
+{
+ // assume an output buffer twice the size of the input plus a bit
+ NPT_CHECK_WARNING(out.Reserve(32+2*in.GetDataSize()));
+
+ // setup the stream
+ z_stream stream;
+ stream.next_in = (Bytef*)in.GetData();
+ stream.avail_in = (uInt)in.GetDataSize();
+ stream.next_out = out.UseData();
+ stream.avail_out = (uInt)out.GetBufferSize();
+
+ // setup the memory functions
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ // initialize the decompressor
+ int err = inflateInit2(&stream, raw?-15:15+32); // 15 = default window bits, +32 = automatic header
+ if (err != Z_OK) return MapError(err);
+
+ // decompress until the end
+ do {
+ err = inflate(&stream, Z_SYNC_FLUSH);
+ if (err == Z_STREAM_END || err == Z_OK || err == Z_BUF_ERROR) {
+ out.SetDataSize((NPT_Size)stream.total_out);
+ if ((err == Z_OK && stream.avail_out == 0) || err == Z_BUF_ERROR) {
+ // grow the output buffer
+ out.Reserve(out.GetBufferSize()*2);
+ stream.next_out = out.UseData()+stream.total_out;
+ stream.avail_out = out.GetBufferSize()-(NPT_Size)stream.total_out;
+ }
+ }
+ } while (err == Z_OK);
+
+ // check for errors
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return MapError(err);
+ }
+
+ // cleanup
+ err = inflateEnd(&stream);
+ return MapError(err);
+}
+
+
+/*----------------------------------------------------------------------
+| NPT_Zip::Deflate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Zip::Deflate(NPT_File& in,
+ NPT_File& out,
+ int compression_level,
+ Format format /* = ZLIB */)
+{
+ // check parameters
+ if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
+ compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ NPT_InputStreamReference input;
+ NPT_CHECK(in.GetInputStream(input));
+ NPT_OutputStreamReference output;
+ NPT_CHECK(out.GetOutputStream(output));
+
+ NPT_ZipDeflatingInputStream deflating_stream(input, compression_level, format);
+ return NPT_StreamToStreamCopy(deflating_stream, *output.AsPointer());
+}
+
+#endif // NPT_CONFIG_ENABLE_ZIP
diff --git a/lib/libUPnP/Neptune/Source/Core/NptZip.h b/lib/libUPnP/Neptune/Source/Core/NptZip.h
new file mode 100644
index 0000000..fbbebcb
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Core/NptZip.h
@@ -0,0 +1,220 @@
+/*****************************************************************
+|
+| Neptune - Zip Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+| * Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+| * Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+| * Neither the name of Axiomatic Systems nor the
+| names of its contributors may be used to endorse or promote products
+| derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_ZIP_H_
+#define _NPT_ZIP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptStreams.h"
+#include "NptArray.h"
+#include "NptFile.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class NPT_ZipInflateState;
+class NPT_ZipDeflateState;
+
+/*----------------------------------------------------------------------
+| NPT_ZipFile
++---------------------------------------------------------------------*/
+const unsigned int NPT_ZIP_FILE_FLAG_ENCRYPTED = 0x01;
+const unsigned int NPT_ZIP_FILE_COMPRESSION_METHOD_NONE = 0x00;
+const unsigned int NPT_ZIP_FILE_COMPRESSION_METHOD_DEFLATE = 0x08;
+
+class NPT_ZipFile
+{
+public:
+ // types
+ class Entry {
+ public:
+ Entry(const unsigned char* data, NPT_Size data_available);
+ NPT_String m_Name;
+ NPT_UInt16 m_Flags;
+ NPT_UInt16 m_CompressionMethod;
+ NPT_UInt32 m_Crc32;
+ NPT_LargeSize m_CompressedSize;
+ NPT_LargeSize m_UncompressedSize;
+ NPT_UInt16 m_DiskNumber;
+ NPT_UInt16 m_InternalFileAttributes;
+ NPT_UInt32 m_ExternalFileAttributes;
+ NPT_Position m_RelativeOffset;
+ NPT_UInt32 m_DirectoryEntrySize;
+ };
+
+ // class methods
+ static NPT_Result Parse(NPT_InputStream& stream, NPT_ZipFile*& file);
+ static NPT_Result GetInputStream(Entry& entry, NPT_InputStreamReference& zip_stream, NPT_InputStream*& file_stream);
+
+ // accessors
+ NPT_Array<Entry>& GetEntries() { return m_Entries; }
+
+private:
+ // constructor
+ NPT_ZipFile();
+
+ // members
+ NPT_Array<Entry> m_Entries;
+};
+
+/*----------------------------------------------------------------------
+| NPT_Zip
++---------------------------------------------------------------------*/
+const int NPT_ZIP_COMPRESSION_LEVEL_DEFAULT = -1;
+const int NPT_ZIP_COMPRESSION_LEVEL_MIN = 0;
+const int NPT_ZIP_COMPRESSION_LEVEL_MAX = 9;
+const int NPT_ZIP_COMPRESSION_LEVEL_NONE = 0;
+class NPT_Zip
+{
+public:
+ // class methods
+ static NPT_Result MapError(int err);
+
+ /**
+ * Compressed data format
+ */
+ typedef enum {
+ ZLIB,
+ GZIP
+ } Format;
+
+ /**
+ * Deflate (i.e compress) a buffer
+ */
+ static NPT_Result Deflate(const NPT_DataBuffer& in,
+ NPT_DataBuffer& out,
+ int compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT,
+ Format format = ZLIB);
+
+ /**
+ * Inflate (i.e decompress) a buffer
+ */
+ static NPT_Result Inflate(const NPT_DataBuffer& in,
+ NPT_DataBuffer& out,
+ bool raw = false);
+
+ /**
+ * Deflate (i.e compress) a file
+ */
+ static NPT_Result Deflate(NPT_File& in,
+ NPT_File& out,
+ int compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT,
+ Format format = GZIP);
+
+};
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingInputStream
++---------------------------------------------------------------------*/
+class NPT_ZipInflatingInputStream : public NPT_InputStream
+{
+public:
+ NPT_ZipInflatingInputStream(NPT_InputStreamReference& source, bool raw = false);
+ ~NPT_ZipInflatingInputStream() override;
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result Seek(NPT_Position offset) override;
+ NPT_Result Tell(NPT_Position& offset) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override;
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+private:
+ NPT_InputStreamReference m_Source;
+ NPT_Position m_Position;
+ NPT_ZipInflateState* m_State;
+ NPT_DataBuffer m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ZipInflatingOutputStream
++---------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+class NPT_ZipDeflatingInputStream : public NPT_InputStream
+{
+public:
+ NPT_ZipDeflatingInputStream(NPT_InputStreamReference& source,
+ int compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT,
+ NPT_Zip::Format format = NPT_Zip::ZLIB);
+ ~NPT_ZipDeflatingInputStream() override;
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result Seek(NPT_Position offset) override;
+ NPT_Result Tell(NPT_Position& offset) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override;
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+private:
+ NPT_InputStreamReference m_Source;
+ NPT_Position m_Position;
+ bool m_Eos;
+ NPT_ZipDeflateState* m_State;
+ NPT_DataBuffer m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+| NPT_ZipDeflatingOutputStream
++---------------------------------------------------------------------*/
+/*class NPT_ZipDeflatingOutputStream : public NPT_OutputStream
+{
+public:
+ NPT_ZipDeflatingOutputStream(NPT_OutputStreamReference& source,
+ int compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT,
+ NPT_Zip::Format format = NPT_Zip::ZLIB);
+ NPT_ZipDeflatingOutputStream();
+
+ // NPT_OutputStream methods
+ virtual NPT_Result Write(void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written = NULL);
+ virtual NPT_Result Seek(NPT_Position offset);
+ virtual NPT_Result Tell(NPT_Position& offset);
+
+private:
+ NPT_OutputStreamReference m_Output;
+ NPT_Position m_Position;
+ bool m_Eos;
+ NPT_ZipDeflateState* m_State;
+ NPT_DataBuffer m_Buffer;
+}; */
+
+#endif // _NPT_ZIP_H_