1/*
2 * INTEL CONFIDENTIAL
3 * Copyright (c) 2002 - 2005 Intel Corporation.  All rights reserved.
4 *
5 * The source code contained or described herein and all documents
6 * related to the source code ("Material") are owned by Intel
7 * Corporation or its suppliers or licensors.  Title to the
8 * Material remains with Intel Corporation or its suppliers and
9 * licensors.  The Material contains trade secrets and proprietary
10 * and confidential information of Intel or its suppliers and
11 * licensors. The Material is protected by worldwide copyright and
12 * trade secret laws and treaty provisions.  No part of the Material
13 * may be used, copied, reproduced, modified, published, uploaded,
14 * posted, transmitted, distributed, or disclosed in any way without
15 * Intel's prior express written permission.
16
17 * No license under any patent, copyright, trade secret or other
18 * intellectual property right is granted to or conferred upon you
19 * by disclosure or delivery of the Materials, either expressly, by
20 * implication, inducement, estoppel or otherwise. Any license
21 * under such intellectual property rights must be express and
22 * approved by Intel in writing.
23 *
24 * $Workfile: ILibParsers.c
25 * $Revision: #1.0.1922.38347
26 * $Author:   Intel Corporation, Intel Device Builder
27 * $Date:     Wednesday, April 06, 2005
28 *
29 *
30 *
31 */
32
33#ifdef WCN
34
35/*
36#if defined(WINSOCK2)
37	#include <winsock2.h>
38	#include <ws2tcpip.h>
39#elif defined(WINSOCK1)
40	#include <winsock.h>
41	#include <wininet.h>
42#endif
43*/
44/*
45#if defined(WIN32) && !defined(_WIN32_WCE)
46	#define _CRTDBG_MAP_ALLOC
47	#include <crtdbg.h>
48#endif
49*/
50
51#include "ILibParsers.h"
52
53//#ifdef _POSIX
54//#include <time.h>
55//#endif
56
57//#define DEBUGSTATEMENT(x)
58//#define MINPORTNUMBER 50000
59//#define PORTNUMBERRANGE 15000
60//#define UPNP_MAX_WAIT 86400	// 24 Hours
61
62//#if defined(WIN32) || defined(_WIN32_WCE)
63//	static sem_t ILibChainLock = NULL;
64//#else
65//	extern int errno;
66//	static sem_t ILibChainLock;
67//#endif
68
69
70//static int ILibChainLock_RefCounter = 0;
71
72/*
73static int malloc_counter = 0;
74void* dbg_malloc(int sz)
75{
76	++malloc_counter;
77	return((void*)malloc(sz));
78}
79void dbg_free(void* ptr)
80{
81	--malloc_counter;
82	free(ptr);
83}
84int dbg_GetCount()
85{
86	return(malloc_counter);
87}
88*/
89
90
91//
92// All of the following structures are meant to be private internal structures
93//
94struct ILibStackNode
95{
96	void *Data;
97	struct ILibStackNode *Next;
98};
99/*
100struct ILibQueueNode
101{
102	struct ILibStackNode *Head;
103	struct ILibStackNode *Tail;
104	sem_t LOCK;
105};
106*/
107/*
108struct HashNode_Root
109{
110	struct HashNode *Root;
111	sem_t LOCK;
112};
113*/
114/*
115struct HashNode
116{
117	struct HashNode *Next;
118	struct HashNode *Prev;
119	int KeyHash;
120	char *KeyValue;
121	int KeyLength;
122	void *Data;
123};
124*/
125/*
126struct HashNodeEnumerator
127{
128	struct HashNode *node;
129};
130*/
131/*
132struct ILibLinkedListNode
133{
134	void *Data;
135	struct ILibLinkedListNode_Root *Root;
136	struct ILibLinkedListNode *Next;
137	struct ILibLinkedListNode *Previous;
138};
139*/
140/*
141struct ILibLinkedListNode_Root
142{
143	sem_t LOCK;
144	long count;
145	struct ILibLinkedListNode *Head;
146	struct ILibLinkedListNode *Tail;
147};
148*/
149
150
151
152
153/*
154#ifdef WINSOCK2
155int ILibGetLocalIPAddressNetMask(int address)
156{
157	SOCKET s;
158	DWORD bytesReturned;
159	SOCKADDR_IN* pAddrInet;
160	INTERFACE_INFO localAddr[10];  // Assume there will be no more than 10 IP interfaces
161	int numLocalAddr;
162	int i;
163
164
165	if((s = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0)) == INVALID_SOCKET)
166	{
167		fprintf (stderr, "Socket creation failed\n");
168     	return(0);
169   	}
170
171	// Enumerate all IP interfaces
172	if(WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, &localAddr,
173                      sizeof(localAddr), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
174	{
175		fprintf(stderr, "WSAIoctl fails with error %d\n", GetLastError());
176		closesocket(s);
177		return(0);
178	}
179
180	closesocket(s);
181
182	// Display interface information
183	numLocalAddr = (bytesReturned/sizeof(INTERFACE_INFO));
184	for (i=0; i<numLocalAddr; i++)
185	{
186
187		pAddrInet = (SOCKADDR_IN*)&localAddr[i].iiAddress;
188		if(pAddrInet->sin_addr.S_un.S_addr == address)
189		{
190			pAddrInet = (SOCKADDR_IN*)&localAddr[i].iiNetmask;
191			return(pAddrInet->sin_addr.s_addr);
192		}
193	}
194	return(0);
195}
196#endif
197*/
198
199/*! \fn ILibGetLocalIPAddressList(int** pp_int)
200	\brief Gets a list of IP Addresses
201	\para
202	\b NOTE: \a pp_int must be freed
203	\param[out] pp_int Array of IP Addresses
204	\returns Number of IP Addresses returned
205*/
206/*
207int ILibGetLocalIPAddressList(int** pp_int)
208{
209	//
210	// Winsock2 will use an Ioctl call to fetch the IPAddress list
211	//
212#if defined(WINSOCK2)
213	int i;
214	char buffer[16*sizeof(SOCKET_ADDRESS_LIST)];
215	DWORD bufferSize;
216	SOCKET TempSocket = socket(AF_INET,SOCK_DGRAM,0);
217	WSAIoctl(TempSocket,SIO_ADDRESS_LIST_QUERY,NULL,0,buffer,16*sizeof(SOCKET_ADDRESS_LIST),&bufferSize,NULL,NULL);
218	*pp_int = (int*)malloc(sizeof(int)*(1+((SOCKET_ADDRESS_LIST*)buffer)->iAddressCount));
219	for (i = 0;i < ((SOCKET_ADDRESS_LIST*)buffer)->iAddressCount;++i)
220	{
221		(*pp_int)[i] = ((struct sockaddr_in*)(((SOCKET_ADDRESS_LIST*)buffer)->Address[i].lpSockaddr))->sin_addr.s_addr;
222	}
223	(*pp_int)[i] = inet_addr("127.0.0.1");
224	closesocket(TempSocket);
225	return(1+((SOCKET_ADDRESS_LIST*)buffer)->iAddressCount);
226#elif defined(WINSOCK1)
227	//
228	// Winsock1 will use gethostbyname to fetch the IPAddress List
229	//
230	char name[256];
231	int i = 0;
232	int num = 0;
233	struct hostent *entry;
234	gethostname(name,256);
235	entry = (struct hostent*)gethostbyname(name);
236	if (entry->h_length != 4) return 0;
237	while (entry->h_addr_list[num]!=0) ++num;
238	*pp_int = (int*)malloc(sizeof(int)*num);
239	for (i = 0;i < num;++i)
240	{
241		(*pp_int)[i] = *((u_long*)entry->h_addr_list[i]);
242	}
243	return num;
244#elif _POSIX
245	//
246	// Posix will also use an Ioctl call to get the IPAddress List
247	//
248	char szBuffer[16*sizeof(struct ifreq)];
249	struct ifconf ifConf;
250	struct ifreq ifReq;
251	int nResult;
252	int LocalSock;
253	struct sockaddr_in LocalAddr;
254	int tempresults[16];
255	int ctr=0;
256	int i;
257	// Create an unbound datagram socket to do the SIOCGIFADDR ioctl on.
258	if ((LocalSock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
259	{
260		DEBUGSTATEMENT(printf("Can't do that\r\n"));
261		exit(1);
262	}
263	// Get the interface configuration information...
264	ifConf.ifc_len = sizeof szBuffer;
265	ifConf.ifc_ifcu.ifcu_buf = (caddr_t)szBuffer;
266	nResult = ioctl(LocalSock, SIOCGIFCONF, &ifConf);
267	if (nResult < 0)
268	{
269		DEBUGSTATEMENT(printf("ioctl error\r\n"));
270		exit(1);
271	}
272	// Cycle through the list of interfaces looking for IP addresses.
273	for (i = 0;(i < ifConf.ifc_len);)
274	{
275		struct ifreq *pifReq = (struct ifreq *)((caddr_t)ifConf.ifc_req + i);
276		i += sizeof *pifReq;
277		// See if this is the sort of interface we want to deal with.
278		strcpy (ifReq.ifr_name, pifReq -> ifr_name);
279		if (ioctl (LocalSock, SIOCGIFFLAGS, &ifReq) < 0)
280		{
281			DEBUGSTATEMENT(printf("Can't get flags\r\n"));
282			exit(1);
283		}
284		// Skip loopback, point-to-point and down interfaces,
285		// except don't skip down interfaces
286		// if we're trying to get a list of configurable interfaces.
287		if ((ifReq.ifr_flags & IFF_LOOPBACK) || (!(ifReq.ifr_flags & IFF_UP)))
288		{
289			continue;
290		}
291		if (pifReq -> ifr_addr.sa_family == AF_INET)
292		{
293			// Get a pointer to the address...
294			memcpy (&LocalAddr, &pifReq -> ifr_addr, sizeof pifReq -> ifr_addr);
295			if (LocalAddr.sin_addr.s_addr != htonl (INADDR_LOOPBACK))
296			{
297				tempresults[ctr] = LocalAddr.sin_addr.s_addr;
298				++ctr;
299			}
300		}
301	}
302	close(LocalSock);
303	*pp_int = (int*)malloc(sizeof(int)*(ctr));
304	memcpy(*pp_int,tempresults,sizeof(int)*ctr);
305	return(ctr);
306#endif
307}
308*/
309
310/*
311struct ILibChain
312{
313	void (*PreSelect)(void* object,fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime);
314	void (*PostSelect)(void* object,int slct, fd_set *readset, fd_set *writeset, fd_set *errorset);
315	void (*Destroy)(void* object);
316};
317*/
318/*
319struct LifeTimeMonitorData
320{
321	unsigned long ExpirationTick;
322	void *data;
323	void (*CallbackPtr)(void *data);
324	void (*DestroyPtr)(void *data);
325	struct LifeTimeMonitorData *Prev;
326	struct LifeTimeMonitorData *Next;
327};
328*/
329/*
330struct ILibLifeTime
331{
332	void (*PreSelect)(void* object,fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime);
333	void (*PostSelect)(void* object,int slct, fd_set *readset, fd_set *writeset, fd_set *errorset);
334	void (*Destroy)(void* object);
335	struct LifeTimeMonitorData *LM;
336	void *Chain;
337
338	void *Reserved;
339	sem_t SyncLock;
340};
341*/
342/*
343struct ILibBaseChain
344{
345	int TerminateFlag;
346#if defined(WIN32) || defined(_WIN32_WCE)
347	SOCKET Terminate;
348#else
349	FILE *TerminateReadPipe;
350	FILE *TerminateWritePipe;
351#endif
352	void *Object;
353	void *Next;
354};
355*/
356//
357// Do not Modify this method.
358// This decompresses compressed string blocks, which is used to store the
359// various description documents
360//
361/*
362char* ILibDecompressString(unsigned char* CurrentCompressed, const int bufferLength, const int DecompressedLength)
363{
364	unsigned char *RetVal = (char*)malloc(DecompressedLength+1);
365	unsigned char *CurrentUnCompressed = RetVal;
366	unsigned char *EndPtr = RetVal + DecompressedLength;
367	int offset,length;
368
369	do
370	{
371		// UnCompressed Data Block
372		memcpy(CurrentUnCompressed,CurrentCompressed+1,(int)*CurrentCompressed);
373		//MEMCHECK(assert((int)*CurrentCompressed <= (DecompressedLength+1) );)
374
375		CurrentUnCompressed += (int)*CurrentCompressed;
376		CurrentCompressed += 1+((int)*CurrentCompressed);
377
378		// CompressedBlock
379#ifdef REQUIRES_MEMORY_ALIGNMENT
380		length = (unsigned short)((*(CurrentCompressed)) & 63);
381		offset = ((unsigned short)(*(CurrentCompressed+1))<<2) + (((unsigned short)(*(CurrentCompressed))) >> 6);
382#else
383		length = (*((unsigned short*)(CurrentCompressed)))&((unsigned short)63);
384		offset = (*((unsigned short*)(CurrentCompressed)))>>6;
385#endif
386		memcpy(CurrentUnCompressed,CurrentUnCompressed-offset,length);
387		//MEMCHECK(assert(length <= (DecompressedLength+1)-(CurrentUnCompressed - RetVal));)
388
389		CurrentCompressed += 2;
390		CurrentUnCompressed += length;
391	} while(CurrentUnCompressed < EndPtr);
392	RetVal[DecompressedLength] = 0;
393	return(RetVal);
394}
395*/
396
397/*! \fn ILibCreateChain()
398	\brief Creates an empty Chain
399	\returns Chain
400*/
401/*
402void *ILibCreateChain()
403{
404	struct ILibBaseChain *RetVal = (struct ILibBaseChain*)malloc(sizeof(struct ILibBaseChain));
405
406#if defined(WIN32) || defined(_WIN32_WCE)
407	WORD wVersionRequested;
408	WSADATA wsaData;
409	#ifdef WINSOCK1
410		wVersionRequested = MAKEWORD( 1, 1 );
411	#elif WINSOCK2
412		wVersionRequested = MAKEWORD( 2, 0 );
413	#endif
414	if (WSAStartup( wVersionRequested, &wsaData ) != 0) {exit(1);}
415
416	RetVal->Terminate = socket(AF_INET, SOCK_DGRAM, 0);
417#endif
418	memset(RetVal,0,sizeof(struct ILibBaseChain));
419
420	#ifdef _POSIX
421	long timeptr = 0;
422	time(&timeptr);
423	srand(timeptr);
424	#else
425	srand((unsigned int)time(NULL));
426	#endif
427
428	RetVal->Object = NULL;
429	RetVal->Next = NULL;
430	RetVal->TerminateFlag = 0;
431#if defined(WIN32) || defined(_WIN32_WCE)
432	RetVal->Terminate = socket(AF_INET, SOCK_DGRAM, 0);
433#endif
434
435	if(ILibChainLock_RefCounter==0)
436	{
437		sem_init(&ILibChainLock,0,1);
438	}
439	return(RetVal);
440}
441*/
442/*! \fn ILibAddToChain(void *Chain, void *object)
443	\brief Add links to the chain
444	\para
445	\b Note: All objects added to the chain must extend/implement ILibChain
446	\param Chain The chain to add the link to
447	\param object The link to add to the chain
448*/
449/*
450void ILibAddToChain(void *Chain, void *object)
451{
452	struct ILibBaseChain *chain = (struct ILibBaseChain*)Chain;
453
454	//
455	// Add link to the end of the chain (Linked List)
456	//
457	while(chain->Next!=NULL)
458	{
459		chain = chain->Next;
460	}
461	if(chain->Object!=NULL)
462	{
463		chain->Next = (struct ILibBaseChain*)malloc(sizeof(struct ILibBaseChain));
464		chain = chain->Next;
465	}
466	chain->Object = object;
467	chain->Next = NULL;
468}
469*/
470/*! \fn ILibForceUnBlockChain(void *Chain)
471	\brief Forces a Chain to unblock, and check for pending operations
472	\param Chain The chain to unblock
473*/
474/*
475void ILibForceUnBlockChain(void *Chain)
476{
477	struct ILibBaseChain *c = (struct ILibBaseChain*)Chain;
478
479#if defined(WIN32) || defined(_WIN32_WCE)
480	SOCKET temp;
481#endif
482	sem_wait(&ILibChainLock);
483
484#if defined(WIN32) || defined(_WIN32_WCE)
485	//
486	// Closing the socket will trigger the select on Windows
487	//
488	temp = c->Terminate;
489	c->Terminate = ~0;
490	closesocket(temp);
491#else
492	//
493	// Writing data on the pipe will trigger the select on Posix
494	//
495	if(c->TerminateWritePipe!=NULL)
496	{
497		fprintf(c->TerminateWritePipe," ");
498		fflush(c->TerminateWritePipe);
499	}
500#endif
501	sem_post(&ILibChainLock);
502}
503*/
504/*! \fn ILibStartChain(void *Chain)
505	\brief Starts a Chain
506	\para
507	This method will use the current thread. This thread will be refered to as the
508	microstack thread. All events and processing will be done on this thread. This method
509	will not return until ILibStopChain is called.
510	\param Chain The chain to start
511*/
512/*
513void ILibStartChain(void *Chain)
514{
515	struct ILibBaseChain *c = (struct ILibBaseChain*)Chain;
516	struct ILibBaseChain *temp;
517	fd_set readset;
518	fd_set errorset;
519	fd_set writeset;
520	struct timeval tv;
521	int slct;
522	int v;
523#if !defined(WIN32) && !defined(_WIN32_WCE)
524	int TerminatePipe[2];
525	int flags;
526#endif
527
528	//
529	// Use this thread as if it's our own. Keep looping until we are signaled to stop
530	//
531	FD_ZERO(&readset);
532	FD_ZERO(&errorset);
533	FD_ZERO(&writeset);
534
535#if !defined(WIN32) && !defined(_WIN32_WCE)
536	//
537	// For posix, we need to use a pipe to force unblock the select loop
538	//
539	pipe(TerminatePipe);
540	flags = fcntl(TerminatePipe[0],F_GETFL,0);
541	//
542	// We need to set the pipe to nonblock, so we can blindly empty the pipe
543	//
544	fcntl(TerminatePipe[0],F_SETFL,O_NONBLOCK|flags);
545	((struct ILibBaseChain*)Chain)->TerminateReadPipe = fdopen(TerminatePipe[0],"r");
546	((struct ILibBaseChain*)Chain)->TerminateWritePipe = fdopen(TerminatePipe[1],"w");
547#endif
548
549	while(((struct ILibBaseChain*)Chain)->TerminateFlag==0)
550	{
551		slct = 0;
552		FD_ZERO(&readset);
553		FD_ZERO(&errorset);
554		FD_ZERO(&writeset);
555		tv.tv_sec = UPNP_MAX_WAIT;
556		tv.tv_usec = 0;
557
558		sem_wait(&ILibChainLock);
559#if defined(WIN32) || defined(_WIN32_WCE)
560		//
561		// Check the fake socket, for ILibForceUnBlockChain
562		//
563		if(((struct ILibBaseChain*)Chain)->Terminate==~0)
564		{
565			slct = -1;
566		}
567		else
568		{
569			FD_SET(((struct ILibBaseChain*)Chain)->Terminate,&errorset);
570		}
571#else
572		//
573		// Put the Read end of the Pipe in the FDSET, for ILibForceUnBlockChain
574		//
575		FD_SET(TerminatePipe[0],&readset);
576#endif
577		sem_post(&ILibChainLock);
578
579		//
580		// Iterate through all the PreSelect function pointers in the chain
581		//
582		c = (struct ILibBaseChain*)Chain;
583		while(c!=NULL && c->Object!=NULL)
584		{
585			if(((struct ILibChain*)c->Object)->PreSelect!=NULL)
586			{
587#ifdef MEMORY_CHECK
588#ifdef WIN32
589				_CrtCheckMemory();
590#endif
591#endif
592				v = (tv.tv_sec*1000) + (tv.tv_usec/1000);
593				((struct ILibChain*)c->Object)->PreSelect(c->Object,&readset,&writeset,&errorset,&v);
594				tv.tv_sec = v/1000;
595				tv.tv_usec = 1000*(v%1000);
596
597#ifdef MEMORY_CHECK
598#ifdef WIN32
599				_CrtCheckMemory();
600#endif
601#endif
602			}
603			c = c->Next;
604		}
605		//
606		// If this flag is set, force the max block time to be zero
607		//
608		if(slct!=0)
609		{
610			tv.tv_sec = 0;
611			tv.tv_usec = 0;
612		}
613
614		//
615		// The actual Select Statement
616		//
617		slct = select(FD_SETSIZE,&readset,&writeset,&errorset,&tv);
618		if(slct==-1)
619		{
620			//
621			// If the select simply timed out, we need to clear these sets
622			//
623			FD_ZERO(&readset);
624			FD_ZERO(&writeset);
625			FD_ZERO(&errorset);
626		}
627
628#if defined(WIN32) || defined(_WIN32_WCE)
629		//
630		// Reinitialise our fake socket if necessary
631		//
632		if(((struct ILibBaseChain*)Chain)->Terminate==~0)
633		{
634			((struct ILibBaseChain*)Chain)->Terminate = socket(AF_INET,SOCK_DGRAM,0);
635		}
636#else
637		if(FD_ISSET(TerminatePipe[0],&readset))
638		{
639			//
640			// Empty the pipe
641			//
642			while(fgetc(((struct ILibBaseChain*)Chain)->TerminateReadPipe)!=EOF)
643			{
644			}
645		}
646#endif
647		//
648		// Iterate through all of the PostSelect in the chain
649		//
650		c = (struct ILibBaseChain*)Chain;
651		while(c!=NULL && c->Object!=NULL)
652		{
653			if(((struct ILibChain*)c->Object)->PostSelect!=NULL)
654			{
655#ifdef MEMORY_CHECK
656#ifdef WIN32
657				_CrtCheckMemory();
658#endif
659#endif
660				((struct ILibChain*)c->Object)->PostSelect(c->Object,slct,&readset,&writeset,&errorset);
661#ifdef MEMORY_CHECK
662#ifdef WIN32
663				_CrtCheckMemory();
664#endif
665#endif
666			}
667			c = c->Next;
668		}
669	}
670
671	//
672	// This loop will start, when the Chain was signaled to quit. Clean up the chain
673	// by iterating through all the Destroy.
674	//
675	c = (struct ILibBaseChain*)Chain;
676	while(c!=NULL && c->Object!=NULL)
677	{
678		if(((struct ILibChain*)c->Object)->Destroy!=NULL)
679		{
680			((struct ILibChain*)c->Object)->Destroy(c->Object);
681		}
682		//
683		// After calling the Destroy, we free the link
684		//
685		free(c->Object);
686		c = c->Next;
687	}
688
689	//
690	// Now we actually free the chain
691	//
692	c = (struct ILibBaseChain*)Chain;
693#if !defined(WIN32) && !defined(_WIN32_WCE)
694	//
695	// Free the pipe resources
696	//
697	fclose(c->TerminateReadPipe);
698	fclose(c->TerminateWritePipe);
699#endif
700	while(c!=NULL)
701	{
702		temp = c->Next;
703		free(c);
704		c = temp;
705	}
706#ifdef WIN32
707	WSACleanup();
708#endif
709	if(ILibChainLock_RefCounter==1)
710	{
711		sem_destroy(&ILibChainLock);
712	}
713	--ILibChainLock_RefCounter;
714}
715*/
716/*! \fn ILibStopChain(void *Chain)
717	\brief Stops a chain
718	\para
719	This will signal the microstack thread to shutdown. When the chain cleans itself up,
720	the thread that is blocked on ILibStartChain will return.
721	\param Chain The Chain to stop
722*/
723/*
724void ILibStopChain(void *Chain)
725{
726	((struct ILibBaseChain*)Chain)->TerminateFlag = 1;
727	ILibForceUnBlockChain(Chain);
728}
729*/
730
731/*! \fn ILibDestructXMLNodeList(struct ILibXMLNode *node)
732	\brief Frees resources from an XMLNodeList tree that was returned from ILibParseXML
733	\param node The XML Tree to clean up
734*/
735
736void ILibDestructXMLNodeList(struct ILibXMLNode *node)
737{
738	struct ILibXMLNode *temp;
739	while(node!=NULL)
740	{
741		temp = node->Next;
742/*
743		if(node->Reserved2!=NULL)
744		{
745			// If there was a namespace table, delete it
746			ILibDestroyHashTree(node->Reserved2);
747		}
748*/
749		free(node);
750		node = temp;
751	}
752}
753
754/*! \fn ILibDestructXMLAttributeList(struct ILibXMLAttribute *attribute)
755	\brief Frees resources from an AttributeList that was returned from ILibGetXMLAttributes
756	\param attribute The Attribute Tree to clean up
757*/
758/*
759void ILibDestructXMLAttributeList(struct ILibXMLAttribute *attribute)
760{
761	struct ILibXMLAttribute *temp;
762	while(attribute!=NULL)
763	{
764		temp = attribute->Next;
765		free(attribute);
766		attribute = temp;
767	}
768}
769*/
770/*! \fn ILibProcessXMLNodeList(struct ILibXMLNode *nodeList)
771	\brief Pro-process an XML node list
772	\para
773	Checks XML for validity, while at the same time populate helper properties on each node,
774	such as Parent, Peer, etc, to aid in XML parsing.
775	\param nodeList The XML Tree to process
776	\returns 0 if the XML is valid, nonzero otherwise
777*/
778
779int ILibProcessXMLNodeList(struct ILibXMLNode *nodeList)
780{
781	int RetVal = 0;
782	struct ILibXMLNode *current = nodeList;
783	struct ILibXMLNode *temp;
784	void *TagStack;
785
786	ILibCreateStack(&TagStack);
787
788	//
789	// Iterate through the node list, and setup all the pointers
790	// such that all StartElements have pointers to EndElements,
791	// And all StartElements have pointers to siblings and parents.
792	//
793	while(current!=NULL)
794	{
795		if(memcmp(current->Name,"!",1)==0)
796		{
797			// Comment
798			temp = current;
799			current = (struct ILibXMLNode*)ILibPeekStack(&TagStack);
800			if(current!=NULL)
801			{
802				current->Next = temp->Next;
803			}
804			else
805			{
806				current = temp;
807			}
808		}
809		else if(current->StartTag!=0)
810		{
811			// Start Tag
812			current->Parent = ILibPeekStack(&TagStack);
813			ILibPushStack(&TagStack,current);
814		}
815		else
816		{
817			// Close Tag
818
819			//
820			// Check to see if there is supposed to be an EndElement
821			//
822			temp = (struct ILibXMLNode*)ILibPopStack(&TagStack);
823			if(temp!=NULL)
824			{
825				//
826				// Checking to see if this EndElement is correct in scope
827				//
828				if(temp->NameLength==current->NameLength && memcmp(temp->Name,current->Name,current->NameLength)==0)
829				{
830					//
831					// Now that we know this EndElement is correct, set the Peer
832					// pointers of the previous sibling
833					//
834					if(current->Next!=NULL)
835					{
836						if(current->Next->StartTag!=0)
837						{
838							temp->Peer = current->Next;
839						}
840					}
841					temp->ClosingTag = current;
842					current->StartingTag = temp;
843				}
844				else
845				{
846					// Illegal Close Tag Order
847					RetVal = -2;
848					break;
849				}
850			}
851			else
852			{
853				// Illegal Close Tag
854				RetVal = -1;
855				break;
856			}
857		}
858		current = current->Next;
859	}
860
861	//
862	// If there are still elements in the stack, that means not all the StartElements
863	// have associated EndElements, which means this XML is not valid XML.
864	//
865	if(TagStack!=NULL)
866	{
867		// Incomplete XML
868		RetVal = -3;
869		ILibClearStack(&TagStack);
870	}
871
872	return(RetVal);
873}
874
875/*! \fn ILibXML_LookupNamespace(struct ILibXMLNode *currentLocation, char *prefix, int prefixLength)
876	\brief Resolves a namespace prefix from the scope of the given node
877	\param currentLocation The node used to start the resolve
878	\param prefix The namespace prefix to resolve
879	\param prefixLength The lenght of the prefix
880	\returns The resolved namespace. NULL if unable to resolve
881*/
882/*
883char* ILibXML_LookupNamespace(struct ILibXMLNode *currentLocation, char *prefix, int prefixLength)
884{
885	struct ILibXMLNode *temp = currentLocation;
886	int done=0;
887	char* RetVal = "";
888
889	//
890	// If the specified Prefix is zero length, we interpret that to mean
891	// they want to lookup the default namespace
892	//
893	if(prefixLength==0)
894	{
895		//
896		// This is the default namespace prefix
897		//
898		prefix = "xmlns";
899		prefixLength = 5;
900	}
901
902
903	//
904	// From the current node, keep traversing up the parents, until we find a match.
905	// Each step we go up, is a step wider in scope.
906	//
907	do
908	{
909		if(temp->Reserved2!=NULL)
910		{
911			if(ILibHasEntry(temp->Reserved2,prefix,prefixLength)!=0)
912			{
913				//
914				// As soon as we find the namespace declaration, stop
915				// iterating the tree, as it would be a waste of time
916				//
917				RetVal = (char*)ILibGetEntry(temp->Reserved2,prefix,prefixLength);
918				done=1;
919			}
920		}
921		temp = temp->Parent;
922	}while(temp!=NULL && done==0);
923	return(RetVal);
924}
925*/
926/*! \fn ILibXML_BuildNamespaceLookupTable(struct ILibXMLNode *node)
927	\brief Builds the lookup table used by ILibXML_LookupNamespace
928	\param node This node will be the highest scoped
929*/
930/*
931void ILibXML_BuildNamespaceLookupTable(struct ILibXMLNode *node)
932{
933	struct ILibXMLAttribute *attr,*currentAttr;
934	struct ILibXMLNode *current = node;
935
936	//
937	// Iterate through all the StartElements, and build a table of the declared namespaces
938	//
939	while(current!=NULL)
940	{
941		if(current->StartTag!=0)
942		{
943			//
944			// Reserved2 is the HashTable containing the fully qualified namespace
945			// keyed by the namespace prefix
946			//
947			current->Reserved2 = ILibInitHashTree();
948			currentAttr = attr = ILibGetXMLAttributes(current);
949			if(attr!=NULL)
950			{
951				//
952				// Iterate through all the attributes to find namespace declarations
953				//
954				while(currentAttr!=NULL)
955				{
956					if(currentAttr->NameLength==5 && memcmp(currentAttr->Name,"xmlns",5)==0)
957					{
958						// Default Namespace Declaration
959						currentAttr->Value[currentAttr->ValueLength]=0;
960						ILibAddEntry(current->Reserved2,"xmlns",5,currentAttr->Value);
961					}
962					else if(currentAttr->PrefixLength==5 && memcmp(currentAttr->Prefix,"xmlns",5)==0)
963					{
964						// Other Namespace Declaration
965						currentAttr->Value[currentAttr->ValueLength]=0;
966						ILibAddEntry(current->Reserved2,currentAttr->Name,currentAttr->NameLength,currentAttr->Value);
967					}
968					currentAttr=currentAttr->Next;
969				}
970				ILibDestructXMLAttributeList(attr);
971			}
972		}
973		current = current->Next;
974	}
975}
976*/
977
978/*! \fn ILibReadInnerXML(struct ILibXMLNode *node, char **RetVal)
979	\brief Reads the data segment from an ILibXMLNode
980	\para
981	The data is a pointer into the original string that the XML was read from.
982	\param node The node to read the data from
983	\param RetVal The data
984	\returns The length of the data read
985*/
986int ILibReadInnerXML(struct ILibXMLNode *node, char **RetVal)
987{
988	struct ILibXMLNode *x = node;
989	int length = 0;
990	void *TagStack;
991	*RetVal = NULL;
992
993	//
994	// Starting with the current StartElement, we use this stack to find the matching
995	// EndElement, so we can figure out what we need to return
996	//
997	ILibCreateStack(&TagStack);
998	do
999	{
1000		if(x->StartTag!=0) {ILibPushStack(&TagStack,x);}
1001		if(x!=NULL)
1002		{
1003			x = x->Next;
1004		}
1005		else
1006		{
1007			return(0);
1008		}
1009	}while(!(x->StartTag==0 && ILibPopStack(&TagStack)==node && x->NameLength==node->NameLength && memcmp(x->Name,node->Name,node->NameLength)==0));
1010
1011	//
1012	// The Reserved fields of the StartElement and EndElement are used as pointers representing
1013	// the data segment of the XML
1014	//
1015	length = (int)((char*)x->Reserved - (char*)node->Reserved - 1);
1016	if(length<0) {length=0;}
1017	*RetVal = (char*)node->Reserved;
1018	return(length);
1019}
1020
1021/*! \fn ILibGetXMLAttributes(struct ILibXMLNode *node)
1022	\breif Reads the attributes from an XML node
1023	\param node The node to read the attributes from
1024	\returns A linked list of attributes
1025*/
1026/*
1027struct ILibXMLAttribute *ILibGetXMLAttributes(struct ILibXMLNode *node)
1028{
1029	struct ILibXMLAttribute *RetVal = NULL;
1030	struct ILibXMLAttribute *current = NULL;
1031	char *c;
1032	int EndReserved = (node->EmptyTag==0)?1:2;
1033	int i;
1034	int CheckName = node->Name[node->NameLength]==0?1:0;
1035
1036	struct parser_result *xml;
1037	struct parser_result_field *field,*field2;
1038	struct parser_result *temp2;
1039	struct parser_result *temp3;
1040
1041
1042	//
1043	// The reserved field is used to show where the data segments start and stop. We
1044	// can also use them to figure out where the attributes start and stop
1045	//
1046	c = (char*)node->Reserved - 1;
1047	while(*c!='<')
1048	{
1049		//
1050		// The Reserved field of the StartElement points to the first character after
1051		// the '>' of the StartElement. Just work our way backwards to find the start of
1052		// the StartElement
1053		//
1054		c = c -1;
1055	}
1056	c = c +1;
1057
1058	//
1059	// Now that we isolated the string in between the '<' and the '>' we can parse the
1060	// string as delimited by ' ', because thats what delineates attributes. We need
1061	// to use ILibParseStringAdv because these attributes can be within quotation marks
1062	//
1063	//
1064	// But before we start, replace linefeeds and carriage-return-linefeeds to spaces
1065	//
1066	for(i=0;i<(int)((char*)node->Reserved - c -EndReserved);++i)
1067	{
1068		if(c[i]==10 || c[i]==13 || c[i]==9 || c[i]==0)
1069		{
1070			c[i]=' ';
1071		}
1072	}
1073	xml = ILibParseStringAdv(c,0,(int)((char*)node->Reserved - c -EndReserved)," ",1);
1074	field = xml->FirstResult;
1075	//
1076	// We skip the first token, because the first token, is the Element name
1077	//
1078	if(field!=NULL) {field = field->NextResult;}
1079
1080	//
1081	// Iterate through all the other tokens, as these are all attributes
1082	//
1083	while(field!=NULL)
1084	{
1085		if(field->datalength>0)
1086		{
1087			if(RetVal==NULL)
1088			{
1089				//
1090				// If we haven't already created an Attribute node, create it now
1091				//
1092				RetVal = (struct ILibXMLAttribute*)malloc(sizeof(struct ILibXMLAttribute));
1093				RetVal->Next = NULL;
1094			}
1095			else
1096			{
1097				//
1098				// We already created an Attribute node, so simply create a new one, and
1099				// attach it on the beginning of the old one.
1100				//
1101				current = (struct ILibXMLAttribute*)malloc(sizeof(struct ILibXMLAttribute));
1102				current->Next = RetVal;
1103				RetVal = current;
1104			}
1105
1106			//
1107			// Parse each token by the ':'
1108			// If this results in more than one token, we can figure that the first token
1109			// is the namespace prefix
1110			//
1111			temp2 = ILibParseStringAdv(field->data,0,field->datalength,":",1);
1112			if(temp2->NumResults==1)
1113			{
1114				//
1115				// This attribute has no prefix, so just parse on the '='
1116				// The first token is the attribute name, the other is the value
1117				//
1118				RetVal->Prefix = NULL;
1119				RetVal->PrefixLength = 0;
1120				temp3 = ILibParseStringAdv(field->data,0,field->datalength,"=",1);
1121				if(temp3->NumResults==1)
1122				{
1123					//
1124					// There were whitespaces around the '='
1125					//
1126					field2 = field->NextResult;
1127					while(field2!=NULL)
1128					{
1129						if(!(field2->datalength==1 && memcmp(field2->data,"=",1)==0) && field2->datalength>0)
1130						{
1131							ILibDestructParserResults(temp3);
1132							temp3 = ILibParseStringAdv(field->data,0,(int)((field2->data-field->data)+field2->datalength),"=",1);
1133							field = field2;
1134							break;
1135						}
1136						field2 = field2->NextResult;
1137					}
1138				}
1139			}
1140			else
1141			{
1142				//
1143				// Since there is a namespace prefix, seperate that out, and parse the remainder
1144				// on the '=' to figure out what the attribute name and value are
1145				//
1146				RetVal->Prefix = temp2->FirstResult->data;
1147				RetVal->PrefixLength = temp2->FirstResult->datalength;
1148				temp3 = ILibParseStringAdv(field->data,RetVal->PrefixLength+1,field->datalength-RetVal->PrefixLength-1,"=",1);
1149				if(temp3->NumResults==1)
1150				{
1151					//
1152					// There were whitespaces around the '='
1153					//
1154					field2 = field->NextResult;
1155					while(field2!=NULL)
1156					{
1157						if(!(field2->datalength==1 && memcmp(field2->data,"=",1)==0) && field2->datalength>0)
1158						{
1159							ILibDestructParserResults(temp3);
1160							temp3 = ILibParseStringAdv(field->data,RetVal->PrefixLength+1,(int)((field2->data-field->data)+field2->datalength-RetVal->PrefixLength-1),"=",1);
1161							field = field2;
1162							break;
1163						}
1164						field2 = field2->NextResult;
1165					}
1166				}
1167			}
1168			//
1169			// After attaching the pointers, we can free the results, as all the data
1170			// is a pointer into the original string. We can think of the nodes we created
1171			// as templates. Once done, we don't need them anymore.
1172			//
1173			ILibDestructParserResults(temp2);
1174			RetVal->Parent = node;
1175			RetVal->Name = temp3->FirstResult->data;
1176			RetVal->Value = temp3->LastResult->data;
1177			RetVal->NameLength = ILibTrimString(&(RetVal->Name),temp3->FirstResult->datalength);
1178			RetVal->ValueLength = ILibTrimString(&(RetVal->Value),temp3->LastResult->datalength);
1179			//
1180			// Remove the Quote or Apostraphe if it exists
1181			//
1182			if(RetVal->ValueLength>=2 && (RetVal->Value[0]=='"' || RetVal->Value[0]=='\''))
1183			{
1184				RetVal->Value += 1;
1185				RetVal->ValueLength -= 2;
1186			}
1187			ILibDestructParserResults(temp3);
1188		}
1189		field = field->NextResult;
1190	}
1191
1192	ILibDestructParserResults(xml);
1193	if(CheckName)
1194	{
1195		node->Name[node->NameLength]=0;
1196	}
1197	return(RetVal);
1198}
1199*/
1200
1201/*! \fn ILibParseXML(char *buffer, int offset, int length)
1202	\brief Parses an XML string.
1203	\para
1204	The strings are never copied. Everything is referenced via pointers into the original buffer
1205	\param buffer The string to parse
1206	\param offset starting index of \a buffer
1207	\param length Length of \a buffer
1208	\returns A tree of ILibXMLNodes, representing the XML document
1209*/
1210struct ILibXMLNode *ILibParseXML(char *buffer, int offset, int length)
1211{
1212	struct parser_result *xml;
1213	struct parser_result_field *field;
1214	struct parser_result *temp;
1215	struct parser_result *temp2;
1216	struct parser_result *temp3;
1217	char* TagName;
1218	int TagNameLength;
1219	int StartTag;
1220	int EmptyTag;
1221	int i;
1222
1223	struct ILibXMLNode *RetVal = NULL;
1224	struct ILibXMLNode *current = NULL;
1225	struct ILibXMLNode *x = NULL;
1226
1227	char *NSTag;
1228	int NSTagLength;
1229
1230	//
1231	// Even though "technically" the first character of an XML document must be <
1232	// we're going to be nice, and not enforce that
1233	//
1234	while(buffer[offset]!='<' && length>0)
1235	{
1236		++offset;
1237		--length;
1238	}
1239
1240	if(length==0)
1241	{
1242		// Garbage in Garbage out :)
1243		RetVal = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode));
1244		memset(RetVal,0,sizeof(struct ILibXMLNode));
1245		return(RetVal);
1246	}
1247
1248	//
1249	// All XML Elements start with a '<' character. If we delineate the string with
1250	// this character, we can go from there.
1251	//
1252	xml = ILibParseString(buffer,offset,length,"<",1);
1253	field = xml->FirstResult;
1254	while(field!=NULL)
1255	{
1256		//
1257		// Ignore the XML declarator
1258		//
1259		if(field->datalength !=0 && memcmp(field->data,"?",1)!=0)
1260		{
1261			EmptyTag = 0;
1262			if(memcmp(field->data,"/",1)==0)
1263			{
1264				//
1265				// The first character after the '<' was a '/', so we know this is the
1266				// EndElement
1267				//
1268				StartTag = 0;
1269				field->data = field->data+1;
1270				field->datalength -= 1;
1271				//
1272				// If we look for the '>' we can find the end of this element
1273				//
1274				temp2 = ILibParseString(field->data,0,field->datalength,">",1);
1275			}
1276			else
1277			{
1278				//
1279				// The first character after the '<' was not a '/' so we know this is a
1280				// StartElement
1281				//
1282				StartTag = -1;
1283				//
1284				// If we look for the '>' we can find the end of this element
1285				//
1286				temp2 = ILibParseString(field->data,0,field->datalength,">",1);
1287				if(temp2->FirstResult->datalength>0 && temp2->FirstResult->data[temp2->FirstResult->datalength-1]=='/')
1288				{
1289					//
1290					// If this element ended with a '/' this is an EmptyElement
1291					//
1292					EmptyTag = -1;
1293				}
1294			}
1295			//
1296			// Parsing on the ' ', we can isolate the Element name from the attributes.
1297			// The first token, being the element name
1298			//
1299			temp = ILibParseString(temp2->FirstResult->data,0,temp2->FirstResult->datalength," ",1);
1300			//
1301			// Now that we have the token that contains the element name, we need to parse on the ":"
1302			// because we need to figure out what the namespace qualifiers are
1303			//
1304			temp3 = ILibParseString(temp->FirstResult->data,0,temp->FirstResult->datalength,":",1);
1305			if(temp3->NumResults==1)
1306			{
1307				//
1308				// If there is only one token, there was no namespace prefix.
1309				// The whole token is the attribute name
1310				//
1311				NSTag = NULL;
1312				NSTagLength = 0;
1313				TagName = temp3->FirstResult->data;
1314				TagNameLength = temp3->FirstResult->datalength;
1315			}
1316			else
1317			{
1318				//
1319				// The first token is the namespace prefix, the second is the attribute name
1320				//
1321				NSTag = temp3->FirstResult->data;
1322				NSTagLength = temp3->FirstResult->datalength;
1323				TagName = temp3->FirstResult->NextResult->data;
1324				TagNameLength = temp3->FirstResult->NextResult->datalength;
1325			}
1326			ILibDestructParserResults(temp3);
1327
1328			//
1329			// Iterate through the tag name, to figure out what the exact length is, as
1330			// well as check to see if its an empty element
1331			//
1332			for(i=0;i<TagNameLength;++i)
1333			{
1334				if( (TagName[i]==' ')||(TagName[i]=='/')||(TagName[i]=='>')||(TagName[i]=='\t')||(TagName[i]=='\r')||(TagName[i]=='\n') )
1335				{
1336					if(i!=0)
1337					{
1338						if(TagName[i]=='/')
1339						{
1340							EmptyTag = -1;
1341						}
1342						TagNameLength = i;
1343						break;
1344					}
1345				}
1346			}
1347
1348			if(TagNameLength!=0)
1349			{
1350				//
1351				// Instantiate a new ILibXMLNode for this element
1352				//
1353				x = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode));
1354				memset(x,0,sizeof(struct ILibXMLNode));
1355				x->Name = TagName;
1356				x->NameLength = TagNameLength;
1357				x->StartTag = StartTag;
1358				x->NSTag = NSTag;
1359				x->NSLength = NSTagLength;
1360
1361				if(StartTag==0)
1362				{
1363					//
1364					// The Reserved field of StartElements point to te first character before
1365					// the '<'.
1366					//
1367					x->Reserved = field->data;
1368					do
1369					{
1370						(char*)x->Reserved -= 1;
1371					}while(*((char*)x->Reserved)=='<');
1372				}
1373				else
1374				{
1375					//
1376					// The Reserved field of EndElements point to the end of the element
1377					//
1378					x->Reserved = temp2->LastResult->data;
1379				}
1380
1381				if(RetVal==NULL)
1382				{
1383					RetVal = x;
1384				}
1385				else
1386				{
1387					current->Next = x;
1388				}
1389				current = x;
1390				if(EmptyTag!=0)
1391				{
1392					//
1393					// If this was an empty element, we need to create a bogus EndElement,
1394					// just so the tree is consistent. No point in introducing unnecessary complexity
1395					//
1396					x = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode));
1397					memset(x,0,sizeof(struct ILibXMLNode));
1398					x->Name = TagName;
1399					x->NameLength = TagNameLength;
1400					x->NSTag = NSTag;
1401					x->NSLength = NSTagLength;
1402
1403					x->Reserved = current->Reserved;
1404					current->EmptyTag = -1;
1405					current->Next = x;
1406					current = x;
1407				}
1408			}
1409
1410			ILibDestructParserResults(temp2);
1411			ILibDestructParserResults(temp);
1412		}
1413		field = field->NextResult;
1414	}
1415
1416	ILibDestructParserResults(xml);
1417	return(RetVal);
1418}
1419
1420/*! \fn ILibQueue_Create()
1421	\brief Create an empty Queue
1422	\returns An empty queue
1423*/
1424/*
1425void *ILibQueue_Create()
1426{
1427	return(ILibLinkedList_Create());
1428}
1429*/
1430
1431/*! \fn ILibQueue_Lock(void *q)
1432	\brief Locks a queue
1433	\param q The queue to lock
1434*/
1435/*
1436void ILibQueue_Lock(void *q)
1437{
1438	ILibLinkedList_Lock(q);
1439}
1440*/
1441
1442/*! \fn ILibQueue_UnLock(void *q)
1443	\brief Unlocks a queue
1444	\param q The queue to unlock
1445*/
1446/*
1447void ILibQueue_UnLock(void *q)
1448{
1449	ILibLinkedList_UnLock(q);
1450}
1451*/
1452/*! \fn ILibQueue_Destroy(void *q)
1453	\brief Frees the resources associated with a queue
1454	\param q The queue to free
1455*/
1456/*
1457void ILibQueue_Destroy(void *q)
1458{
1459	ILibLinkedList_Destroy(q);
1460}
1461*/
1462/*! \fn ILibQueue_IsEmpty(void *q)
1463	\brief Checks to see if a queue is empty
1464	\param q The queue to check
1465	\returns zero value if not empty, non-zero if empty
1466*/
1467/*
1468int ILibQueue_IsEmpty(void *q)
1469{
1470	return(ILibLinkedList_GetNode_Head(q)==NULL?1:0);
1471}
1472*/
1473/*! \fn ILibQueue_EnQueue(void *q, void *data)
1474	\brief Add an item to the queue
1475	\param q The queue to add to
1476	\param data The data to add to the queue
1477*/
1478/*
1479void ILibQueue_EnQueue(void *q, void *data)
1480{
1481	ILibLinkedList_AddTail(q,data);
1482}
1483*/
1484/*! \fn ILibQueue_DeQueue(void *q)
1485	\brief Removes an item from the queue
1486	\param q The queue to pop the item from
1487	\returns The item popped off the queue. NULL if empty
1488*/
1489/*
1490void *ILibQueue_DeQueue(void *q)
1491{
1492	void *RetVal = NULL;
1493	void *node;
1494
1495	node = ILibLinkedList_GetNode_Head(q);
1496	if(node!=NULL)
1497	{
1498		RetVal = ILibLinkedList_GetDataFromNode(node);
1499		ILibLinkedList_Remove(node);
1500	}
1501	return(RetVal);
1502}
1503*/
1504/*! \fn ILibQueue_PeekQueue(void *q)
1505	\brief Peeks at an item from the queue
1506	\param q The queue to peek an item from
1507	\returns The item from the queue. NULL if empty
1508*/
1509/*
1510void *ILibQueue_PeekQueue(void *q)
1511{
1512	void *RetVal = NULL;
1513	void *node;
1514
1515	node = ILibLinkedList_GetNode_Head(q);
1516	if(node!=NULL)
1517	{
1518		RetVal = ILibLinkedList_GetDataFromNode(node);
1519	}
1520	return(RetVal);
1521}
1522*/
1523/*! \fn ILibCreateStack(void **TheStack)
1524	\brief Creates an empty Stack
1525	\para
1526	This module uses a void* that is preinitialized to NULL, eg:<br>
1527	<i>
1528	void *stack = NULL;<br>
1529	ILibCreateStack(&stack);<br>
1530	</i>
1531	\param TheStack A void* to use for the stack. Simply pass in a void* by reference
1532*/
1533void ILibCreateStack(void **TheStack)
1534{
1535	*TheStack = NULL;
1536}
1537
1538/*! \fn ILibPushStack(void **TheStack, void *data)
1539	\brief Push an item onto the stack
1540	\param TheStack The stack to push to
1541	\param data The data to push onto the stack
1542*/
1543void ILibPushStack(void **TheStack, void *data)
1544{
1545	struct ILibStackNode *RetVal = (struct ILibStackNode*)malloc(sizeof(struct ILibStackNode));
1546	RetVal->Data = data;
1547	RetVal->Next = *TheStack;
1548	*TheStack = RetVal;
1549}
1550
1551/*! \fn ILibPopStack(void **TheStack)
1552	\brief Pop an item from the stack
1553	\param TheStack The stack to pop from
1554	\returns The item that was popped from the stack
1555*/
1556void *ILibPopStack(void **TheStack)
1557{
1558	void *RetVal = NULL;
1559	void *Temp;
1560	if(*TheStack!=NULL)
1561	{
1562		RetVal = ((struct ILibStackNode*)*TheStack)->Data;
1563		Temp = *TheStack;
1564		*TheStack = ((struct ILibStackNode*)*TheStack)->Next;
1565		free(Temp);
1566	}
1567	return(RetVal);
1568}
1569
1570/*! \fn ILibPeekStack(void **TheStack)
1571	\brief Peek at an item from the stack
1572	\param TheStack The stack to peek from
1573	\returns The item that is currently on the top of the stack
1574*/
1575void *ILibPeekStack(void **TheStack)
1576{
1577	void *RetVal = NULL;
1578	if(*TheStack!=NULL)
1579	{
1580		RetVal = ((struct ILibStackNode*)*TheStack)->Data;
1581	}
1582	return(RetVal);
1583}
1584
1585/*! \fn ILibClearStack(void **TheStack)
1586	\brief Clears all the items from the stack
1587	\param TheStack The stack to clear
1588*/
1589void ILibClearStack(void **TheStack)
1590{
1591	void *Temp = *TheStack;
1592	do
1593	{
1594		ILibPopStack(&Temp);
1595	}while(Temp!=NULL);
1596	*TheStack = NULL;
1597}
1598
1599/*! \fn ILibHashTree_Lock(void *hashtree)
1600	\brief Locks a HashTree
1601	\param hashtree The HashTree to lock
1602*/
1603/*
1604void ILibHashTree_Lock(void *hashtree)
1605{
1606	struct HashNode_Root *r = (struct HashNode_Root*)hashtree;
1607	sem_wait(&(r->LOCK));
1608}
1609*/
1610
1611/*! \fn ILibHashTree_UnLock(void *hashtree)
1612	\brief Unlocks a HashTree
1613	\param hashtree The HashTree to unlock
1614*/
1615/*
1616void ILibHashTree_UnLock(void *hashtree)
1617{
1618	struct HashNode_Root *r = (struct HashNode_Root*)hashtree;
1619	sem_post(&(r->LOCK));
1620}
1621*/
1622/*! \fn ILibDestroyHashTree(void *tree)
1623	\brief Frees resources associated with a HashTree
1624	\param hashtree The HashTree to free
1625*/
1626/*
1627void ILibDestroyHashTree(void *tree)
1628{
1629	struct HashNode_Root *r = (struct HashNode_Root*)tree;
1630	struct HashNode *c = r->Root;
1631	struct HashNode *n;
1632
1633	sem_destroy(&(r->LOCK));
1634	while(c!=NULL)
1635	{
1636		//
1637		// Iterate through each node, and free all the resources
1638		//
1639		n = c->Next;
1640		if(c->KeyValue!=NULL) {free(c->KeyValue);}
1641		free(c);
1642		c = n;
1643	}
1644	free(r);
1645}
1646*/
1647/*! \fn ILibHashTree_GetEnumerator(void *tree)
1648	\brief Returns an Enumerator for a HashTree
1649	\para
1650	Functionally identicle to an IDictionaryEnumerator in .NET
1651	\param tree The HashTree to get an enumerator for
1652	\returns An enumerator
1653*/
1654/*
1655void *ILibHashTree_GetEnumerator(void *tree)
1656{
1657	//
1658	// The enumerator is basically a state machine that keeps track of which node we are at
1659	// in the tree. So initialize it to the root.
1660	//
1661	struct HashNodeEnumerator *en = (struct HashNodeEnumerator*)malloc(sizeof(struct HashNodeEnumerator));
1662	en->node = ((struct HashNode_Root*)tree)->Root;
1663	return(en);
1664}
1665*/
1666/*! \fn ILibHashTree_DestroyEnumerator(void *tree_enumerator)
1667	\brief Frees resources associated with an Enumerator created by ILibHashTree_GetEnumerator
1668	\param tree_enumerator The enumerator to free
1669*/
1670/*
1671void ILibHashTree_DestroyEnumerator(void *tree_enumerator)
1672{
1673	//
1674	// The enumerator just contains a pointer, so we can just free the enumerator
1675	//
1676	free(tree_enumerator);
1677}
1678*/
1679/*! \fn ILibHashTree_MoveNext(void *tree_enumerator)
1680	\brief Advances an enumerator to the next item
1681	\param tree_enumerator The enumerator to advance
1682	\returns A zero value if successful, nonzero if no more items
1683*/
1684/*
1685int ILibHashTree_MoveNext(void *tree_enumerator)
1686{
1687	struct HashNodeEnumerator *en = (struct HashNodeEnumerator*)tree_enumerator;
1688	if(en->node!=NULL)
1689	{
1690		//
1691		// Advance the enumerator to point to the next node. If there is a node
1692		// return 0, else return 1
1693		//
1694		en->node = en->node->Next;
1695		return(en->node!=NULL?0:1);
1696	}
1697	else
1698	{
1699		//
1700		// There are no more nodes, so just return 1
1701		//
1702		return(1);
1703	}
1704}
1705*/
1706/*! \fn ILibHashTree_GetValue(void *tree_enumerator, char **key, int *keyLength, void **data)
1707	\brief Reads from the current item of an enumerator
1708	\param tree_enumerator The enumerator to read from
1709	\param key The key of the current item
1710	\param keyLength The length of the key of the current item
1711	\param data The data of the current item
1712*/
1713/*
1714void ILibHashTree_GetValue(void *tree_enumerator, char **key, int *keyLength, void **data)
1715{
1716	struct HashNodeEnumerator *en = (struct HashNodeEnumerator*)tree_enumerator;
1717
1718	//
1719	// All we do, is just assign the pointers.
1720	//
1721	if(key!=NULL){*key = en->node->KeyValue;}
1722	if(keyLength!=NULL){*keyLength = en->node->KeyLength;}
1723	if(data!=NULL){*data = en->node->Data;}
1724}
1725*/
1726/*! \fn ILibInitHashTree()
1727	\brief Creates an empty ILibHashTree
1728	\returns An empty ILibHashTree
1729*/
1730/*
1731void* ILibInitHashTree()
1732{
1733	struct HashNode_Root *Root = (struct  HashNode_Root*)malloc(sizeof(struct HashNode_Root));
1734	struct HashNode *RetVal = (struct HashNode*)malloc(sizeof(struct HashNode));
1735	memset(RetVal,0,sizeof(struct HashNode));
1736	Root->Root = RetVal;
1737	sem_init(&(Root->LOCK),0,1);
1738	return(Root);
1739}
1740*/
1741
1742/*! \fn ILibGetHashValue(void *key, int keylength)
1743	\brief Calculates a numeric Hash from a given string
1744	\para
1745	Used by ILibHashTree methods
1746	\param key The string to hash
1747	\param keylength The length of the string to hash
1748	\returns A hash value
1749*/
1750/*
1751int ILibGetHashValue(void *key, int keylength)
1752{
1753	int HashValue=0;
1754	char TempValue[4];
1755
1756	if(keylength<=4)
1757	{
1758		//
1759		// If the key length is <= 4, the hash is just the key expressed as an integer
1760		//
1761		memset(TempValue,0,4);
1762		memcpy(TempValue,key,keylength);
1763		//MEMCHECK(assert(keylength<=4);)
1764
1765		HashValue = *((int*)TempValue);
1766	}
1767	else
1768	{
1769		//
1770		// If the key length is >4, the hash is the first 4 bytes XOR with the last 4
1771		//
1772		memcpy(TempValue,key,4);
1773		HashValue = *((int*)TempValue);
1774		memcpy(TempValue,(char*)key+(keylength-4),4);
1775		HashValue = HashValue^(*((int*)TempValue));
1776		//
1777		// If the key length is >= 10, the hash is also XOR with the middle 4 bytes
1778		//
1779		if(keylength>=10)
1780		{
1781			memcpy(TempValue,(char*)key+(keylength/2),4);
1782			HashValue = HashValue^(*((int*)TempValue));
1783		}
1784	}
1785	return(HashValue);
1786}
1787*/
1788//
1789// Determines if a key entry exists in a HashTree, and creates it if requested
1790//
1791/*
1792struct HashNode* ILibFindEntry(void *hashtree, void *key, int keylength, int create)
1793{
1794	struct HashNode *current = ((struct HashNode_Root*)hashtree)->Root;
1795	int HashValue = ILibGetHashValue(key,keylength);
1796	int done = 0;
1797
1798	if(keylength==0){return(NULL);}
1799
1800	//
1801	// Iterate through our tree to see if we can find this key entry
1802	//
1803	while(done==0)
1804	{
1805		//
1806		// Integer compares are very fast, this will weed out most non-matches
1807		//
1808		if(current->KeyHash==HashValue)
1809		{
1810			//
1811			// Verify this is really a match
1812			//
1813			#ifdef ASUS_UPNP_DEBUG
1814			printf("current->KeyValue=%s\n", current->KeyValue);
1815			#endif
1816			if(current->KeyLength==keylength && memcmp(current->KeyValue,key,keylength)==0)
1817			{
1818				return(current);
1819			}
1820		}
1821
1822		if(current->Next!=NULL)
1823		{
1824			current = current->Next;
1825		}
1826		else if(create!=0)
1827		{
1828			#ifdef ASUS_UPNP_DEBUG
1829			printf("Create an entry: KeyValue=%s\n", (char*)key);
1830			#endif
1831			//
1832			// If there is no match, and the create flag is set, we need to create an entry
1833			//
1834			current->Next = (struct HashNode*)malloc(sizeof(struct HashNode));
1835			memset(current->Next,0,sizeof(struct HashNode));
1836			current->Next->Prev = current;
1837			current->Next->KeyHash = HashValue;
1838			current->Next->KeyValue = (void*)malloc(keylength+1);
1839			memcpy(current->Next->KeyValue,key,keylength);
1840			current->Next->KeyValue[keylength]=0;
1841			current->Next->KeyLength = keylength;
1842			return(current->Next);
1843		}
1844		else
1845		{
1846			return(NULL);
1847		}
1848	}
1849	return(NULL);
1850}
1851*/
1852/*! \fn ILibHasEntry(void *hashtree, char* key, int keylength)
1853	\brief Determines if a key entry exists in a HashTree
1854	\param hashtree The HashTree to operate on
1855	\param key The key
1856	\param keylength The length of the key
1857	\returns 0 if does not exist, nonzero otherwise
1858*/
1859/*
1860int ILibHasEntry(void *hashtree, char* key, int keylength)
1861{
1862	//
1863	// This can be duplicated by calling Find entry, but setting the create flag to false
1864	//
1865	return(ILibFindEntry(hashtree,key,keylength,0)!=NULL?1:0);
1866}
1867*/
1868
1869/*! \fn ILibAddEntry(void* hashtree, char* key, int keylength, void *value)
1870	\brief Adds an item to the HashTree
1871	\param hashtree The HashTree to operate on
1872	\param key The key
1873	\param keylength The length of the key
1874	\param value The data to add into the HashTree
1875*/
1876/*
1877void ILibAddEntry(void* hashtree, char* key, int keylength, void *value)
1878{
1879	//
1880	// This can be duplicated by calling FindEntry, and setting create to true
1881	//
1882	struct HashNode* n = ILibFindEntry(hashtree,key,keylength,1);
1883	n->Data = value;
1884}
1885*/
1886
1887/*! \fn ILibGetEntry(void *hashtree, char* key, int keylength)
1888	\brief Gets an item from a HashTree
1889	\param hashtree The HashTree to operate on
1890	\param key The key
1891	\param keylength The length of the key
1892	\returns The data in the HashTree. NULL if key does not exist
1893*/
1894/*
1895void* ILibGetEntry(void *hashtree, char* key, int keylength)
1896{
1897	//
1898	// This can be duplicated by calling FindEntry and setting create to false.
1899	// If a match is found, just return the data
1900	//
1901	struct HashNode* n = ILibFindEntry(hashtree,key,keylength,0);
1902	if(n==NULL)
1903	{
1904		return(NULL);
1905	}
1906	else
1907	{
1908		return(n->Data);
1909	}
1910}
1911*/
1912/*! \fn ILibDeleteEntry(void *hashtree, char* key, int keylength)
1913	\brief Deletes a keyed item from the HashTree
1914	\param hashtree The HashTree to operate on
1915	\param key The key
1916	\param keylength The length of the key
1917*/
1918/*
1919void ILibDeleteEntry(void *hashtree, char* key, int keylength)
1920{
1921	//
1922	// First find the entry
1923	//
1924	struct HashNode* n = ILibFindEntry(hashtree,key,keylength,0);
1925	if(n!=NULL)
1926	{
1927		//
1928		// Then remove it from the tree
1929		//
1930		n->Prev->Next = n->Next;
1931		if(n->Next!=NULL)
1932		{
1933			n->Next->Prev = n->Prev;
1934		}
1935		free(n->KeyValue);
1936		free(n);
1937	}
1938}
1939*/
1940/*! \fn ILibGetLong(char *TestValue, int TestValueLength, long* NumericValue)
1941	\brief Reads a long value from a string, in a validating fashion
1942	\param TestValue The string to read from
1943	\param TestValueLength The length of the string
1944	\param NumericValue The long value extracted from the string
1945	\returns 0 if succesful, nonzero if there was an error
1946*/
1947/*
1948int ILibGetLong(char *TestValue, int TestValueLength, long* NumericValue)
1949{
1950	char* StopString;
1951	char* TempBuffer2 = (char*)malloc(1+sizeof(char)*19);
1952	char* TempBuffer = (char*)malloc(1+sizeof(char)*TestValueLength);
1953	memcpy(TempBuffer,TestValue,TestValueLength);
1954	TempBuffer[TestValueLength] = '\0';
1955	*NumericValue = strtol(TempBuffer,&StopString,10);
1956	if(*StopString!='\0')
1957	{
1958		//
1959		// If strtol stopped somewhere other than the end, there was an error
1960		//
1961		free(TempBuffer);
1962		free(TempBuffer2);
1963		return(-1);
1964	}
1965	else
1966	{
1967		//
1968		// Now just check errno to see if there was an error reported
1969		//
1970		free(TempBuffer);
1971		free(TempBuffer2);
1972		if(errno!=ERANGE)
1973		{
1974			return(0);
1975		}
1976		else
1977		{
1978			return(-1);
1979		}
1980	}
1981}
1982*/
1983/*! \fn ILibGetULong(char *TestValue, int TestValueLength, long* NumericValue)
1984	\brief Reads an unsigned long value from a string, in a validating fashion
1985	\param TestValue The string to read from
1986	\param TestValueLength The length of the string
1987	\param NumericValue The long value extracted from the string
1988	\returns 0 if succesful, nonzero if there was an error
1989*/
1990/*
1991int ILibGetULong(const char *TestValue, const int TestValueLength, unsigned long* NumericValue){
1992	char* StopString;
1993	char* TempBuffer2 = (char*)malloc(1+sizeof(char)*19);
1994	char* TempBuffer = (char*)malloc(1+sizeof(char)*TestValueLength);
1995	memcpy(TempBuffer,TestValue,TestValueLength);
1996	TempBuffer[TestValueLength] = '\0';
1997	*NumericValue = strtoul(TempBuffer,&StopString,10);
1998	if(*StopString!='\0')
1999	{
2000		free(TempBuffer);
2001		free(TempBuffer2);
2002		return(-1);
2003	}
2004	else
2005	{
2006		free(TempBuffer);
2007		free(TempBuffer2);
2008#ifdef _WIN32_WCE
2009		// Not Supported on PPC
2010		return(0);
2011#else
2012		if(errno!=ERANGE)
2013		{
2014			if(memcmp(TestValue,"-",1)==0)
2015			{
2016				return(-1);
2017			}
2018			return(0);
2019		}
2020		else
2021		{
2022			return(-1);
2023		}
2024#endif
2025	}
2026}
2027*/
2028
2029//
2030// Determines if a buffer offset is a delimiter
2031//
2032int ILibIsDelimiter(char* buffer, int offset, int buffersize, char* Delimiter, int DelimiterLength)
2033{
2034	//
2035	// For simplicity sake, we'll assume a match unless proven otherwise
2036	//
2037	int i=0;
2038	int RetVal = 1;
2039	if(DelimiterLength>buffersize)
2040	{
2041		//
2042		// If the offset plus delimiter length is greater than the buffersize
2043		// There can't possible be a match, so don't bother looking
2044		//
2045		return(0);
2046	}
2047
2048	for(i=0;i<DelimiterLength;++i)
2049	{
2050		if(buffer[offset+i]!=Delimiter[i])
2051		{
2052			//
2053			// Uh oh! Can't possibly be a match now!
2054			//
2055			RetVal = 0;
2056			break;
2057		}
2058	}
2059	return(RetVal);
2060}
2061
2062/*! \fn ILibParseStringAdv(char* buffer, int offset, int length, char* Delimiter, int DelimiterLength)
2063	\brief Parses a string into a linked list of tokens.
2064	\para
2065	Differs from \a ILibParseString, in that this method ignores characters contained within
2066	quotation marks, whereas \a ILibParseString does not.
2067	\param buffer The buffer to parse
2068	\param offset The offset of the buffer to start parsing
2069	\param length The length of the buffer to parse
2070	\param Delimiter The delimiter
2071	\param DelimiterLength The length of the delimiter
2072	\returns A list of tokens
2073*/
2074/*
2075struct parser_result* ILibParseStringAdv(char* buffer, int offset, int length, char* Delimiter, int DelimiterLength)
2076{
2077	struct parser_result* RetVal = (struct parser_result*)malloc(sizeof(struct parser_result));
2078	int i=0;
2079	char* Token = NULL;
2080	int TokenLength = 0;
2081	struct parser_result_field *p_resultfield;
2082	int Ignore = 0;
2083	char StringDelimiter=0;
2084
2085	RetVal->FirstResult = NULL;
2086	RetVal->NumResults = 0;
2087
2088	//
2089	// By default we will always return at least one token, which will be the
2090	// entire string if the delimiter is not found.
2091	//
2092	// Iterate through the string to find delimiters
2093	//
2094	Token = buffer + offset;
2095	for(i=offset;i<(length+offset);++i)
2096	{
2097		if(StringDelimiter==0)
2098		{
2099			if(buffer[i]=='"')
2100			{
2101				//
2102				// Ignore everything inside double quotes
2103				//
2104				StringDelimiter='"';
2105				Ignore=1;
2106			}
2107			else
2108			{
2109				if(buffer[i]=='\'')
2110				{
2111					//
2112					// Ignore everything inside single quotes
2113					//
2114					StringDelimiter='\'';
2115					Ignore=1;
2116				}
2117			}
2118		}
2119		else
2120		{
2121			//
2122			// Once we isolated everything inside double or single quotes, we can get
2123			// on with the real parsing
2124			//
2125			if(buffer[i]==StringDelimiter)
2126			{
2127				Ignore=((Ignore==0)?1:0);
2128			}
2129		}
2130		if(Ignore==0 && ILibIsDelimiter(buffer,i,length,Delimiter,DelimiterLength))
2131		{
2132			//
2133			// We found a delimiter in the string
2134			//
2135			p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field));
2136			p_resultfield->data = Token;
2137			p_resultfield->datalength = TokenLength;
2138			p_resultfield->NextResult = NULL;
2139			if(RetVal->FirstResult != NULL)
2140			{
2141				RetVal->LastResult->NextResult = p_resultfield;
2142				RetVal->LastResult = p_resultfield;
2143			}
2144			else
2145			{
2146				RetVal->FirstResult = p_resultfield;
2147				RetVal->LastResult = p_resultfield;
2148			}
2149
2150			//
2151			// After we populate the values, we advance the token to after the delimiter
2152			// to prep for the next token
2153			//
2154			++RetVal->NumResults;
2155			i = i + DelimiterLength -1;
2156			Token = Token + TokenLength + DelimiterLength;
2157			TokenLength = 0;
2158		}
2159		else
2160		{
2161			//
2162			// No match yet, so just increment this counter
2163			//
2164			++TokenLength;
2165		}
2166	}
2167
2168	//
2169	// Create a result for the last token, since it won't be caught in the above loop
2170	// because if there are no more delimiters, than the entire last portion of the string since the
2171	// last delimiter is the token
2172	//
2173	p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field));
2174	p_resultfield->data = Token;
2175	p_resultfield->datalength = TokenLength;
2176	p_resultfield->NextResult = NULL;
2177	if(RetVal->FirstResult != NULL)
2178	{
2179		RetVal->LastResult->NextResult = p_resultfield;
2180		RetVal->LastResult = p_resultfield;
2181	}
2182	else
2183	{
2184		RetVal->FirstResult = p_resultfield;
2185		RetVal->LastResult = p_resultfield;
2186	}
2187	++RetVal->NumResults;
2188
2189	return(RetVal);
2190}
2191*/
2192/*! \fn ILibTrimString(char **theString, int length)
2193	\brief Trims leading and trailing whitespace characters
2194	\param theString The string to trim
2195	\param length Length of \a theString
2196	\returns Length of the trimmed string
2197*/
2198/*
2199int ILibTrimString(char **theString, int length)
2200{
2201	int i;
2202	int flag1=0,flag2=0;
2203	for(i=0;i<length;++i)
2204	{
2205		if(!flag2 && (*theString)[length-i-1]!=8 && (*theString)[length-i-1]!=32)
2206		{
2207			length -= i;
2208			flag2=1;
2209			if(flag1 && flag2) {break;}
2210		}
2211		if(!flag1 && (*theString)[i]!=8 && (*theString)[i]!=32)
2212		{
2213			*theString = *theString + i;
2214			length -= i;
2215			flag1=1;
2216			if(flag1 && flag2) {break;}
2217		}
2218	}
2219	return(length);
2220}
2221*/
2222/*! \fn ILibParseString(char* buffer, int offset, int length, char* Delimiter, int DelimiterLength)
2223	\brief Parses a string into a linked list of tokens.
2224	\para
2225	Differs from \a ILibParseStringAdv, in that this method does not ignore characters contained within
2226	quotation marks, whereas \a ILibParseStringAdv does.
2227	\param buffer The buffer to parse
2228	\param offset The offset of the buffer to start parsing
2229	\param length The length of the buffer to parse
2230	\param Delimiter The delimiter
2231	\param DelimiterLength The length of the delimiter
2232	\returns A list of tokens
2233*/
2234struct parser_result* ILibParseString(char* buffer, int offset, int length, char* Delimiter, int DelimiterLength)
2235{
2236	struct parser_result* RetVal = (struct parser_result*)malloc(sizeof(struct parser_result));
2237	int i=0;
2238	char* Token = NULL;
2239	int TokenLength = 0;
2240	struct parser_result_field *p_resultfield = NULL;
2241
2242	RetVal->FirstResult = NULL;
2243	RetVal->NumResults = 0;
2244
2245	//
2246	// By default we will always return at least one token, which will be the
2247	// entire string if the delimiter is not found.
2248	//
2249	// Iterate through the string to find delimiters
2250	//
2251	Token = buffer + offset;
2252	for(i=offset;i<length;++i)
2253	{
2254		if(ILibIsDelimiter(buffer,i,length,Delimiter,DelimiterLength))
2255		{
2256			//
2257			// We found a delimiter in the string
2258			//
2259			p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field));
2260			p_resultfield->data = Token;
2261			p_resultfield->datalength = TokenLength;
2262			p_resultfield->NextResult = NULL;
2263			if(RetVal->FirstResult != NULL)
2264			{
2265				RetVal->LastResult->NextResult = p_resultfield;
2266				RetVal->LastResult = p_resultfield;
2267			}
2268			else
2269			{
2270				RetVal->FirstResult = p_resultfield;
2271				RetVal->LastResult = p_resultfield;
2272			}
2273
2274			//
2275			// After we populate the values, we advance the token to after the delimiter
2276			// to prep for the next token
2277			//
2278			++RetVal->NumResults;
2279			i = i + DelimiterLength -1;
2280			Token = Token + TokenLength + DelimiterLength;
2281			TokenLength = 0;
2282		}
2283		else
2284		{
2285			//
2286			// No match yet, so just increment this counter
2287			//
2288			++TokenLength;
2289		}
2290	}
2291
2292	//
2293	// Create a result for the last token, since it won't be caught in the above loop
2294	// because if there are no more delimiters, than the entire last portion of the string since the
2295	// last delimiter is the token
2296	//
2297	p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field));
2298	p_resultfield->data = Token;
2299	p_resultfield->datalength = TokenLength;
2300	p_resultfield->NextResult = NULL;
2301	if(RetVal->FirstResult != NULL)
2302	{
2303		RetVal->LastResult->NextResult = p_resultfield;
2304		RetVal->LastResult = p_resultfield;
2305	}
2306	else
2307	{
2308		RetVal->FirstResult = p_resultfield;
2309		RetVal->LastResult = p_resultfield;
2310	}
2311	++RetVal->NumResults;
2312
2313	return(RetVal);
2314}
2315
2316/*! \fn ILibDestructParserResults(struct parser_result *result)
2317	\brief Frees resources associated with the list of tokens returned from ILibParseString and ILibParseStringAdv.
2318	\param result The list of tokens to free
2319*/
2320void ILibDestructParserResults(struct parser_result *result)
2321{
2322	//
2323	// All of these nodes only contain pointers
2324	// so we just need to iterate through all the nodes and free them
2325	//
2326	struct parser_result_field *node = result->FirstResult;
2327	struct parser_result_field *temp = NULL;
2328
2329	while(node!=NULL)
2330	{
2331		temp = node->NextResult;
2332		free(node);
2333		node = temp;
2334	}
2335	free(result);
2336}
2337
2338/*! \fn ILibDestructPacket(struct packetheader *packet)
2339	\brief Frees resources associated with a Packet that was created either by \a ILibCreateEmptyPacket or \a ILibParsePacket
2340	\param packet The packet to free
2341*/
2342/*
2343void ILibDestructPacket(struct packetheader *packet)
2344{
2345	struct packetheader_field_node *node = packet->FirstField;
2346	struct packetheader_field_node *nextnode;
2347
2348	//
2349	// Iterate through all the headers
2350	//
2351	while(node!=NULL)
2352	{
2353		nextnode = node->NextField;
2354		if(node->UserAllocStrings!=0)
2355		{
2356			//
2357			// If the user allocated the string, then we need to free it.
2358			// Otherwise these are just pointers into others strings, in which
2359			// case we don't want to free them
2360			//
2361			free(node->Field);
2362			free(node->FieldData);
2363		}
2364		free(node);
2365		node = nextnode;
2366	}
2367	if(packet->UserAllocStrings!=0)
2368	{
2369		//
2370		// If this flag was set, it means the used ILibCreateEmptyPacket,
2371		// and set these fields manually, which means the string was copied.
2372		// In which case, we need to free the strings
2373		//
2374		if(packet->StatusData!=NULL) {free(packet->StatusData);}
2375		if(packet->Directive!=NULL) {free(packet->Directive);}
2376		if(packet->Reserved==NULL && packet->DirectiveObj!=NULL) {free(packet->DirectiveObj);}
2377		if(packet->Reserved!=NULL) {free(packet->Reserved);}
2378		if(packet->Body!=NULL) free(packet->Body);
2379	}
2380	if(packet->UserAllocVersion!=0)
2381	{
2382		free(packet->Version);
2383	}
2384	free(packet);
2385}
2386*/
2387/*! \fn ILibHTTPEscape(char* outdata, const char* data)
2388	\brief Escapes a string according to HTTP Specifications.
2389	\para
2390	The string you would want to escape would typically be the string used in the Path portion
2391	of an HTTP request. eg:<br>
2392	GET foo/bar.txt HTTP/1.1<br>
2393	<br>
2394	\b Note: It should be noted that the output buffer needs to be allocated prior to calling this method.
2395	The required space can be determined by calling \a ILibHTTPEscapeLength.
2396	\param outdata The escaped string
2397	\param data The string to escape
2398	\returns The length of the escaped string
2399*/
2400/*
2401int ILibHTTPEscape(char* outdata, const char* data)
2402{
2403	int i=0;
2404	int x=0;
2405	char hex[4];
2406	int hexLen;
2407
2408	while(data[x]!=0)
2409	{
2410		if( (data[x]>=63 && data[x]<=90) || (data[x]>=97 && data[x]<=122) || (data[x]>=47 && data[x]<=57) \
2411			|| data[x]==59 || data[x]==47 || data[x]==63 || data[x]==58 || data[x]==64 || data[x]==61 \
2412			|| data[x]==43 || data[x]==36 || data[x]==45 || data[x]==95 || data[x]==46 || data[x]==42)
2413		{
2414			//
2415			// These are all the allowed values for HTTP. If it's one of these characters, we're ok
2416			//
2417			outdata[i] = data[x];
2418			++i;
2419		}
2420		else
2421		{
2422			//
2423			// If it wasn't one of these characters, then we need to escape it
2424			//
2425			hexLen = sprintf(hex,"%02X",(unsigned char)data[x]);
2426			outdata[i] = '%';
2427			outdata[i+1] = hex[0];
2428			outdata[i+2] = hex[1];
2429			i+=3;
2430		}
2431		++x;
2432	}
2433	outdata[i]=0;
2434	return(i+1);
2435}
2436*/
2437/*! \fn ILibHTTPEscapeLength(const char* data)
2438	\brief Determines the buffer space required to HTTP escape a particular string.
2439	\param data Calculates the length requirements as if \a\b data was escaped
2440	\returns The minimum required length
2441*/
2442/*
2443int ILibHTTPEscapeLength(const char* data)
2444{
2445	int i=0;
2446	int x=0;
2447	while(data[x]!=0)
2448	{
2449		if( (data[x]>=63 && data[x]<=90) || (data[x]>=97 && data[x]<=122) || (data[x]>=47 && data[x]<=57) \
2450			|| data[x]==59 || data[x]==47 || data[x]==63 || data[x]==58 || data[x]==64 || data[x]==61 \
2451			|| data[x]==43 || data[x]==36 || data[x]==45 || data[x]==95 || data[x]==46 || data[x]==42)
2452		{
2453			// No need to escape
2454			++i;
2455		}
2456		else
2457		{
2458			// Need to escape
2459			i+=3;
2460		}
2461		++x;
2462	}
2463	return(i+1);
2464}
2465*/
2466/*! \fn ILibInPlaceHTTPUnEscape(char* data)
2467	\brief Unescapes a given string according to HTTP encoding rules
2468	\para
2469	The escaped representation of a string is always longer than the unescaped version
2470	so this method will overwrite the escaped string, with the unescaped result.
2471	\param data The buffer to unescape
2472	\returns The length of the unescaped string
2473*/
2474/*
2475int ILibInPlaceHTTPUnEscape(char* data)
2476{
2477	char hex[3];
2478	char *stp;
2479	int src_x=0;
2480	int dst_x=0;
2481
2482	int length = (int)strlen(data);
2483	hex[2]=0;
2484
2485	while(src_x<length)
2486	{
2487		if(strncmp(data+src_x,"%",1)==0)
2488		{
2489			//
2490			// Since we encountered a '%' we know this is an escaped character
2491			//
2492			hex[0] = data[src_x+1];
2493			hex[1] = data[src_x+2];
2494			data[dst_x] = (char)strtol(hex,&stp,16);
2495			dst_x += 1;
2496			src_x += 3;
2497		}
2498		else if(src_x!=dst_x)
2499		{
2500			//
2501			// This doesn't need to be unescaped. If we didn't unescape anything previously
2502			// there is no need to copy the string either
2503			//
2504			data[dst_x] = data[src_x];
2505			src_x += 1;
2506			dst_x += 1;
2507		}
2508		else
2509		{
2510			//
2511			// This doesn't need to be unescaped, however we need to copy the string
2512			//
2513			src_x += 1;
2514			dst_x += 1;
2515		}
2516	}
2517	return(dst_x);
2518}
2519*/
2520/*! \fn ILibParsePacketHeader(char* buffer, int offset, int length)
2521	\brief Parses the HTTP headers from a buffer, into a packetheader structure
2522	\param buffer The buffer to parse
2523	\param offset The offset of the buffer to start parsing
2524	\param length The length of the buffer to parse
2525	\returns>packetheader structure
2526*/
2527/*
2528struct packetheader* ILibParsePacketHeader(char* buffer, int offset, int length)
2529{
2530	struct packetheader *RetVal = (struct packetheader*)malloc(sizeof(struct packetheader));
2531	struct parser_result *_packet = NULL;
2532	struct parser_result *p = NULL;
2533	struct parser_result *StartLine = NULL;
2534	struct parser_result_field *HeaderLine = NULL;
2535	struct parser_result_field *f = NULL;
2536	char* tempbuffer = NULL;
2537	struct packetheader_field_node *node = NULL;
2538	int i=0;
2539
2540	memset(RetVal,0,sizeof(struct packetheader));
2541
2542	//
2543	// All the headers are delineated with a CRLF, so we parse on that
2544	//
2545	p = (struct parser_result*)ILibParseString(buffer,offset,length,"\r\n",2);
2546	_packet = p;
2547	f = p->FirstResult;
2548	//
2549	// The first token is where we can figure out the Method, Path, Version, etc.
2550	//
2551	StartLine = (struct parser_result*)ILibParseString(f->data,0,f->datalength," ",1);
2552	HeaderLine = f->NextResult;
2553	if(memcmp(StartLine->FirstResult->data,
2554	"HTTP/",
2555	5)==0)
2556	{
2557		//
2558		// If the StartLine starts with HTTP/, then we know this is a response packet.
2559		// We parse on the '/' character to determine the Version, as it follows.
2560		// eg: HTTP/1.1 200 OK
2561		//
2562		p = (struct parser_result*)ILibParseString(StartLine->FirstResult->data,
2563		0,
2564		StartLine->FirstResult->datalength,
2565		"/",1);
2566		RetVal->Version = p->LastResult->data;
2567		RetVal->VersionLength = p->LastResult->datalength;
2568		RetVal->Version[RetVal->VersionLength]=0;
2569		ILibDestructParserResults(p);
2570		tempbuffer = (char*)malloc(1+sizeof(char)*(StartLine->FirstResult->NextResult->datalength));
2571		memcpy(tempbuffer,StartLine->FirstResult->NextResult->data,
2572		StartLine->FirstResult->NextResult->datalength);
2573		//MEMCHECK(assert(StartLine->FirstResult->NextResult->datalength <= 1+(int)sizeof(char)*(StartLine->FirstResult->NextResult->datalength));)
2574
2575		//
2576		// The other tokens contain the Status code and data
2577		//
2578		tempbuffer[StartLine->FirstResult->NextResult->datalength] = '\0';
2579		RetVal->StatusCode = (int)atoi(tempbuffer);
2580		free(tempbuffer);
2581		RetVal->StatusData = StartLine->FirstResult->NextResult->NextResult->data;
2582		RetVal->StatusDataLength = StartLine->FirstResult->NextResult->NextResult->datalength;
2583	}
2584	else
2585	{
2586
2587		//
2588		// If the packet didn't start with HTTP/ then we know it's a request packet
2589		// eg: GET /index.html HTTP/1.1
2590		// The method (or directive), is the first token, and the Path
2591		// (or DirectiveObj) is the second, and version in the 3rd.
2592		//
2593		RetVal->Directive = StartLine->FirstResult->data;
2594		RetVal->DirectiveLength = StartLine->FirstResult->datalength;
2595		RetVal->DirectiveObj = StartLine->FirstResult->NextResult->data;
2596		RetVal->DirectiveObjLength = StartLine->FirstResult->NextResult->datalength;
2597		RetVal->StatusCode = -1;
2598		//
2599		// We parse the last token on '/' to find the version
2600		//
2601		p = (struct parser_result*)ILibParseString(StartLine->LastResult->data,
2602		0,
2603		StartLine->LastResult->datalength,
2604		"/",1);
2605		RetVal->Version = p->LastResult->data;
2606		RetVal->VersionLength = p->LastResult->datalength;
2607		RetVal->Version[RetVal->VersionLength]=0;
2608		ILibDestructParserResults(p);
2609
2610		RetVal->Directive[RetVal->DirectiveLength] = '\0';
2611		RetVal->DirectiveObj[RetVal->DirectiveObjLength] = '\0';
2612	}
2613	//
2614	// Headerline starts with the second token. Then we iterate through the rest of the tokens
2615	//
2616
2617	while(HeaderLine!=NULL)
2618	{
2619		if(HeaderLine->datalength==0)
2620		{
2621			//
2622			// An empty line signals the end of the headers
2623			//
2624			break;
2625		}
2626		// Arthur, 050721, DLNA CTT 1.00.07 case 7.8.10.3
2627		#ifdef ASUS_DLNA_CTT
2628		if(node!=NULL && (HeaderLine->data[0] == 0x09 || HeaderLine->data[0] == 0x20))
2629		#else
2630		if(node!=NULL && HeaderLine->data[0]==' ')
2631		#endif
2632		{
2633			//
2634			// This is a multi-line continuation
2635			//
2636			if(node->UserAllocStrings==0)
2637			{
2638				tempbuffer = node->FieldData;
2639				node->FieldData = (char*)malloc(node->FieldDataLength + HeaderLine->datalength);
2640				memcpy(node->FieldData,tempbuffer,node->FieldDataLength);
2641
2642				tempbuffer = node->Field;
2643				node->Field = (char*)malloc(node->FieldLength+1);
2644				memcpy(node->Field,tempbuffer,node->FieldLength);
2645
2646				node->UserAllocStrings = -1;
2647			}
2648			else
2649			{
2650				node->FieldData = (char*)realloc(node->FieldData,node->FieldDataLength + HeaderLine->datalength);
2651			}
2652			memcpy(node->FieldData+node->FieldDataLength,HeaderLine->data+1,HeaderLine->datalength-1);
2653			node->FieldDataLength += (HeaderLine->datalength-1);
2654		}
2655		else
2656		{
2657			//
2658			// Instantiate a new header entry for each new token
2659			//
2660			node = (struct packetheader_field_node*)malloc(sizeof(struct packetheader_field_node));
2661			memset(node,0,sizeof(struct packetheader_field_node));
2662			for(i=0;i<HeaderLine->datalength;++i)
2663			{
2664				if(*((HeaderLine->data)+i)==':')
2665				{
2666					node->Field = HeaderLine->data;
2667					node->FieldLength = i;
2668					node->FieldData = HeaderLine->data + i + 1;
2669					node->FieldDataLength = (HeaderLine->datalength)-i-1;
2670					break;
2671				}
2672			}
2673			if(node->Field==NULL)
2674			{
2675				free(RetVal);
2676				RetVal = NULL;
2677				break;
2678			}
2679			//
2680			// We need to do white space processing, because we need to ignore them in the
2681			// headers
2682			// So do a 'trim' operation
2683			//
2684			node->FieldDataLength = ILibTrimString(&(node->FieldData),node->FieldDataLength);
2685			node->Field[node->FieldLength] = '\0';
2686			node->FieldData[node->FieldDataLength] = '\0';
2687
2688			//
2689			// Since we are parsing an existing string, we set this flag to zero, so that it doesn't
2690			// get freed
2691			//
2692			node->UserAllocStrings = 0;
2693			node->NextField = NULL;
2694
2695			if(RetVal->FirstField==NULL)
2696			{
2697				//
2698				// If there aren't any headers yet, this will be the first
2699				//
2700				RetVal->FirstField = node;
2701				RetVal->LastField = node;
2702			}
2703			else
2704			{
2705				//
2706				// There are already headers, so link this in the tail
2707				//
2708				RetVal->LastField->NextField = node;
2709			}
2710			RetVal->LastField = node;
2711		}
2712		HeaderLine = HeaderLine->NextResult;
2713	}
2714	ILibDestructParserResults(_packet);
2715	ILibDestructParserResults(StartLine);
2716	return(RetVal);
2717}
2718*/
2719/*! \fn ILibFragmentTextLength(char *text, int textLength, char *delimiter, int delimiterLength, int tokenLength)
2720	\brief Determines the buffer size required to fragment a string
2721	\param text The string to fragment
2722	\param textLength Length of \a text
2723	\param delimiter Line delimiter
2724	\param delimiterLength Length of \a delimiter
2725	\param tokenLength The maximum size of each fragment or token
2726	\returns The length of the buffer required to call \a ILibFragmentText
2727*/
2728/*
2729int ILibFragmentTextLength(char *text, int textLength, char *delimiter, int delimiterLength, int tokenLength)
2730{
2731	int RetVal = textLength + (((textLength/tokenLength)==1?0:(textLength/tokenLength))*delimiterLength);
2732	return(RetVal);
2733}
2734*/
2735/*! \fn ILibFragmentText(char *text, int textLength, char *delimiter, int delimiterLength, int tokenLength, char **RetVal)
2736	\brief Fragments a string into multiple tokens
2737	\param text The string to fragment
2738	\param textLength Length of \a text
2739	\param delimiter Line delimiter
2740	\param delimiterLength Length of \a delimiter
2741	\param tokenLength The maximum size of each fragment or token
2742	\param RetVal The buffer to store the resultant string
2743	\returns The length of the written string
2744*/
2745/*
2746int ILibFragmentText(char *text, int textLength, char *delimiter, int delimiterLength, int tokenLength, char **RetVal)
2747{
2748	char *Buffer;
2749	int i=0,i2=0;
2750	int BufferSize = 0;
2751	*RetVal = (char*)malloc(ILibFragmentTextLength(text,textLength,delimiter,delimiterLength,tokenLength));
2752
2753	Buffer = *RetVal;
2754
2755	i2 = textLength;
2756	while(i2!=0)
2757	{
2758		if(i2!=textLength)
2759		{
2760			memcpy(Buffer+i,delimiter,delimiterLength);
2761			i+=delimiterLength;
2762			BufferSize += delimiterLength;
2763		}
2764		memcpy(Buffer+i,text + (textLength-i2),i2>tokenLength?tokenLength:i2);
2765		i+=i2>tokenLength?tokenLength:i2;
2766		BufferSize += i2>tokenLength?tokenLength:i2;
2767		i2 -= i2>tokenLength?tokenLength:i2;
2768	}
2769	return(BufferSize);
2770}
2771*/
2772/*! \fn ILibGetRawPacket(struct packetheader* packet,char **RetVal)
2773	\brief Converts a packetheader structure into a raw char* buffer
2774	\para
2775	\b Note: The returned buffer must be freed
2776	\param packet The packetheader struture to convert
2777	\param RetVal The output char* buffer
2778	\returns The length of the output buffer
2779*/
2780/*
2781int ILibGetRawPacket(struct packetheader* packet,char **RetVal)
2782{
2783	int i,i2;
2784	int BufferSize = 0;
2785	char* Buffer, *temp;
2786	struct packetheader_field_node *node;
2787
2788	if(packet->StatusCode!=-1)
2789	{
2790		BufferSize = 12 + packet->VersionLength + packet->StatusDataLength;
2791		//
2792		// HTTP/1.1 200 OK\r\n
2793		// 12 is the total number of literal characters. Just add Version and StatusData
2794		// HTTP/ OK \r\n
2795		//
2796	}
2797	else
2798	{
2799		BufferSize = packet->DirectiveLength + packet->DirectiveObjLength + 12;
2800		//
2801		// GET / HTTP/1.1\r\n
2802		// This is calculating the length for a request packet.
2803		// ToDo: This isn't completely correct
2804		// But it will work as long as the version is not > 9.9
2805		// It should also add the length of the Version, but it's not critical.
2806	}
2807
2808	node = packet->FirstField;
2809	while(node!=NULL)
2810	{
2811		//
2812		// A conservative estimate adding the lengths of the header name and value, plus
2813		// 4 characters for the ':' and CRLF
2814		//
2815		BufferSize += node->FieldLength + node->FieldDataLength + 4;
2816
2817		//
2818		// If the header is longer than MAX_HEADER_LENGTH, we need to break it up
2819		// into multiple lines, so we need to calculate the space needed for the
2820		// delimiters.
2821		//
2822		if(node->FieldDataLength>MAX_HEADER_LENGTH)
2823		{
2824			BufferSize += ILibFragmentTextLength(node->FieldData,node->FieldDataLength,"\r\n ",3,MAX_HEADER_LENGTH);
2825		}
2826		node = node->NextField;
2827	}
2828	//
2829	// Another conservative estimate adding in the packet body length plus a padding of 3
2830	// for the empty line
2831	//
2832	BufferSize += (3+packet->BodyLength);
2833
2834	//
2835	// Allocate the buffer
2836	//
2837	*RetVal = (char*)malloc(BufferSize);
2838	Buffer = *RetVal;
2839	if(packet->StatusCode!=-1)
2840	{
2841		//
2842		// Write the response
2843		//
2844		memcpy(Buffer,"HTTP/",5);
2845		memcpy(Buffer+5,packet->Version,packet->VersionLength);
2846		i = 5+packet->VersionLength;
2847
2848		i+=sprintf(Buffer+i," %d ",packet->StatusCode);
2849		memcpy(Buffer+i,packet->StatusData,packet->StatusDataLength);
2850		i+=packet->StatusDataLength;
2851
2852		memcpy(Buffer+i,"\r\n",2);
2853		i+=2;
2854		// HTTP/1.1 200 OK\r\n
2855	}
2856	else
2857	{
2858		//
2859		// Write the Request
2860		//
2861		memcpy(Buffer,packet->Directive,packet->DirectiveLength);
2862		i = packet->DirectiveLength;
2863		memcpy(Buffer+i," ",1);
2864		i+=1;
2865		memcpy(Buffer+i,packet->DirectiveObj,packet->DirectiveObjLength);
2866		i+=packet->DirectiveObjLength;
2867		memcpy(Buffer+i," HTTP/",6);
2868		i+=6;
2869		memcpy(Buffer+i,packet->Version,packet->VersionLength);
2870		i+=packet->VersionLength;
2871		memcpy(Buffer+i,"\r\n",2);
2872		i+=2;
2873		// GET / HTTP/1.1\r\n
2874	}
2875
2876	node = packet->FirstField;
2877	while(node!=NULL)
2878	{
2879		//
2880		// Write each header
2881		//
2882		memcpy(Buffer+i,node->Field,node->FieldLength);
2883		i+=node->FieldLength;
2884		memcpy(Buffer+i,": ",2);
2885		i+=2;
2886		BufferSize += (node->FieldLength + 2);
2887
2888		if(ILibFragmentTextLength(node->FieldData,node->FieldDataLength,"\r\n ",3, MAX_HEADER_LENGTH)>node->FieldDataLength)
2889		{
2890			// Fragment this
2891			i2 = ILibFragmentText(node->FieldData,node->FieldDataLength,"\r\n ",3, MAX_HEADER_LENGTH,&temp);
2892			memcpy(Buffer+i,temp,i2);
2893			i += i2;
2894			BufferSize += i2;
2895			free(temp);
2896		}
2897		else
2898		{
2899			// No need to fragment this
2900			memcpy(Buffer+i,node->FieldData,node->FieldDataLength);
2901			i += node->FieldDataLength;
2902			BufferSize += node->FieldDataLength;
2903		}
2904
2905		memcpy(Buffer+i,"\r\n",2);
2906		i+=2;
2907		BufferSize += 2;
2908		node = node->NextField;
2909	}
2910	//
2911	// Write the empty line
2912	//
2913	memcpy(Buffer+i,"\r\n",2);
2914	i+=2;
2915
2916	//
2917	// Write the body
2918	//
2919	memcpy(Buffer+i,packet->Body,packet->BodyLength);
2920	i+=packet->BodyLength;
2921	Buffer[i] = '\0';
2922
2923	return(i);
2924}
2925*/
2926/*! \fn unsigned short ILibGetDGramSocket(int local, int *TheSocket)
2927	\brief Allocates a UDP socket for a given interface, choosing a random port number from 50000 to 65535
2928	\para
2929	\b Note: Storage type of \a TheSocket is platform dependent. <br>
2930	Windows Winsock2 = HANDLE*<br>
2931	Windows Winsock1 = SOCKET*<br>
2932	Linux/Posix = int*<br>
2933	\param local The interface to bind to
2934	\param TheSocket The created UDP socket
2935	\returns The port number that was bound
2936*/
2937/*
2938#ifdef WINSOCK2
2939	unsigned short ILibGetDGramSocket(int local, HANDLE *TheSocket)
2940#elif WINSOCK1
2941	unsigned short ILibGetDGramSocket(int local, SOCKET *TheSocket)
2942#else
2943	unsigned short ILibGetDGramSocket(int local, int *TheSocket)
2944#endif
2945{
2946	unsigned short PortNum = -1;
2947	struct sockaddr_in addr;
2948	memset((char *)&(addr), 0, sizeof(addr));
2949	addr.sin_family = AF_INET;
2950	addr.sin_addr.s_addr = local;
2951#ifdef WINSOCK2
2952	*TheSocket = (HANDLE)socket(AF_INET, SOCK_DGRAM, 0);
2953#elif WINSOCK1
2954	*TheSocket = (SOCKET)socket(AF_INET, SOCK_DGRAM, 0);
2955#else
2956	*TheSocket = (int)socket(AF_INET, SOCK_DGRAM, 0);
2957#endif
2958	//
2959	// Keep looping until we find a port number that isn't in use. Since
2960	// we're using random numbers, the first try should usually do it.
2961	// We can't just bind to 0, because we need to be IANA compliant.
2962	//
2963	do
2964	{
2965		//
2966		// Choose a random port from 50000 to 65500, which is what IANA says to use
2967		// for non standard ports
2968		//
2969		PortNum = (unsigned short)(50000 + ((unsigned short)rand() % 15000));
2970		addr.sin_port = htons(PortNum);
2971	}
2972#ifdef WIN32
2973	while(bind((SOCKET)*TheSocket, (struct sockaddr *) &(addr), sizeof(addr)) < 0);
2974#else
2975	while(bind((int)*TheSocket, (struct sockaddr *) &(addr), sizeof(addr)) < 0);
2976#endif
2977	return(PortNum);
2978}
2979*/
2980
2981/*! \fn unsigned short ILibGetStreamSocket(int local, unsigned short PortNumber, int *TheSocket)
2982	\brief Allocates a TCP socket for a given interface, choosing a random port number from 50000 to 65535
2983	\para
2984	\b Note: Storage type of \a TheSocket is platform dependent. <br>
2985	Windows Winsock2 = HANDLE*<br>
2986	Windows Winsock1 = SOCKET*<br>
2987	Linux/Posix = int*<br>
2988	\param local The interface to bind to
2989	\param TheSocket The created TCP socket
2990	\returns The port number that was bound
2991*/
2992/*
2993#ifdef WINSOCK2
2994	unsigned short ILibGetStreamSocket(int local, unsigned short PortNumber, HANDLE *TheSocket)
2995#elif WINSOCK1
2996	unsigned short ILibGetStreamSocket(int local, unsigned short PortNumber, SOCKET *TheSocket)
2997#else
2998	unsigned short ILibGetStreamSocket(int local, unsigned short PortNumber, int *TheSocket)
2999#endif
3000{
3001	int ra=1;
3002	unsigned short PortNum = -1;
3003	struct sockaddr_in addr;
3004	memset((char *)&(addr), 0, sizeof(addr));
3005	addr.sin_family = AF_INET;
3006	addr.sin_addr.s_addr = local;
3007
3008#ifdef WINSOCK2
3009	*TheSocket = (HANDLE)socket(AF_INET, SOCK_STREAM, 0);
3010#elif WINSOCK1
3011	*TheSocket = (SOCKET)socket(AF_INET, SOCK_STREAM, 0);
3012#else
3013	*TheSocket = (int)socket(AF_INET, SOCK_STREAM, 0);
3014#endif
3015	if(PortNumber==0)
3016	{
3017		//
3018		// If PortNumber is 0, we need to choose a random port from MINPORTNUMBER to
3019		// MINPORTNUMBER + PORTNUMBERRANGE.
3020		// By default this is 50000 + 15000, which gives us the IANA defined range to use
3021		//
3022		do
3023		{
3024			PortNum = (unsigned short)(MINPORTNUMBER + ((unsigned short)rand() % PORTNUMBERRANGE));
3025			addr.sin_port = htons(PortNum);
3026		}
3027#ifdef WIN32
3028		while(bind((SOCKET)*TheSocket, (struct sockaddr *) &(addr), sizeof(addr)) < 0);
3029#else
3030		while(bind((int)*TheSocket, (struct sockaddr *) &(addr), sizeof(addr)) < 0);
3031#endif
3032	}
3033	else
3034	{
3035		//
3036		// If a specific port was specified, try to use that
3037		//
3038		addr.sin_port = htons(PortNumber);
3039#ifdef WIN32
3040		if (setsockopt((SOCKET)*TheSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&ra, sizeof(ra)) < 0)
3041#else
3042		if (setsockopt((int)*TheSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&ra, sizeof(ra)) < 0)
3043#endif
3044		{
3045		}
3046#ifdef WIN32
3047		PortNum = bind((SOCKET)*TheSocket, (struct sockaddr *) &(addr), sizeof(addr))<0?0:PortNumber;
3048#else
3049		PortNum = bind((int)*TheSocket, (struct sockaddr *) &(addr), sizeof(addr))<0?0:PortNumber;
3050#endif
3051	}
3052	return(PortNum);
3053}
3054*/
3055
3056/*! \fn ILibParseUri(char* URI, char** IP, unsigned short* Port, char** Path)
3057	\brief Parses a URI string, into its IP Address, Port Number, and Path components
3058	\para
3059	\b Note: The IP and Path components must be freed
3060	\param URI The URI to parse
3061	\param IP The IP Address component in dotted quad format
3062	\param Port The Port component. Default is 80
3063	\param Path The Path component
3064*/
3065/*
3066void ILibParseUri(char* URI, char** IP, unsigned short* Port, char** Path)
3067{
3068	struct parser_result *result,*result2,*result3;
3069	char *TempString,*TempString2;
3070	int TempStringLength,TempStringLength2;
3071
3072	//
3073	// A scheme has the format xxx://yyy , so if we parse on ://, we can extract the path info
3074	//
3075	result = ILibParseString(URI, 0, (int)strlen(URI), "://", 3);
3076	TempString = result->LastResult->data;
3077	TempStringLength = result->LastResult->datalength;
3078
3079	//
3080	// Parse Path
3081	// The first '/' will occur after the IPAddress:Port combination
3082	//
3083	result2 = ILibParseString(TempString,0,TempStringLength,"/",1);
3084	TempStringLength2 = TempStringLength-result2->FirstResult->datalength;
3085	*Path = (char*)malloc(TempStringLength2+1);
3086	memcpy(*Path,TempString+(result2->FirstResult->datalength),TempStringLength2);
3087	(*Path)[TempStringLength2] = '\0';
3088
3089	// Parse Port Number
3090	result3 = ILibParseString(result2->FirstResult->data,0,result2->FirstResult->datalength,":",1);
3091	if(result3->NumResults==1)
3092	{
3093		//
3094		// The default port is 80, if non is specified, because we are assuming
3095		// an HTTP scheme
3096		//
3097		*Port = 80;
3098	}
3099	else
3100	{
3101		//
3102		// If a port was specified, use that
3103		//
3104		TempString2 = (char*)malloc(result3->LastResult->datalength+1);
3105		memcpy(TempString2,result3->LastResult->data,result3->LastResult->datalength);
3106		TempString2[result3->LastResult->datalength] = '\0';
3107		*Port = (unsigned short)atoi(TempString2);
3108		free(TempString2);
3109	}
3110
3111	// Parse IP Address
3112	TempStringLength2 = result3->FirstResult->datalength;
3113	*IP = (char*)malloc(TempStringLength2+1);
3114	memcpy(*IP,result3->FirstResult->data,TempStringLength2);
3115	(*IP)[TempStringLength2] = '\0';
3116	ILibDestructParserResults(result3);
3117	ILibDestructParserResults(result2);
3118	ILibDestructParserResults(result);
3119}
3120*/
3121/*! \fn ILibCreateEmptyPacket()
3122	\brief Creates an empty packetheader structure
3123	\returns An empty packet
3124*/
3125/*
3126struct packetheader *ILibCreateEmptyPacket()
3127{
3128	struct packetheader *RetVal = (struct packetheader*)malloc(sizeof(struct packetheader));
3129	memset(RetVal,0,sizeof(struct packetheader));
3130
3131	RetVal->UserAllocStrings = -1;
3132	RetVal->StatusCode = -1;
3133	RetVal->Version = "1.0";
3134	RetVal->VersionLength = 3;
3135
3136	return(RetVal);
3137}
3138*/
3139/*! \fn ILibClonePacket(struct packetheader *packet)
3140	\brief Creates a Deep Copy of a packet structure
3141	\para
3142	Because ILibParsePacketHeader does not copy any data, the data will become invalid
3143	once the data is flushed. This method is used to preserve the data.
3144	\param packet The packet to clone
3145	\returns A cloned packet structure
3146*/
3147/*
3148struct packetheader* ILibClonePacket(struct packetheader *packet)
3149{
3150	struct packetheader *RetVal = ILibCreateEmptyPacket();
3151	struct packetheader_field_node *n;
3152
3153	RetVal->ClonedPacket=1;
3154	RetVal->ReceivingAddress = packet->ReceivingAddress;
3155
3156	//
3157	// These three calls will result in the fields being copied
3158	//
3159	ILibSetDirective(
3160	RetVal,
3161	packet->Directive,
3162	packet->DirectiveLength,
3163	packet->DirectiveObj,
3164	packet->DirectiveObjLength);
3165
3166	ILibSetStatusCode(
3167	RetVal,
3168	packet->StatusCode,
3169	packet->StatusData,
3170	packet->StatusDataLength);
3171
3172	ILibSetVersion(RetVal,packet->Version,packet->VersionLength);
3173
3174	//
3175	// Iterate through each header, and copy them
3176	//
3177	n = packet->FirstField;
3178	while(n!=NULL)
3179	{
3180		ILibAddHeaderLine(
3181		RetVal,
3182		n->Field,
3183		n->FieldLength,
3184		n->FieldData,
3185		n->FieldDataLength);
3186		n = n->NextField;
3187	}
3188	return(RetVal);
3189}
3190*/
3191/*! \fn ILibSetVersion(struct packetheader *packet, char* Version, int VersionLength)
3192	\brief Sets the version of a packetheader structure. The Default version is 1.0
3193	\param packet The packet to modify</param>
3194	\param Version The version string to write. eg: 1.1
3195	\param VersionLength The length of the \a Version
3196*/
3197/*
3198void ILibSetVersion(struct packetheader *packet, char* Version, int VersionLength)
3199{
3200	if(packet->UserAllocVersion!=0)	{free(packet->Version);}
3201	packet->UserAllocVersion=1;
3202	packet->Version = (char*)malloc(1+VersionLength);
3203	memcpy(packet->Version,Version,VersionLength);
3204	packet->Version[VersionLength] = '\0';
3205}
3206*/
3207/*! \fn ILibSetStatusCode(struct packetheader *packet, int StatusCode, char *StatusData, int StatusDataLength)
3208	\brief Sets the status code of a packetheader structure
3209	\param packet The packet to modify
3210	\param StatusCode The status code, eg: 200
3211	\param StatusData The status string, eg: OK
3212	\param StatusDataLength The length of \a StatusData
3213*/
3214/*
3215void ILibSetStatusCode(struct packetheader *packet, int StatusCode, char *StatusData, int StatusDataLength)
3216{
3217	packet->StatusCode = StatusCode;
3218	packet->StatusData = (char*)malloc(StatusDataLength+1);
3219	memcpy(packet->StatusData,StatusData,StatusDataLength);
3220	packet->StatusData[StatusDataLength] = '\0';
3221	packet->StatusDataLength = StatusDataLength;
3222}
3223*/
3224/*! \fn ILibSetDirective(struct packetheader *packet, char* Directive, int DirectiveLength, char* DirectiveObj, int DirectiveObjLength)
3225	\brief Sets the /a Method and /a Path of a packetheader structure
3226	\param packet The packet to modify
3227	\param Directive The Method to write, eg: \b GET
3228	\param DirectiveLength The length of \a Directive
3229	\param DirectiveObj The path component of the method, eg: \b /index.html
3230	\param DirectiveObjLength The length of \a DirectiveObj
3231*/
3232/*
3233void ILibSetDirective(struct packetheader *packet, char* Directive, int DirectiveLength, char* DirectiveObj, int DirectiveObjLength)
3234{
3235	packet->Directive = (char*)malloc(DirectiveLength+1);
3236	memcpy(packet->Directive,Directive,DirectiveLength);
3237	packet->Directive[DirectiveLength] = '\0';
3238	packet->DirectiveLength = DirectiveLength;
3239
3240	packet->DirectiveObj = (char*)malloc(DirectiveObjLength+1);
3241	memcpy(packet->DirectiveObj,DirectiveObj,DirectiveObjLength);
3242	packet->DirectiveObj[DirectiveObjLength] = '\0';
3243	packet->DirectiveObjLength = DirectiveObjLength;
3244	packet->UserAllocStrings = -1;
3245}
3246*/
3247/*! \fn ILibAddHeaderLine(struct packetheader *packet, char* FieldName, int FieldNameLength, char* FieldData, int FieldDataLength)
3248	\brief Adds an HTTP header entry into a packetheader structure
3249	\param packet The packet to modify
3250	\param FieldName The header name, eg: \b CONTENT-TYPE
3251	\param FieldNameLength The length of the \a FieldName
3252	\param FieldData The header value, eg: \b text/xml
3253	\param FieldDataLength The length of the \a FieldData
3254*/
3255/*
3256void ILibAddHeaderLine(struct packetheader *packet, char* FieldName, int FieldNameLength, char* FieldData, int FieldDataLength)
3257{
3258	struct packetheader_field_node *node;
3259
3260	//
3261	// Create the Header Node
3262	//
3263	node = (struct packetheader_field_node*)malloc(sizeof(struct packetheader_field_node));
3264	node->UserAllocStrings = -1;
3265	node->Field = (char*)malloc(FieldNameLength+1);
3266	memcpy(node->Field,FieldName,FieldNameLength);
3267	node->Field[FieldNameLength] = '\0';
3268	node->FieldLength = FieldNameLength;
3269
3270	node->FieldData = (char*)malloc(FieldDataLength+1);
3271	memcpy(node->FieldData,FieldData,FieldDataLength);
3272	node->FieldData[FieldDataLength] = '\0';
3273	node->FieldDataLength = FieldDataLength;
3274
3275	node->NextField = NULL;
3276
3277	//
3278	// And attach it to the linked list
3279	//
3280	if(packet->LastField!=NULL)
3281	{
3282		packet->LastField->NextField = node;
3283		packet->LastField = node;
3284	}
3285	else
3286	{
3287		packet->LastField = node;
3288		packet->FirstField = node;
3289	}
3290}
3291*/
3292/*! \fn ILibGetHeaderLine(struct packetheader *packet, char* FieldName, int FieldNameLength)
3293	\brief Retrieves an HTTP header value from a packet structure
3294	\para
3295	\b Note: The result must be freed
3296	\param packet The packet to introspect
3297	\param FieldName The header name to lookup
3298	\param FieldNameLength">The length of \a FieldName
3299	\returns The header value. NULL if not found
3300*/
3301/*
3302char* ILibGetHeaderLine(struct packetheader *packet, char* FieldName, int FieldNameLength)
3303{
3304	char* RetVal = NULL;
3305	struct packetheader_field_node *node = packet->FirstField;
3306	int i;
3307
3308	//
3309	// Iterate through the headers, until we find the one we're interested in
3310	//
3311	while(node!=NULL)
3312	{
3313		if(strncasecmp(FieldName,node->Field,FieldNameLength)==0)
3314		{
3315			//
3316			// Copy the value, and return it
3317			//
3318			RetVal = (char*)malloc(node->FieldDataLength+1);
3319
3320			for(i=0;i<node->FieldDataLength;++i)
3321			{
3322				if(node->FieldData[i]!=' ') {break;}
3323			}
3324			if(i==node->FieldDataLength-1) {i = 0;}
3325			memcpy(RetVal,node->FieldData+i,node->FieldDataLength-i);
3326			RetVal[node->FieldDataLength-i] = '\0';
3327			break;
3328		}
3329		node = node->NextField;
3330	}
3331
3332	return(RetVal);
3333}
3334*/
3335/*
3336static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3337static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
3338
3339// encode 3 8-bit binary bytes as 4 '6-bit' characters
3340void ILibencodeblock( unsigned char in[3], unsigned char out[4], int len )
3341{
3342	out[0] = cb64[ in[0] >> 2 ];
3343	out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
3344	out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
3345	out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
3346}
3347*/
3348/*! \fn ILibBase64Encode(unsigned char* input, const int inputlen, unsigned char** output)
3349	\brief Base64 encode a stream adding padding and line breaks as per spec.
3350	\para
3351	\b Note: The encoded stream must be freed
3352	\param input The stream to encode
3353	\param inputlen The length of \a input
3354	\param output The encoded stream
3355	\returns The length of the encoded stream
3356*/
3357/*
3358int ILibBase64Encode(unsigned char* input, const int inputlen, unsigned char** output)
3359{
3360	unsigned char* out;
3361	unsigned char* in;
3362
3363	*output = (unsigned char*)malloc(((inputlen * 4) / 3) + 5);
3364	out = *output;
3365	in  = input;
3366
3367	if (input == NULL || inputlen == 0)
3368	{
3369		*output = NULL;
3370		return 0;
3371	}
3372
3373	while ((in+3) <= (input+inputlen))
3374	{
3375		ILibencodeblock(in, out, 3);
3376		in += 3;
3377		out += 4;
3378	}
3379	if ((input+inputlen)-in == 1)
3380	{
3381		ILibencodeblock(in, out, 1);
3382		out += 4;
3383	}
3384	else
3385	if ((input+inputlen)-in == 2)
3386	{
3387		ILibencodeblock(in, out, 2);
3388		out += 4;
3389	}
3390	*out = 0;
3391
3392	return (int)(out-*output);
3393}
3394*/
3395/* Decode 4 '6-bit' characters into 3 8-bit binary bytes */
3396/*
3397void ILibdecodeblock( unsigned char in[4], unsigned char out[3] )
3398{
3399	out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
3400	out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
3401	out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
3402}
3403*/
3404/*! \fn ILibBase64Decode(unsigned char* input, const int inputlen, unsigned char** output)
3405	\brief Decode a base64 encoded stream discarding padding, line breaks and noise
3406	\para
3407	\b Note: The decoded stream must be freed
3408	\param input The stream to decode
3409	\param inputlen The length of \a input
3410	\param output The decoded stream
3411	\returns The length of the decoded stream
3412*/
3413/*
3414int ILibBase64Decode(unsigned char* input, const int inputlen, unsigned char** output)
3415{
3416	unsigned char* inptr;
3417	unsigned char* out;
3418	unsigned char v;
3419	unsigned char in[4];
3420	int i, len;
3421
3422	if (input == NULL || inputlen == 0)
3423	{
3424		*output = NULL;
3425		return 0;
3426	}
3427
3428	*output = (unsigned char*)malloc(((inputlen * 3) / 4) + 4);
3429	out = *output;
3430	inptr = input;
3431
3432	while( inptr <= (input+inputlen) )
3433	{
3434		for( len = 0, i = 0; i < 4 && inptr <= (input+inputlen); i++ )
3435		{
3436			v = 0;
3437			while( inptr <= (input+inputlen) && v == 0 ) {
3438				v = (unsigned char) *inptr;
3439				inptr++;
3440				v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
3441				if( v ) {
3442					v = (unsigned char) ((v == '$') ? 0 : v - 61);
3443				}
3444			}
3445			if( inptr <= (input+inputlen) ) {
3446				len++;
3447				if( v ) {
3448					in[ i ] = (unsigned char) (v - 1);
3449				}
3450			}
3451			else {
3452				in[i] = 0;
3453			}
3454		}
3455		if( len )
3456		{
3457			ILibdecodeblock( in, out );
3458			out += len-1;
3459		}
3460	}
3461	*out = 0;
3462	return (int)(out-*output);
3463}
3464*/
3465/*! \fn ILibInPlaceXmlUnEscape(char* data)
3466	\brief Unescapes a string according to XML parsing rules
3467	\para
3468	Since an escaped XML string is always larger than its unescaped form, this method
3469	will overwrite the escaped string with the unescaped string, while decoding.
3470	\param data The XML string to unescape
3471	\returns The length of the unescaped XML string
3472*/
3473/*
3474int ILibInPlaceXmlUnEscape(char* data)
3475{
3476	char* end = NULL;
3477	char* i = NULL;              // src
3478	char* j = NULL;              // dest
3479
3480	if(data == NULL)
3481		return 0;
3482
3483	end = data + strlen(data);
3484	i = data;
3485	j = data;
3486
3487	//
3488	// Iterate through the string to find escaped sequences
3489	//
3490	while (j < end)
3491	{
3492		if (j[0] == '&' && j[1] == 'q' && j[2] == 'u' && j[3] == 'o' && j[4] == 't' && j[5] == ';')   // &quot;
3493		{
3494			// Double Quote
3495			i[0] = '"';
3496			j += 5;
3497		}
3498		else if (j[0] == '&' && j[1] == 'a' && j[2] == 'p' && j[3] == 'o' && j[4] == 's' && j[5] == ';')   // &apos;
3499		{
3500			// Single Quote (apostrophe)
3501			i[0] = '\'';
3502			j += 5;
3503		}
3504		else if (j[0] == '&' && j[1] == 'a' && j[2] == 'm' && j[3] == 'p' && j[4] == ';')   // &amp;
3505		{
3506			// Ampersand
3507			i[0] = '&';
3508			j += 4;
3509		}
3510		else if (j[0] == '&' && j[1] == 'l' && j[2] == 't' && j[3] == ';')   // &lt;
3511		{
3512			// Less Than
3513			i[0] = '<';
3514			j += 3;
3515		}
3516		else if (j[0] == '&' && j[1] == 'g' && j[2] == 't' && j[3] == ';')   // &gt;
3517		{
3518			// Greater Than
3519			i[0] = '>';
3520			j += 3;
3521		}
3522		else
3523		{
3524			i[0] = j[0];
3525		}
3526		i++;
3527		j++;
3528	}
3529	i[0] = '\0';
3530	return (int)(i - data);
3531}
3532*/
3533/*! \fn ILibXmlEscapeLength(const char* data)
3534	\brief Calculates the minimum required buffer space, to escape an xml string
3535	\para
3536	\b Note: This calculation does not include space for a null terminator
3537	\param data The XML string to calculate buffer requirments with
3538	\returns The minimum required buffer size
3539*/
3540/*
3541int ILibXmlEscapeLength(const char* data)
3542{
3543	int i = 0, j = 0;
3544	while (data[i] != 0)
3545	{
3546		switch (data[i])
3547		{
3548			case '"':
3549			j += 6;
3550			break;
3551			case '\'':
3552			j += 6;
3553			break;
3554			case '<':
3555			j += 4;
3556			break;
3557			case '>':
3558			j += 4;
3559			break;
3560			case '&':
3561			j += 5;
3562			break;
3563			default:
3564			j++;
3565		}
3566		i++;
3567	}
3568	return j;
3569}
3570*/
3571
3572/*! \fn ILibXmlEscape(char* outdata, const char* indata)
3573	\brief Escapes a string according to XML parsing rules
3574	\b Note: /a outdata must be pre-allocated and freed
3575	\param outdata The escaped XML string
3576	\param indata The string to escape
3577	\returns The length of the escaped string
3578*/
3579/*
3580int ILibXmlEscape(char* outdata, const char* indata)
3581{
3582	int i=0;
3583	int inlen;
3584	char* out;
3585
3586	out = outdata;
3587	inlen = (int)strlen(indata);
3588
3589	for (i=0; i < inlen; i++)
3590	{
3591		if (indata[i] == '"')
3592		{
3593			memcpy(out, "&quot;", 6);
3594			out = out + 6;
3595		}
3596		else
3597		if (indata[i] == '\'')
3598		{
3599			memcpy(out, "&apos;", 6);
3600			out = out + 6;
3601		}
3602		else
3603		if (indata[i] == '<')
3604		{
3605			memcpy(out, "&lt;", 4);
3606			out = out + 4;
3607		}
3608		else
3609		if (indata[i] == '>')
3610		{
3611			memcpy(out, "&gt;", 4);
3612			out = out + 4;
3613		}
3614		else
3615		if (indata[i] == '&')
3616		{
3617			memcpy(out, "&amp;", 5);
3618			out = out + 5;
3619		}
3620		else
3621		{
3622			out[0] = indata[i];
3623			out++;
3624		}
3625	}
3626
3627	out[0] = 0;
3628
3629	return (int)(out - outdata);
3630}
3631*/
3632/*! \fn ILibLifeTime_AddEx(void *LifetimeMonitorObject,void *data, int ms, void* Callback, void* Destroy)
3633	\brief Registers a timed callback with millisecond granularity
3634	\param LifetimeMonitorObject The \a ILibLifeTime object to add the timed callback to
3635	\param data The data object to associate with the timed callback
3636	\param ms The number of milliseconds for the timed callback
3637	\param Callback The callback function pointer to trigger when the specified time elapses
3638	\param Destroy The abort function pointer, which triggers all non-triggered timed callbacks, upon shutdown
3639*/
3640/*
3641void ILibLifeTime_AddEx(void *LifetimeMonitorObject,void *data, int ms, void* Callback, void* Destroy)
3642{
3643	int NeedUnBlock = 0;
3644	struct timeval tv;
3645	struct LifeTimeMonitorData *temp;
3646	struct LifeTimeMonitorData *ltms = (struct LifeTimeMonitorData*)malloc(sizeof(struct LifeTimeMonitorData));
3647	struct ILibLifeTime *UPnPLifeTime = (struct ILibLifeTime*)LifetimeMonitorObject;
3648
3649	//
3650	// Get the current time for reference
3651	//
3652	gettimeofday(&tv,NULL);
3653
3654	//
3655	// Set the trigger time
3656	//
3657	ltms->data = data;
3658	ltms->ExpirationTick = (tv.tv_sec*1000) + (tv.tv_usec/1000) + ms;
3659
3660	//
3661	// Set the callback handlers
3662	//
3663	ltms->CallbackPtr = Callback;
3664	ltms->DestroyPtr = Destroy;
3665	ltms->Next = NULL;
3666	ltms->Prev = NULL;
3667
3668	sem_wait(&(UPnPLifeTime->SyncLock));
3669	if(UPnPLifeTime->LM==NULL)
3670	{
3671		//
3672		// There are no current triggers, so this is the first,
3673		// which also means, the Select timeout may not be short enough, so we need
3674		// to force an unblock, which will then reset the timeout appropriately
3675		//
3676		UPnPLifeTime->LM = ltms;
3677		NeedUnBlock = 1;
3678	}
3679	else
3680	{
3681		//
3682		// There are already triggers, so we just insert this one in sorted order
3683		//
3684		temp = UPnPLifeTime->LM;
3685		while(temp!=NULL)
3686		{
3687			if(ltms->ExpirationTick<=temp->ExpirationTick)
3688			{
3689				ltms->Next = temp;
3690				if(temp->Prev==NULL)
3691				{
3692					//
3693					// This is the shortest trigger, so again, the select timeout
3694					// may not be short enough, so we need to force unblock, to
3695					// recalculate the timeout for the select
3696					//
3697					UPnPLifeTime->LM=ltms;
3698					temp->Prev = ltms;
3699					NeedUnBlock = 1;
3700				}
3701				else
3702				{
3703					//
3704					// This isn't the shortest trigger, so we are gauranteed that the
3705					// MicroStack thread will unblock in time to reset the timeouts
3706					//
3707					ltms->Prev = temp->Prev;
3708					temp->Prev->Next = ltms;
3709					temp->Prev = ltms;
3710				}
3711				break;
3712			}
3713			else if(temp->Next == NULL)
3714			{
3715				//
3716				// If there aren't any more triggers left, this means we have the largest
3717				// trigger, so just tack it on the end
3718				//
3719				ltms->Next = NULL;
3720				ltms->Prev = temp;
3721				temp->Next = ltms;
3722				break;
3723			}
3724			temp = temp->Next;
3725		}
3726	}
3727	if(NeedUnBlock!=0) {ILibForceUnBlockChain(UPnPLifeTime->Chain);}
3728	sem_post(&(UPnPLifeTime->SyncLock));
3729}
3730*/
3731
3732//
3733// An internal method used by the ILibLifeTime methods
3734//
3735/*
3736void ILibLifeTime_Check(void *LifeTimeMonitorObject,fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime)
3737{
3738	struct timeval tv;
3739	unsigned long CurrentTick;
3740	struct LifeTimeMonitorData *Temp, *Temp2, *Temp3, *EVT,*Last=NULL;
3741	struct ILibLifeTime *UPnPLifeTime = (struct ILibLifeTime*)LifeTimeMonitorObject;
3742	int nexttick;
3743
3744	void *TempObject;
3745
3746	EVT = NULL;
3747	sem_wait(&(UPnPLifeTime->SyncLock));
3748	if(UPnPLifeTime->LM!=NULL)
3749	{
3750		//
3751		// Get the current tick count for reference
3752		//
3753		gettimeofday(&tv,NULL);
3754		CurrentTick = (tv.tv_sec*1000) + (tv.tv_usec/1000);
3755		Temp = UPnPLifeTime->LM;
3756		//
3757		// Keep looping until we find a node that doesn't need to be triggered
3758		//
3759		while(Temp!=NULL && Temp->ExpirationTick<=CurrentTick)
3760		{
3761			//
3762			// Since these are in sorted order, EVT will always point to the first
3763			// node that needs to be triggered. Last will point to the last node that
3764			// needs to be triggered. Temp will point to the first node that doesn't
3765			// need to be triggered.
3766			//
3767			EVT = UPnPLifeTime->LM;
3768			Last = Temp;
3769			Temp = Temp->Next;
3770		}
3771		if(EVT != NULL)
3772		{
3773			if(Temp!=NULL)
3774			{
3775				//
3776				// There are still nodes that will need to be triggered later, so reset it.
3777				//
3778				UPnPLifeTime->LM = Temp;
3779				if(UPnPLifeTime->LM!=NULL)
3780				{
3781					UPnPLifeTime->LM->Prev = NULL;
3782				}
3783				Last->Next = NULL;
3784			}
3785			else
3786			{
3787				//
3788				// There are no more nodes that will need to be triggered later.
3789				//
3790				UPnPLifeTime->LM = NULL;
3791			}
3792		}
3793
3794		if(EVT!=NULL)
3795		{
3796			//
3797			// We need to create this queue, because it's possible that someone may try to remove
3798			// this particular node, while we are trying to remove it, which could get tricky. So
3799			// by creating this queue, we can track it.
3800			//
3801			UPnPLifeTime->Reserved = ILibQueue_Create();
3802		}
3803
3804		sem_post(&(UPnPLifeTime->SyncLock));
3805
3806		//
3807		// Iterate through all the triggers that we need to fire
3808		//
3809		while(EVT!=NULL)
3810		{
3811			//ToDo: We may want to check the table below first, before we start triggering
3812			EVT->CallbackPtr(EVT->data);
3813			Temp = EVT;
3814			EVT = EVT->Next;
3815			free(Temp);
3816
3817
3818			//
3819			// After we trigger, we check to see if any that are queued are already going to be
3820			// fired. Lots of times, a trigger may cause a removal, which may already be happening.
3821			//
3822			if(UPnPLifeTime->Reserved!=NULL)
3823			{
3824				ILibQueue_Lock(UPnPLifeTime->Reserved);
3825				Temp3 = NULL;
3826				//
3827				// TempObject is a node that was removed while we are triggering events
3828				// Iterate through all of these
3829				//
3830				TempObject = ILibQueue_DeQueue(UPnPLifeTime->Reserved);
3831				while(TempObject != NULL)
3832				{
3833					//
3834					// We need to iterate through our list of event triggers to see if
3835					// there is a match. If there is we need to remove it.
3836					// Save the root at Temp2, so when we're done, we can set EVT back
3837					// up so we can continue with the event triggers.
3838					//
3839					Temp2 = EVT;
3840					while(EVT!=NULL)
3841					{
3842						if(EVT->data==TempObject)
3843						{
3844							// Found Match, Remove it instead of triggering it
3845							if(EVT->Next!=NULL)
3846							{
3847								EVT->Next->Prev = EVT->Prev;
3848							}
3849							if(EVT->Prev!=NULL)
3850							{
3851								EVT->Prev->Next = EVT->Next;
3852							}
3853							if(Temp2 == EVT)
3854							{
3855								//
3856								// If we removed the root of the event triggers, we need to
3857								// change Temp2, so that when the list is reset, it is set correctly
3858								//
3859								Temp2 = EVT->Next;
3860							}
3861							EVT->Prev = NULL;
3862							EVT->Next = NULL;
3863							//
3864							// ToDo: Temp3 is initialized to NULL, so it looks like dead
3865							// code to me... Need to remove it later.
3866							//
3867							if(Temp3!=NULL)
3868							{
3869								EVT->Next = Temp3;
3870								Temp3 = EVT;
3871							}
3872							break;
3873						}
3874						EVT = EVT->Next;
3875					}
3876					EVT = Temp2;
3877					TempObject = (struct LifeTimeMonitorData*)ILibQueue_DeQueue(UPnPLifeTime->Reserved);
3878				}
3879				ILibQueue_UnLock(UPnPLifeTime->Reserved);
3880
3881				//
3882				// Since none of the queued items were up to be triggered, we can go ahead and
3883				// trigger the Destroy event, because they won't be triggered. I noticed
3884				// that in the ILibLifeTime_Remove, it already triggers the Destroy. However
3885				// since Temp3 was preinitialized to NULL, I don't think this loop will enter
3886				// anyways, because I think it's dead code.
3887				// ToDo: Remove this
3888				//
3889				while(Temp3!=NULL)
3890				{
3891					Temp2 = Temp3->Next;
3892					if(Temp3->DestroyPtr!=NULL) {Temp3->DestroyPtr(Temp3->data);}
3893					free(Temp3);
3894					Temp3 = Temp2;
3895				}
3896			}
3897		}
3898
3899		//
3900		// If there are more triggers that need to be fired later, we need to
3901		// recalculate what the max block time for our select should be
3902		//
3903		if(UPnPLifeTime->LM!=NULL)
3904		{
3905			nexttick = UPnPLifeTime->LM->ExpirationTick-CurrentTick;
3906			if(nexttick<*blocktime) {*blocktime=nexttick;}
3907		}
3908
3909		if(UPnPLifeTime->Reserved!=NULL)
3910		{
3911			//
3912			// Since we already triggered a remove, we can throw away the queue, since
3913			// it's useless now
3914			//
3915			ILibQueue_Lock(UPnPLifeTime->Reserved);
3916			while(ILibQueue_DeQueue(UPnPLifeTime->Reserved)!=NULL);
3917			TempObject = UPnPLifeTime->Reserved;
3918			UPnPLifeTime->Reserved = NULL;
3919			ILibQueue_UnLock(TempObject);
3920			ILibQueue_Destroy(TempObject);
3921		}
3922	}
3923	else
3924	{
3925		sem_post(&(UPnPLifeTime->SyncLock));
3926	}
3927}
3928*/
3929/*! \fn ILibLifeTime_Remove(void *LifeTimeToken, void *data)
3930	\brief Removes a timed callback from an \a ILibLifeTime module
3931	\param LifeTimeToken The \a ILibLifeTime object to remove the callback from
3932	\param data The data object to remove
3933*/
3934/*
3935void ILibLifeTime_Remove(void *LifeTimeToken, void *data)
3936{
3937	struct ILibLifeTime *UPnPLifeTime = (struct ILibLifeTime*)LifeTimeToken;
3938	struct LifeTimeMonitorData *first,*last,*evt,*temp;
3939
3940	evt = last = NULL;
3941	sem_wait(&(UPnPLifeTime->SyncLock));
3942
3943	first = UPnPLifeTime->LM;
3944	while(first!=NULL)
3945	{
3946		if(first->data==data)
3947		{
3948			//
3949			// Save the next pointer for use at end of loop
3950			//
3951			temp = first->Next;
3952
3953			//
3954			// Found a match, now remove it from the list
3955			//
3956			if(first->Prev==NULL)
3957			{
3958				UPnPLifeTime->LM = first->Next;
3959				if(UPnPLifeTime->LM!=NULL)
3960				{
3961					UPnPLifeTime->LM->Prev = NULL;
3962				}
3963			}
3964			else
3965			{
3966				first->Prev->Next = first->Next;
3967				if(first->Next!=NULL)
3968				{
3969					first->Next->Prev = first->Prev;
3970				}
3971			}
3972			if(evt==NULL)
3973			{
3974				//
3975				// If this is the first match, create a new list
3976				//
3977				evt = last = first;
3978				evt->Prev = evt->Next = NULL;
3979			}
3980			else
3981			{
3982				//
3983				// Attach this match to the end of the list of matches
3984				//
3985				last->Next = first;
3986				first->Prev = last;
3987				first->Next = NULL;
3988				last = first;
3989			}
3990			first = temp;
3991		}
3992		else
3993		{
3994			first = first->Next;
3995		}
3996	}
3997
3998	if(UPnPLifeTime->Reserved!=NULL)
3999	{
4000		//
4001		// If this queue exists, that means a bunch of nodes are being triggered.
4002		// If we are trying to remove one that is about to be triggered, we need to
4003		// stop it from being triggered.
4004		//
4005		ILibQueue_Lock(UPnPLifeTime->Reserved);
4006		ILibQueue_EnQueue(UPnPLifeTime->Reserved,data);
4007		ILibQueue_UnLock(UPnPLifeTime->Reserved);
4008	}
4009
4010	//
4011	// Iterate through each node that is to be removed
4012	//
4013	sem_post(&(UPnPLifeTime->SyncLock));
4014	while(evt!=NULL)
4015	{
4016		first = evt->Next;
4017		if(evt->DestroyPtr!=NULL) {evt->DestroyPtr(evt->data);}
4018		free(evt);
4019		evt = first;
4020	}
4021}
4022*/
4023/*! \fn ILibLifeTime_Flush(void *LifeTimeToken)
4024	\brief Flushes all timed callbacks from an ILibLifeTime module
4025	\param LifeTimeToken The \a ILibLifeTime object to flush items from
4026*/
4027/*
4028void ILibLifeTime_Flush(void *LifeTimeToken)
4029{
4030	struct ILibLifeTime *UPnPLifeTime = (struct ILibLifeTime*)LifeTimeToken;
4031	struct LifeTimeMonitorData *temp,*temp2;
4032
4033	sem_wait(&(UPnPLifeTime->SyncLock));
4034
4035	temp = UPnPLifeTime->LM;
4036	UPnPLifeTime->LM = NULL;
4037	sem_post(&(UPnPLifeTime->SyncLock));
4038
4039	while(temp!=NULL)
4040	{
4041		temp2 = temp->Next;
4042		if(temp->DestroyPtr!=NULL) {temp->DestroyPtr(temp->data);}
4043		free(temp);
4044		temp = temp2;
4045	}
4046}
4047*/
4048//
4049// An internal method used by the ILibLifeTime methods
4050//
4051/*
4052void ILibLifeTime_Destroy(void *LifeTimeToken)
4053{
4054	struct ILibLifeTime *UPnPLifeTime = (struct ILibLifeTime*)LifeTimeToken;
4055	ILibLifeTime_Flush(LifeTimeToken);
4056	sem_destroy(&(UPnPLifeTime->SyncLock));
4057}
4058*/
4059/*! \fn ILibCreateLifeTime(void *Chain)
4060	\brief Creates an empty ILibLifeTime container for Timed Callbacks.
4061	\para
4062	\b Note: All events are triggered on the MicroStack thread. Developers must \b NEVER block this thread!
4063	\param Chain The chain to add the \aILibLifeTime to
4064	\returns An \a ILibLifeTime token, which is used to add/remove callbacks
4065*/
4066/*
4067void *ILibCreateLifeTime(void *Chain)
4068{
4069	struct ILibLifeTime *RetVal = (struct ILibLifeTime*)malloc(sizeof(struct ILibLifeTime));
4070	RetVal->LM = NULL;
4071	RetVal->PreSelect = &ILibLifeTime_Check;
4072	RetVal->PostSelect = NULL;
4073	RetVal->Destroy = &ILibLifeTime_Destroy;
4074	RetVal->Chain = Chain;
4075	RetVal->Reserved = NULL;
4076	sem_init(&(RetVal->SyncLock),0,1);
4077	ILibAddToChain(Chain,RetVal);
4078	return((void*)RetVal);
4079}
4080*/
4081/*! \fn ILibFindEntryInTable(char *Entry, char **Table)
4082	\param Entry The text to search for
4083	\param Table The Array of strings to search
4084	\return The index into the array
4085*/
4086/*
4087int ILibFindEntryInTable(char *Entry, char **Table)
4088{
4089	int i = 0;
4090
4091	while(Table[i]!=NULL)
4092	{
4093		if(strcmp(Entry,Table[i])==0)
4094		{
4095			return(i);
4096		}
4097		++i;
4098	}
4099
4100	return(-1);
4101}
4102*/
4103/*! \fn ILibLinkedList_Create()
4104	\brief Create an empty Linked List Data Structure
4105	\returns Empty Linked List
4106*/
4107/*
4108void* ILibLinkedList_Create()
4109{
4110	struct ILibLinkedListNode_Root *root = (struct ILibLinkedListNode_Root*)malloc(sizeof(struct ILibLinkedListNode_Root));
4111	root->Head = NULL;
4112	root->Tail = NULL;
4113	root->count=0;
4114	sem_init(&(root->LOCK),0,1);
4115	return(root);
4116}
4117*/
4118/*! \fn ILibLinkedList_ShallowCopy(void *LinkedList)
4119	\brief Create a shallow copy of a linked list
4120	\param LinkedList The linked list to copy
4121	\returns The copy of the supplied linked list
4122*/
4123/*
4124void* ILibLinkedList_ShallowCopy(void *LinkedList)
4125{
4126	void *RetVal = ILibLinkedList_Create();
4127	void *node = ILibLinkedList_GetNode_Head(LinkedList);
4128	while(node!=NULL)
4129	{
4130		ILibLinkedList_AddTail(RetVal,ILibLinkedList_GetDataFromNode(node));
4131		node = ILibLinkedList_GetNextNode(node);
4132	}
4133	return(RetVal);
4134}
4135*/
4136/*! \fn ILibLinkedList_GetNode_Head(void *LinkedList)
4137	\brief Returns the Head node of a linked list data structure
4138	\param LinkedList The linked list
4139	\returns The first node of the linked list
4140*/
4141/*
4142void* ILibLinkedList_GetNode_Head(void *LinkedList)
4143{
4144	return(((struct ILibLinkedListNode_Root*)LinkedList)->Head);
4145}
4146*/
4147/*! \fn ILibLinkedList_GetNode_Tail(void *LinkedList)
4148	\brief Returns the Tail node of a linked list data structure
4149	\param LinkedList The linked list
4150	\returns The last node of the linked list
4151*/
4152/*
4153void* ILibLinkedList_GetNode_Tail(void *LinkedList)
4154{
4155	return(((struct ILibLinkedListNode_Root*)LinkedList)->Tail);
4156}
4157*/
4158/*! \fn ILibLinkedList_GetNextNode(void *LinkedList_Node)
4159	\brief Returns the next node, from the specified linked list node
4160	\param LinkedList_Node The current linked list node
4161	\returns The next adjacent node of the current one
4162*/
4163/*
4164void* ILibLinkedList_GetNextNode(void *LinkedList_Node)
4165{
4166	return(((struct ILibLinkedListNode*)LinkedList_Node)->Next);
4167}
4168*/
4169/*! \fn ILibLinkedList_GetPreviousNode(void *LinkedList_Node)
4170	\brief Returns the previous node, from the specified linked list node
4171	\param LinkedList_Node The current linked list node
4172	\returns The previous adjacent node of the current one
4173*/
4174/*
4175void* ILibLinkedList_GetPreviousNode(void *LinkedList_Node)
4176{
4177	return(((struct ILibLinkedListNode*)LinkedList_Node)->Previous);
4178}
4179*/
4180/*! \fn ILibLinkedList_GetDataFromNode(void *LinkedList_Node)
4181	\brief Returns the data pointed to by a linked list node
4182	\param LinkedList_Node The current linked list node
4183	\returns The data pointer
4184*/
4185/*
4186void *ILibLinkedList_GetDataFromNode(void *LinkedList_Node)
4187{
4188	return(((struct ILibLinkedListNode*)LinkedList_Node)->Data);
4189}
4190*/
4191/*! \fn ILibLinkedList_InsertBefore(void *LinkedList_Node, void *data)
4192	\brief Creates a new element, and inserts it before the given node
4193	\param LinkedList_Node The linked list node
4194	\param data The data pointer to be referenced
4195*/
4196/*
4197void ILibLinkedList_InsertBefore(void *LinkedList_Node, void *data)
4198{
4199	struct ILibLinkedListNode_Root *r = ((struct ILibLinkedListNode*)LinkedList_Node)->Root;
4200	struct ILibLinkedListNode *n = (struct ILibLinkedListNode*) LinkedList_Node;
4201
4202	struct ILibLinkedListNode *newNode = (struct ILibLinkedListNode*)malloc(sizeof(struct ILibLinkedListNode));
4203	newNode->Data = data;
4204	newNode->Root = r;
4205
4206
4207	//
4208	// Attach ourselved before the specified node
4209	//
4210	newNode->Next = n;
4211	newNode->Previous = n->Previous;
4212	if(newNode->Previous!=NULL)
4213	{
4214		newNode->Previous->Next = newNode;
4215	}
4216	n->Previous = newNode;
4217	//
4218	// If we are the first node, we need to adjust the head
4219	//
4220	if(r->Head==n)
4221	{
4222		r->Head = newNode;
4223	}
4224	++r->count;
4225}
4226*/
4227/*! \fn ILibLinkedList_InsertAfter(void *LinkedList_Node, void *data)
4228	\brief Creates a new element, and appends it after the given node
4229	\param LinkedList_Node The linked list node
4230	\param data The data pointer to be referenced
4231*/
4232/*
4233void ILibLinkedList_InsertAfter(void *LinkedList_Node, void *data)
4234{
4235	struct ILibLinkedListNode_Root *r = ((struct ILibLinkedListNode*)LinkedList_Node)->Root;
4236	struct ILibLinkedListNode *n = (struct ILibLinkedListNode*) LinkedList_Node;
4237
4238	struct ILibLinkedListNode *newNode = (struct ILibLinkedListNode*)malloc(sizeof(struct ILibLinkedListNode));
4239	newNode->Data = data;
4240	newNode->Root = r;
4241
4242
4243	//
4244	// Attach ourselved after the specified node
4245	//
4246	newNode->Next = n->Next;
4247	n->Next = newNode;
4248	newNode->Previous = n;
4249	if(newNode->Next!=NULL)
4250	{
4251		newNode->Next->Previous = newNode;
4252	}
4253
4254	//
4255	// If we are the last node, we need to adjust the tail
4256	//
4257	if(r->Tail==n)
4258	{
4259		r->Tail = newNode;
4260	}
4261
4262	++r->count;
4263}
4264*/
4265/*! \fn ILibLinkedList_Remove(void *LinkedList_Node)
4266	\brief Removes the given node from a linked list data structure
4267	\param LinkedList_Node The linked list node to remove
4268*/
4269/*
4270void ILibLinkedList_Remove(void *LinkedList_Node)
4271{
4272	struct ILibLinkedListNode_Root *r = ((struct ILibLinkedListNode*)LinkedList_Node)->Root;
4273	struct ILibLinkedListNode *n = (struct ILibLinkedListNode*) LinkedList_Node;
4274
4275	if(n->Previous!=NULL)
4276	{
4277		n->Previous->Next = n->Next;
4278	}
4279	if(n->Next!=NULL)
4280	{
4281		n->Next->Previous = n->Previous;
4282	}
4283	if(r->Head==n)
4284	{
4285		r->Head = n->Next;
4286	}
4287	if(r->Tail==n)
4288	{
4289		r->Tail = n->Next;
4290	}
4291	--r->count;
4292	free(n);
4293}
4294*/
4295/*! \fn ILibLinkedList_Remove_ByData(void *LinkedList, void *data)
4296	\brief Removes a node from the Linked list, via comparison
4297	\para
4298	Given a data pointer, will traverse the linked list data structure, deleting
4299	elements that point to this data pointer.
4300	\param LinkedList_Node The linked list to traverse
4301	\param data The data pointer to compare
4302*/
4303/*
4304void ILibLinkedList_Remove_ByData(void *LinkedList, void *data)
4305{
4306	struct ILibLinkedListNode_Root *r = (struct ILibLinkedListNode_Root*)LinkedList;
4307	struct ILibLinkedListNode *n,*t;
4308
4309	n = r->Head;
4310	while(n!=NULL)
4311	{
4312		if(n->Data==data)
4313		{
4314			--r->count;
4315			if(n->Previous!=NULL)
4316			{
4317				n->Previous->Next = n->Next;
4318			}
4319			if(n->Next!=NULL)
4320			{
4321				n->Next->Previous = n->Previous;
4322			}
4323			if(r->Head==n)
4324			{
4325				r->Head = n->Next;
4326			}
4327			if(r->Tail==n)
4328			{
4329				r->Tail = n->Next;
4330			}
4331			t = n->Next;
4332			free(n);
4333			n = t;
4334		}
4335		else
4336		{
4337			n = n->Next;
4338		}
4339	}
4340}
4341*/
4342/*! \fn ILibLinkedList_AddHead(void *LinkedList, void *data)
4343	\brief Creates a new element, and inserts it at the top of the linked list.
4344	\param LinkedList The linked list
4345	\param data The data pointer to reference
4346*/
4347/*
4348void ILibLinkedList_AddHead(void *LinkedList, void *data)
4349{
4350	struct ILibLinkedListNode_Root *r = (struct ILibLinkedListNode_Root*)LinkedList;
4351	struct ILibLinkedListNode *newNode = (struct ILibLinkedListNode*)malloc(sizeof(struct ILibLinkedListNode));
4352	newNode->Data = data;
4353	newNode->Root = r;
4354	newNode->Previous = NULL;
4355
4356	newNode->Next = r->Head;
4357	if(r->Head!=NULL)
4358	{
4359		r->Head->Previous = newNode;
4360	}
4361	r->Head = newNode;
4362	if(r->Tail==NULL)
4363	{
4364		r->Tail = newNode;
4365	}
4366
4367	++r->count;
4368}
4369*/
4370/*! \fn ILibLinkedList_AddTail(void *LinkedList, void *data)
4371	\brief Creates a new element, and appends it to the end of the linked list
4372	\param LinkedList The linked list
4373	\param data The data pointer to reference
4374*/
4375/*
4376void ILibLinkedList_AddTail(void *LinkedList, void *data)
4377{
4378	struct ILibLinkedListNode_Root *r = (struct ILibLinkedListNode_Root*)LinkedList;
4379	struct ILibLinkedListNode *newNode = (struct ILibLinkedListNode*)malloc(sizeof(struct ILibLinkedListNode));
4380	newNode->Data = data;
4381	newNode->Root = r;
4382	newNode->Next = NULL;
4383
4384	newNode->Previous = r->Tail;
4385	if(r->Tail!=NULL)
4386	{
4387		r->Tail->Next = newNode;
4388	}
4389	r->Tail = newNode;
4390	if(r->Head==NULL)
4391	{
4392		r->Head = newNode;
4393	}
4394
4395	++r->count;
4396}
4397*/
4398/*! \fn ILibLinkedList_Lock(void *LinkedList)
4399	\brief Locks the linked list with a non-recursive lock
4400	\param LinkedList The linked list
4401*/
4402/*
4403void ILibLinkedList_Lock(void *LinkedList)
4404{
4405	struct ILibLinkedListNode_Root *r = (struct ILibLinkedListNode_Root*)LinkedList;
4406
4407	sem_wait(&(r->LOCK));
4408}
4409*/
4410/*! \fn ILibLinkedList_Lock(void *LinkedList)
4411	\brief Unlocks the linked list's non-recursive lock
4412	\param LinkedList The linked list
4413*/
4414/*
4415void ILibLinkedList_UnLock(void *LinkedList)
4416{
4417	struct ILibLinkedListNode_Root *r = (struct ILibLinkedListNode_Root*)LinkedList;
4418
4419	sem_post(&(r->LOCK));
4420}
4421*/
4422
4423/*! \fn ILibLinkedList_Destroy(void *LinkedList)
4424	\brief Frees the resources used by the linked list
4425	\b Note: The data pointer referenced needs to be freed by the user if required
4426	\param LinkedList The linked list
4427*/
4428/*
4429void ILibLinkedList_Destroy(void *LinkedList)
4430{
4431	struct ILibLinkedListNode_Root *r = (struct ILibLinkedListNode_Root*)LinkedList;
4432
4433	while(r->Head!=NULL)
4434	{
4435		ILibLinkedList_Remove(ILibLinkedList_GetNode_Head(LinkedList));
4436	}
4437	sem_destroy(&(r->LOCK));
4438	free(r);
4439}
4440*/
4441
4442/*! \fn ILibLinkedList_GetCount(void *LinkedList)
4443	\brief Returns the number of nodes in the linked list
4444	\param LinkedList The linked list
4445	\returns Number of elements in the linked list
4446*/
4447/*
4448long ILibLinkedList_GetCount(void *LinkedList)
4449{
4450	return(((struct ILibLinkedListNode_Root*)LinkedList)->count);
4451}
4452*/
4453/*! \fn ILibReadFileFromDiskEx(char **Target, char *FileName)
4454	\brief Reads a file into a char *
4455	\para
4456	\b Note: \a Target must be freed
4457	\param Target Pointer to char* that will contain the data
4458	\param FileName Filename of the file to read
4459	\returns length of the data read
4460*/
4461int ILibReadFileFromDiskEx(char **Target, char *FileName)
4462{
4463	char *buffer;
4464	int SourceFileLength;
4465	FILE *SourceFile = fopen(FileName,"rb");
4466
4467	if(SourceFile==NULL)
4468	{
4469		return(0);
4470	}
4471
4472	fseek(SourceFile,0,SEEK_END);
4473
4474	SourceFileLength = (int)ftell(SourceFile);
4475
4476	fseek(SourceFile,0,SEEK_SET);
4477	buffer = (char*)malloc(SourceFileLength);
4478	fread(buffer,sizeof(char),SourceFileLength,SourceFile);
4479	fclose(SourceFile);
4480
4481	*Target = buffer;
4482	return(SourceFileLength);
4483}
4484
4485
4486/*! \fn ILibReadFileFromDisk(char *FileName)
4487	\brief Reads a file into a char *
4488	\para
4489	\b Note: Data must be null terminated
4490	\param FileName Filename of the file to read
4491	\returns data read
4492*/
4493char *ILibReadFileFromDisk(char *FileName, int *FileLen)
4494{
4495	char *RetVal;
4496	*FileLen = ILibReadFileFromDiskEx(&RetVal,FileName);
4497	return(RetVal);
4498}
4499
4500/*! \fn ILibWriteStringToDisk(char *FileName, char *data)
4501	\brief Writes a null terminated string to disk
4502	\para
4503	\b Note: Files that already exist will be overwritten
4504	\param FileName Filename of the file to write
4505	\param data data to write
4506*/
4507/*
4508void ILibWriteStringToDisk(char *FileName, char *data)
4509{
4510	FILE *SourceFile = fopen(FileName,"wb");
4511	if(SourceFile!=NULL)
4512	{
4513		fwrite(data,sizeof(char),(int)strlen(data),SourceFile);
4514		fclose(SourceFile);
4515	}
4516}
4517*/
4518#endif
4519
4520