forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			238 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 | |
|  *
 | |
|  * ***** BEGIN LICENSE BLOCK *****
 | |
|  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 | |
|  *
 | |
|  * The contents of this file are subject to the Mozilla Public License Version
 | |
|  * 1.1 (the "License"); you may not use this file except in compliance with
 | |
|  * the License. You may obtain a copy of the License at
 | |
|  * http://www.mozilla.org/MPL/
 | |
|  *
 | |
|  * Software distributed under the License is distributed on an "AS IS" basis,
 | |
|  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | |
|  * for the specific language governing rights and limitations under the
 | |
|  * License.
 | |
|  *
 | |
|  * The Original Code is formdata.c code, released
 | |
|  * May 9, 2002.
 | |
|  *
 | |
|  * The Initial Developer of the Original Code is
 | |
|  * Netscape Communications Corporation.
 | |
|  * Portions created by the Initial Developer are Copyright (C) 2002
 | |
|  * the Initial Developer. All Rights Reserved.
 | |
|  *
 | |
|  * Contributor(s):
 | |
|  *   Garrett Arch Blythe, 09-May-2002
 | |
|  *
 | |
|  * Alternatively, the contents of this file may be used under the terms of
 | |
|  * either the GNU General Public License Version 2 or later (the "GPL"), or
 | |
|  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 | |
|  * in which case the provisions of the GPL or the LGPL are applicable instead
 | |
|  * of those above. If you wish to allow use of your version of this file only
 | |
|  * under the terms of either the GPL or the LGPL, and not to allow others to
 | |
|  * use your version of this file under the terms of the MPL, indicate your
 | |
|  * decision by deleting the provisions above and replace them with the notice
 | |
|  * and other provisions required by the GPL or the LGPL. If you do not delete
 | |
|  * the provisions above, a recipient may use your version of this file under
 | |
|  * the terms of any one of the MPL, the GPL or the LGPL.
 | |
|  *
 | |
|  * ***** END LICENSE BLOCK ***** */
 | |
| 
 | |
| /*
 | |
| **  formdata.c
 | |
| **
 | |
| **  Play utility to parse up form get data into name value pairs.
 | |
| */
 | |
| 
 | |
| #include "formdata.h"
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <ctype.h>
 | |
| 
 | |
| 
 | |
| static void unhexcape(char* inPlace)
 | |
| /*
 | |
| **  Real low tech unhexcaper....
 | |
| **
 | |
| **  inPlace     string to decode, in place as it were.
 | |
| */
 | |
| {
 | |
|     if(NULL != inPlace)
 | |
|     {
 | |
|         int index1 = 0;
 | |
|         int index2 = 0;
 | |
|         int theLen = strlen(inPlace);
 | |
|         
 | |
|         for(; index1 <= theLen; index1++)
 | |
|         {
 | |
|             if('%' == inPlace[index1] && '\0' != inPlace[index1 + 1] && '\0' != inPlace[index1 + 2])
 | |
|             {
 | |
|                 int unhex = 0;
 | |
|                 
 | |
|                 if('9' >= inPlace[index1 + 1])
 | |
|                 {
 | |
|                     unhex |= ((inPlace[index1 + 1] - '0') << 4);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     unhex |= ((toupper(inPlace[index1 + 1]) - 'A' + 10) << 4);
 | |
|                 }
 | |
|                 
 | |
|                 if('9' >= inPlace[index1 + 2])
 | |
|                 {
 | |
|                     unhex |= (inPlace[index1 + 2] - '0');
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     unhex |= (toupper(inPlace[index1 + 2]) - 'A' + 10);
 | |
|                 }
 | |
|                 
 | |
|                 index1 += 2;
 | |
|                 inPlace[index1] = unhex;
 | |
|             }
 | |
|             
 | |
|             inPlace[index2++] = inPlace[index1];
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| FormData* FormData_Create(const char* inFormData)
 | |
| {
 | |
|     FormData* retval = NULL;
 | |
| 
 | |
|     if(NULL != inFormData)
 | |
|     {
 | |
|         FormData* container = NULL;
 | |
| 
 | |
|         /*
 | |
|         **  Allocate form data container.
 | |
|         */
 | |
|         container = (FormData*)calloc(1, sizeof(FormData));
 | |
|         if(NULL != container)
 | |
|         {
 | |
|             /*
 | |
|             **  Dup the incoming form data.
 | |
|             */
 | |
|             container->mStorage = strdup(inFormData);
 | |
|             if(NULL != container->mStorage)
 | |
|             {
 | |
|                 char* traverse = NULL;
 | |
|                 unsigned nvpairs = 1;
 | |
|                 unsigned storeLen = 0;
 | |
| 
 | |
|                 /*
 | |
|                 **  Count the number of pairs we are going to have.
 | |
|                 **  We do this by counting '&' + 1.
 | |
|                 */
 | |
|                 for(traverse = container->mStorage; '\0' != *traverse; traverse++)
 | |
|                 {
 | |
|                     if('&' == *traverse)
 | |
|                     {
 | |
|                         nvpairs++;
 | |
|                     }
 | |
|                 }
 | |
|                 storeLen = (unsigned)(traverse - container->mStorage);
 | |
| 
 | |
|                 /*
 | |
|                 **  Allocate space for our names and values.
 | |
|                 */
 | |
|                 container->mNArray = (char**)calloc(nvpairs * 2, sizeof(char*));
 | |
|                 if(NULL != container->mNArray)
 | |
|                 {
 | |
|                     char* amp = NULL;
 | |
|                     char* equ = NULL;
 | |
| 
 | |
|                     container->mVArray = &container->mNArray[nvpairs];
 | |
| 
 | |
|                     /*
 | |
|                     **  Go back over the storage.
 | |
|                     **  Fill in the names and values as we go.
 | |
|                     **  Terminate on dividing '=' and '&' characters.
 | |
|                     **  Increase the count of items as we go.
 | |
|                     */
 | |
|                     for(traverse = container->mStorage; NULL != traverse; container->mNVCount++)
 | |
|                     {
 | |
|                         container->mNArray[container->mNVCount] = traverse;
 | |
| 
 | |
|                         amp = strchr(traverse, '&');
 | |
|                         equ = strchr(traverse, '=');
 | |
|                         traverse = NULL;
 | |
| 
 | |
|                         if(NULL != equ && (NULL == amp || equ < amp))
 | |
|                         {
 | |
|                             *equ++ = '\0';
 | |
| 
 | |
|                             container->mVArray[container->mNVCount] = equ;
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             container->mVArray[container->mNVCount] = (container->mStorage + storeLen);
 | |
|                         }
 | |
| 
 | |
|                         if(NULL != amp)
 | |
|                         {
 | |
|                             *amp++ = '\0';
 | |
| 
 | |
|                             traverse = amp;
 | |
|                         }
 | |
| 
 | |
|                         unhexcape(container->mNArray[container->mNVCount]);
 | |
|                         unhexcape(container->mVArray[container->mNVCount]);
 | |
|                     }
 | |
| 
 | |
|                     retval = container;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /*
 | |
|         **  If we failed, cleanup.
 | |
|         */
 | |
|         if(NULL == retval)
 | |
|         {
 | |
|             FormData_Destroy(container);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| 
 | |
| void FormData_Destroy(FormData* inDestroy)
 | |
| {
 | |
|     if(NULL != inDestroy)
 | |
|     {
 | |
|         unsigned traverse = 0;
 | |
| 
 | |
|         for(traverse = 0; traverse < inDestroy->mNVCount; traverse++)
 | |
|         {
 | |
|             if(NULL != inDestroy->mNArray)
 | |
|             {
 | |
|                 inDestroy->mNArray[traverse] = NULL;
 | |
|             }
 | |
|             if(NULL != inDestroy->mVArray)
 | |
|             {
 | |
|                 inDestroy->mVArray[traverse] = NULL;
 | |
|             }
 | |
|         }
 | |
|         inDestroy->mNVCount = 0;
 | |
| 
 | |
|         if(NULL != inDestroy->mStorage)
 | |
|         {
 | |
|             free(inDestroy->mStorage);
 | |
|             inDestroy->mStorage = NULL;
 | |
|         }
 | |
| 
 | |
|         if(NULL != inDestroy->mNArray)
 | |
|         {
 | |
|             free(inDestroy->mNArray);
 | |
|             inDestroy->mNArray = NULL;
 | |
|             inDestroy->mVArray = NULL;
 | |
|         }
 | |
| 
 | |
|         free(inDestroy);
 | |
|         inDestroy = NULL;
 | |
|     }
 | |
| }
 | 
