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] == ';') // " 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] == ';') // ' 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] == ';') // & 3505 { 3506 // Ampersand 3507 i[0] = '&'; 3508 j += 4; 3509 } 3510 else if (j[0] == '&' && j[1] == 'l' && j[2] == 't' && j[3] == ';') // < 3511 { 3512 // Less Than 3513 i[0] = '<'; 3514 j += 3; 3515 } 3516 else if (j[0] == '&' && j[1] == 'g' && j[2] == 't' && j[3] == ';') // > 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, """, 6); 3594 out = out + 6; 3595 } 3596 else 3597 if (indata[i] == '\'') 3598 { 3599 memcpy(out, "'", 6); 3600 out = out + 6; 3601 } 3602 else 3603 if (indata[i] == '<') 3604 { 3605 memcpy(out, "<", 4); 3606 out = out + 4; 3607 } 3608 else 3609 if (indata[i] == '>') 3610 { 3611 memcpy(out, ">", 4); 3612 out = out + 4; 3613 } 3614 else 3615 if (indata[i] == '&') 3616 { 3617 memcpy(out, "&", 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