michael@0: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: ** formdata.c michael@0: ** michael@0: ** Play utility to parse up form get data into name value pairs. michael@0: */ michael@0: michael@0: #include "formdata.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: michael@0: static void unhexcape(char* inPlace) michael@0: /* michael@0: ** Real low tech unhexcaper.... michael@0: ** michael@0: ** inPlace string to decode, in place as it were. michael@0: */ michael@0: { michael@0: if(NULL != inPlace) michael@0: { michael@0: int index1 = 0; michael@0: int index2 = 0; michael@0: int theLen = strlen(inPlace); michael@0: michael@0: for(; index1 <= theLen; index1++) michael@0: { michael@0: if('%' == inPlace[index1] && '\0' != inPlace[index1 + 1] && '\0' != inPlace[index1 + 2]) michael@0: { michael@0: int unhex = 0; michael@0: michael@0: if('9' >= inPlace[index1 + 1]) michael@0: { michael@0: unhex |= ((inPlace[index1 + 1] - '0') << 4); michael@0: } michael@0: else michael@0: { michael@0: unhex |= ((toupper(inPlace[index1 + 1]) - 'A' + 10) << 4); michael@0: } michael@0: michael@0: if('9' >= inPlace[index1 + 2]) michael@0: { michael@0: unhex |= (inPlace[index1 + 2] - '0'); michael@0: } michael@0: else michael@0: { michael@0: unhex |= (toupper(inPlace[index1 + 2]) - 'A' + 10); michael@0: } michael@0: michael@0: index1 += 2; michael@0: inPlace[index1] = unhex; michael@0: } michael@0: michael@0: inPlace[index2++] = inPlace[index1]; michael@0: } michael@0: } michael@0: } michael@0: michael@0: michael@0: FormData* FormData_Create(const char* inFormData) michael@0: { michael@0: FormData* retval = NULL; michael@0: michael@0: if(NULL != inFormData) michael@0: { michael@0: FormData* container = NULL; michael@0: michael@0: /* michael@0: ** Allocate form data container. michael@0: */ michael@0: container = (FormData*)calloc(1, sizeof(FormData)); michael@0: if(NULL != container) michael@0: { michael@0: /* michael@0: ** Dup the incoming form data. michael@0: */ michael@0: container->mStorage = strdup(inFormData); michael@0: if(NULL != container->mStorage) michael@0: { michael@0: char* traverse = NULL; michael@0: unsigned nvpairs = 1; michael@0: unsigned storeLen = 0; michael@0: michael@0: /* michael@0: ** Count the number of pairs we are going to have. michael@0: ** We do this by counting '&' + 1. michael@0: */ michael@0: for(traverse = container->mStorage; '\0' != *traverse; traverse++) michael@0: { michael@0: if('&' == *traverse) michael@0: { michael@0: nvpairs++; michael@0: } michael@0: } michael@0: storeLen = (unsigned)(traverse - container->mStorage); michael@0: michael@0: /* michael@0: ** Allocate space for our names and values. michael@0: */ michael@0: container->mNArray = (char**)calloc(nvpairs * 2, sizeof(char*)); michael@0: if(NULL != container->mNArray) michael@0: { michael@0: char* amp = NULL; michael@0: char* equ = NULL; michael@0: michael@0: container->mVArray = &container->mNArray[nvpairs]; michael@0: michael@0: /* michael@0: ** Go back over the storage. michael@0: ** Fill in the names and values as we go. michael@0: ** Terminate on dividing '=' and '&' characters. michael@0: ** Increase the count of items as we go. michael@0: */ michael@0: for(traverse = container->mStorage; NULL != traverse; container->mNVCount++) michael@0: { michael@0: container->mNArray[container->mNVCount] = traverse; michael@0: michael@0: amp = strchr(traverse, '&'); michael@0: equ = strchr(traverse, '='); michael@0: traverse = NULL; michael@0: michael@0: if(NULL != equ && (NULL == amp || equ < amp)) michael@0: { michael@0: *equ++ = '\0'; michael@0: michael@0: container->mVArray[container->mNVCount] = equ; michael@0: } michael@0: else michael@0: { michael@0: container->mVArray[container->mNVCount] = (container->mStorage + storeLen); michael@0: } michael@0: michael@0: if(NULL != amp) michael@0: { michael@0: *amp++ = '\0'; michael@0: michael@0: traverse = amp; michael@0: } michael@0: michael@0: unhexcape(container->mNArray[container->mNVCount]); michael@0: unhexcape(container->mVArray[container->mNVCount]); michael@0: } michael@0: michael@0: retval = container; michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* michael@0: ** If we failed, cleanup. michael@0: */ michael@0: if(NULL == retval) michael@0: { michael@0: FormData_Destroy(container); michael@0: } michael@0: } michael@0: michael@0: return retval; michael@0: } michael@0: michael@0: michael@0: void FormData_Destroy(FormData* inDestroy) michael@0: { michael@0: if(NULL != inDestroy) michael@0: { michael@0: unsigned traverse = 0; michael@0: michael@0: for(traverse = 0; traverse < inDestroy->mNVCount; traverse++) michael@0: { michael@0: if(NULL != inDestroy->mNArray) michael@0: { michael@0: inDestroy->mNArray[traverse] = NULL; michael@0: } michael@0: if(NULL != inDestroy->mVArray) michael@0: { michael@0: inDestroy->mVArray[traverse] = NULL; michael@0: } michael@0: } michael@0: inDestroy->mNVCount = 0; michael@0: michael@0: if(NULL != inDestroy->mStorage) michael@0: { michael@0: free(inDestroy->mStorage); michael@0: inDestroy->mStorage = NULL; michael@0: } michael@0: michael@0: if(NULL != inDestroy->mNArray) michael@0: { michael@0: free(inDestroy->mNArray); michael@0: inDestroy->mNArray = NULL; michael@0: inDestroy->mVArray = NULL; michael@0: } michael@0: michael@0: free(inDestroy); michael@0: inDestroy = NULL; michael@0: } michael@0: }