Files
maui/src/mcom/MXML.c
T
dev 9a0042c61e Initial revision
git-svn-id: svn://opensvn.adaptivecomputing.com/maui/trunk@2 3f5042e3-fb1d-0410-be18-d6ca2573e517
2005-07-12 21:12:53 +00:00

1966 lines
32 KiB
C

/* HEADER */
/* *
* Contains: *
* *
* */
#include "mcom.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* prototypes */
int MXMLGetChild(mxml_t *,char *,int *,mxml_t **);
int MXMLAddE(mxml_t *,mxml_t *);
int MXMLGetAttrF(mxml_t *,char *,int *,void *,enum MDataFormatEnum,int);
int MXMLGetAttr(mxml_t *,char *,int *,char *,int);
int MXMLToString(mxml_t *,char *,int,char **,mbool_t);
int MXMLAppendAttr(mxml_t *,char *,char *,char);
/* END prototypes */
extern int MSecCompress(unsigned char *,unsigned int,unsigned char *,char *);
extern int MSecDecompress(unsigned char *,unsigned int,unsigned char *,unsigned int,unsigned char **,char *);
int MXMLExtractE(
mxml_t *E, /* I */
mxml_t *C, /* I */
mxml_t **CP) /* O (optional) */
{
int cindex;
if ((E == NULL) || (C == NULL))
{
return(FAILURE);
}
for (cindex = 0;cindex < E->CCount;cindex++)
{
if (C != E->C[cindex])
{
if (MXMLExtractE(E->C[cindex],C,CP) == SUCCESS)
{
return(SUCCESS);
}
continue;
}
if (CP != NULL)
*CP = E->C[cindex];
E->C[cindex] = NULL;
return(SUCCESS);
} /* END for (cindex) */
return(FAILURE);
} /* MXMLExtractE() */
int MXMLMergeE(
mxml_t *Dst, /* I */
mxml_t *Src, /* I */
char Delim) /* I */
{
int cindex;
int aindex;
/* parent and child must have identical element structure */
if ((Dst == NULL) || (Src == NULL))
{
return(FAILURE);
}
for (cindex = 0;cindex < Dst->CCount;cindex++)
{
/* recursively call all children */
if (MXMLMergeE(Dst->C[cindex],Src->C[cindex],Delim) == FAILURE)
{
return(FAILURE);
}
/* merge all attributes */
for (aindex = 0;aindex < Src->ACount;aindex++)
{
MXMLAppendAttr(
Dst,
Src->AName[aindex],
(char *)Src->AVal[aindex],
Delim);
}
} /* END for (cindex) */
return(SUCCESS);
} /* MXMLMergeE() */
int MXMLSetChild(
mxml_t *E, /* I */
char *CName, /* I */
mxml_t **CE) /* O */
{
if (CE != NULL)
*CE = NULL;
if ((E == NULL) || (CName == NULL))
{
return(FAILURE);
}
if (MXMLGetChild(E,CName,NULL,CE) == SUCCESS)
{
/* located existing child */
return(SUCCESS);
}
/* create new child */
if ((*CE = (mxml_t *)calloc(1,sizeof(mxml_t))) == NULL)
{
return(FAILURE);
}
MXMLAddE(E,*CE);
if (CName != NULL)
(*CE)->Name = strdup(CName);
return(SUCCESS);
} /* END MXMLSetChild() */
int MXMLCreateE(
mxml_t **E, /* O */
char *Name) /* I (optional) */
{
/* NOTE: should 'Name' be mandatory? */
if (E == NULL)
{
return(FAILURE);
}
if ((*E = (mxml_t *)calloc(1,sizeof(mxml_t))) == NULL)
{
return(FAILURE);
}
if ((Name != NULL) && (Name[0] != '\0'))
(*E)->Name = strdup(Name);
return(SUCCESS);
} /* END MXMLCreateE() */
int MXMLDestroyE(
mxml_t **EP) /* I (modified) */
{
int index;
mxml_t *E;
if (EP == NULL)
{
return(FAILURE);
}
E = *EP;
if (E == NULL)
{
return(SUCCESS);
}
if (E->C != NULL)
{
/* destroy children */
for (index = 0;index < E->CCount;index++)
{
if (E->C[index] == NULL)
continue;
MXMLDestroyE(&E->C[index]);
} /* END for (index) */
free(E->C);
} /* END if (E->C != NULL) */
/* free attributes */
if (E->AName != NULL)
{
for (index = 0;index < E->ACount;index++)
{
if (E->AName[index] == NULL)
break;
free(E->AName[index]);
if ((E->AVal != NULL) && (E->AVal[index] != NULL))
free(E->AVal[index]);
} /* END for (index) */
if (E->AVal != NULL)
{
free(E->AVal);
}
if (E->AName != NULL)
{
free(E->AName);
}
} /* END if (E->AName != NULL) */
/* free name */
if (E->Name != NULL)
free(E->Name);
if (E->Val != NULL)
free(E->Val);
free(E);
*EP = NULL;
return(SUCCESS);
} /* END MXMLDestroyE() */
int MXMLSetAttr(
mxml_t *E, /* I (modified) */
char *A, /* I */
void *V, /* I */
enum MDataFormatEnum Format) /* I */
{
int aindex;
int iindex;
int rc;
char tmpLine[MMAX_LINE];
char *ptr;
/* NOTE: overwrite existing attr if found */
if ((E == NULL) || (A == NULL))
{
return(FAILURE);
}
if (V != NULL)
{
switch (Format)
{
case mdfString:
default:
ptr = (char *)V;
break;
case mdfInt:
sprintf(tmpLine,"%d",
*(int *)V);
ptr = tmpLine;
break;
case mdfLong:
sprintf(tmpLine,"%ld",
*(long *)V);
ptr = tmpLine;
break;
case mdfDouble:
sprintf(tmpLine,"%f",
*(double *)V);
ptr = tmpLine;
break;
} /* END switch(Format) */
}
else
{
tmpLine[0] = '\0';
ptr = tmpLine;
}
/* initialize attribute table */
if (E->AName == NULL)
{
E->AName = (char **)calloc(1,sizeof(char *) * MMAX_XMLATTR);
E->AVal = (char **)calloc(1,sizeof(char *) * MMAX_XMLATTR);
if ((E->AName == NULL) || (E->AVal == NULL))
{
return(FAILURE);
}
E->ASize = MMAX_XMLATTR;
E->ACount = 0;
}
/* insert in alphabetical order */
/* overwrite existing attribute if found */
iindex = 0;
rc = 0;
for (aindex = 0;aindex < E->ACount;aindex++)
{
rc = strcmp(E->AName[aindex],A);
if (rc > 0)
break;
if (rc == 0)
{
iindex = aindex;
break;
}
iindex = aindex + 1;
} /* END for (aindex) */
if (aindex >= E->ACount)
{
iindex = aindex;
if (aindex >= E->ASize)
{
/* allocate memory */
E->AName = (char **)realloc(E->AName,sizeof(char *) * MAX(16,E->ASize << 1));
E->AVal = (char **)realloc(E->AVal,sizeof(char *) * MAX(16,E->ASize << 1));
if ((E->AVal == NULL) || (E->AName == NULL))
{
E->ASize = 0;
return(FAILURE);
}
E->ASize <<= 1;
}
} /* END if (aindex >= E->ACount) */
if ((ptr == NULL) && (aindex >= E->ACount))
{
/* no action required for empty attribute */
return(SUCCESS);
}
/* prepare insertion point */
if (rc != 0)
{
for (aindex = E->ACount - 1;aindex >= iindex;aindex--)
{
E->AVal[aindex + 1] = E->AVal[aindex];
E->AName[aindex + 1] = E->AName[aindex];
} /* END for (aindex) */
E->AVal[aindex + 1] = NULL;
E->AName[aindex + 1] = NULL;
} /* END if (rc != 0) */
if ((iindex < E->ACount) && (E->AVal[iindex] != NULL))
free(E->AVal[iindex]);
E->AVal[iindex] = strdup((ptr != NULL) ? ptr : "");
if ((rc != 0) || (E->AName[iindex] == NULL))
{
E->AName[iindex] = strdup(A);
E->ACount++;
}
return(SUCCESS);
} /* END MXMLSetAttr() */
int MXMLAppendAttr(
mxml_t *E, /* I root element */
char *AName, /* I */
char *AVal, /* I */
char Delim) /* I */
{
int ATok;
int len;
char VBuf[MMAX_LINE];
if ((E == NULL) || (AName == NULL) || (AVal == NULL))
{
return(FAILURE);
}
ATok = -1;
if (MXMLGetAttr(E,AName,&ATok,VBuf,sizeof(VBuf)) == SUCCESS)
{
char DString[2];
len = strlen(E->AVal[ATok]) + strlen(AVal) + 2;
E->AVal[ATok] = (char *)realloc(
E->AVal[ATok],
len);
if (E->AVal[ATok] == NULL)
{
return(FAILURE);
}
DString[0] = Delim;
DString[1] = '\0';
/* just allocated adequate space, should not be able to overflow */
strcat(E->AVal[ATok],DString);
strcat(E->AVal[ATok],AVal);
}
else if (MXMLSetAttr(E,AName,AVal,mdfString) == FAILURE)
{
return(FAILURE);
}
return(SUCCESS);
} /* END MXMLAppendAttr() */
int MXMLSetVal(
mxml_t *E, /* I (modified) */
void *V, /* I */
enum MDataFormatEnum Format) /* I */
{
char tmpLine[MMAX_LINE];
char *ptr;
if ((E == NULL) || (V == NULL))
{
return(FAILURE);
}
if (E->Val != NULL)
{
free(E->Val);
E->Val = NULL;
}
switch(Format)
{
case mdfString:
default:
ptr = (char *)V;
break;
case mdfInt:
sprintf(tmpLine,"%d",
*(int *)V);
ptr = tmpLine;
break;
case mdfLong:
sprintf(tmpLine,"%ld",
*(long *)V);
ptr = tmpLine;
break;
case mdfDouble:
sprintf(tmpLine,"%f",
*(double *)V);
ptr = tmpLine;
break;
} /* END switch(Format) */
E->Val = strdup(ptr);
/* strip '<' symbols NOTE: ignore '<' symbol in attrs */
/* NOTE: must replace temp hack 14 w/ &lt; */
for (ptr = strchr(E->Val,'<');ptr != NULL;ptr = strchr(ptr,'<'))
*ptr = (char)14;
return(SUCCESS);
} /* END MXMLSetVal() */
int MXMLAddE(
mxml_t *E, /* I (modified) */
mxml_t *C) /* I (required) */
{
if ((E == NULL) || (C == NULL))
{
return(FAILURE);
}
if (E->CCount >= E->CSize)
{
if (E->C == NULL)
{
E->C = (mxml_t **)calloc(1,sizeof(mxml_t *) * MDEF_XMLICCOUNT);
E->CSize = MDEF_XMLICCOUNT;
}
else
{
E->C = (mxml_t **)realloc(E->C,sizeof(mxml_t *) * MAX(16,E->CSize << 1));
E->CSize <<= 1;
}
if (E->C == NULL)
{
/* cannot alloc memory */
return(FAILURE);
} /* END if (E->C == NULL) */
} /* END if (E->CCount >= E->CSize) */
E->C[E->CCount] = C;
E->CCount++;
return(SUCCESS);
} /* END MXMLAddE() */
int MXMLToXString(
mxml_t *E, /* I */
char **Buf, /* O (populated/modified) */
int *BufSize, /* I/O */
int MaxBufSize, /* I */
char **Tail, /* O */
mbool_t NoCompress) /* I */
{
int NewSize;
/* NOTE: MXMLToString() only fails due to lack of space */
if ((E == NULL) || (Buf == NULL))
{
return(FAILURE);
}
/* allocate initial memory if required */
if (*Buf == NULL)
{
NewSize = MMAX_BUFFER;
if ((*Buf = (char *)malloc(NewSize)) == NULL)
{
/* cannot allocate buffer */
return(FAILURE);
}
if (BufSize != NULL)
*BufSize = MMAX_BUFFER;
}
else
{
if (BufSize != NULL)
{
NewSize = *BufSize;
}
else
{
return(FAILURE);
}
}
while (MXMLToString(
E,
*Buf,
NewSize,
Tail,
NoCompress) == FAILURE)
{
if (NewSize >= MaxBufSize)
{
return(FAILURE);
}
NewSize = MIN(NewSize << 1,MaxBufSize);
if ((*Buf = (char *)realloc(*Buf,NewSize)) == NULL)
{
/* cannot allocate buffer */
return(FAILURE);
}
if (BufSize != NULL)
*BufSize = NewSize;
} /* END while (MXMLToString() == FAILURE) */
return(SUCCESS);
} /* END MXMLToXString() */
int MXMLToString(
mxml_t *E, /* I */
char *Buf, /* O */
int BufSize, /* I */
char **Tail, /* O */
mbool_t NoCompress) /* I (compress Data element) */
{
char NewLine[MMAX_BUFFER];
int index;
int BSpace;
char *BPtr;
char *tail;
int len;
if (Buf != NULL)
{
Buf[0] = '\0';
}
if ((E == NULL) || (Buf == NULL))
{
return(FAILURE);
}
if (BufSize < MMAX_NAME)
{
return(FAILURE);
}
BPtr = Buf;
BSpace = BufSize;
/* display header */
BPtr[0] = '<';
BPtr++;
BSpace--;
if (E->Name != NULL)
{
len = strlen(E->Name);
if (len >= BSpace)
{
/* insufficient space */
BPtr[0] = '\0';
return(FAILURE);
}
strcpy(BPtr,E->Name);
BSpace -= len;
BPtr += len;
}
else
{
strcpy(BPtr,"NA");
len = strlen("NA");
BPtr += len;
BSpace -= len;
}
/* display attributes */
for (index = 0;index < E->ACount;index++)
{
/* FORMAT: <NAME>="<VAL>" */
BPtr[0] = ' ';
BPtr++;
BSpace--;
len = strlen(E->AName[index]);
if (len >= BSpace)
{
/* insufficient space */
BPtr[0] = '\0';
return(FAILURE);
}
strcpy(BPtr,E->AName[index]);
BSpace -= len;
BPtr += len;
BPtr[0] = '=';
BPtr++;
BSpace--;
BPtr[0] = '"';
BPtr++;
BSpace--;
if ((strchr(E->AVal[index],'<') != NULL) ||
(strchr(E->AVal[index],'>') != NULL))
{
/* must replace '<' with '&lt;' and '>' with '&gt;' */
int index1;
int index2 = 0;
len = strlen(E->AVal[index]);
for (index1 = 0;index1 < len;index1++)
{
if (E->AVal[index][index1] == '<')
{
NewLine[index2++] = '&';
NewLine[index2++] = 'l';
NewLine[index2++] = 't';
NewLine[index2++] = ';';
}
else if (E->AVal[index][index1] == '>')
{
NewLine[index2++] = '&';
NewLine[index2++] = 'g';
NewLine[index2++] = 't';
NewLine[index2++] = ';';
}
else
{
NewLine[index2++] = E->AVal[index][index1];
}
} /* END for (index1) */
NewLine[index2] = '\0';
len = strlen(NewLine);
if (len >= BSpace)
{
/* insufficient space */
BPtr[0] = '\0';
return(FAILURE);
}
strcpy(BPtr,NewLine);
} /* END if (strchr(E->AVal,'<')...) */
else
{
len = strlen(E->AVal[index]);
if (len >= BSpace)
{
/* insufficient space */
BPtr[0] = '\0';
return(FAILURE);
}
strcpy(BPtr,E->AVal[index]);
} /* END else */
BSpace -= len;
BPtr += len;
BPtr[0] = '"';
BPtr++;
BSpace--;
} /* END for (index) */
BPtr[0] = '>';
BPtr++;
BSpace--;
if (E->Val != NULL)
{
len = strlen(E->Val);
if (len >= BSpace)
{
/* insufficient space */
BPtr[0] = '\0';
return(FAILURE);
}
strcpy(BPtr,E->Val);
BSpace -= len;
BPtr += len;
}
/* display children */
for (index = 0;index < E->CCount;index++)
{
if (E->C[index] == NULL)
continue;
if (MXMLToString(E->C[index],BPtr,BSpace,&tail,NoCompress) == FAILURE)
{
return(FAILURE);
}
len = strlen(BPtr);
BSpace -= len;
BPtr += len;
} /* END for (index) */
/* display footer */
if (E->Name != NULL)
{
len = strlen(E->Name);
}
else
{
len = strlen("NA");
}
if (BSpace < len + 4)
{
BPtr[0] = '\0';
return(FAILURE);
}
BPtr[0] = '<';
BPtr++;
BSpace--;
BPtr[0] = '/';
BPtr++;
BSpace--;
if (E->Name != NULL)
{
strcpy(BPtr,E->Name);
}
else
{
strcpy(BPtr,"NA");
}
BSpace -= len;
BPtr += len;
BPtr[0] = '>';
BPtr++;
BSpace--;
/* terminate string */
BPtr[0] = '\0';
if (Tail != NULL)
*Tail = BPtr;
if ((NoCompress == FALSE) && (strlen(Buf) > (MMAX_BUFFER >> 1)))
{
if ((E->Name != NULL) && !strcmp(E->Name,"Data"))
{
/* attempt to compress in place */
if (MSecCompress((unsigned char *)Buf,strlen(Buf),NULL,MCONST_CKEY) == FAILURE)
{
return(FAILURE);
}
}
}
return(SUCCESS);
} /* END MXMLToString() */
int MXMLGetAttrF(
mxml_t *E, /* I */
char *AName, /* I/O */
int *ATok, /* I (optional) */
void *AVal, /* O (optional) */
enum MDataFormatEnum DFormat, /* I */
int VSize) /* I */
{
char tmpLine[MMAX_LINE];
int rc;
if (AVal == NULL)
{
return(FAILURE);
}
switch (DFormat)
{
case mdfString:
rc = MXMLGetAttr(
E,
AName,
ATok,
(char *)AVal,
VSize);
return(rc);
/* NOTREACHED*/
break;
case mdfInt:
case mdfLong:
case mdfDouble:
if (MXMLGetAttr(
E,
AName,
ATok,
tmpLine,
sizeof(tmpLine)) == FAILURE)
{
/* clear response */
switch(DFormat)
{
case mdfInt: *(int *)AVal = 0; break;
case mdfLong: *(long *)AVal = 0; break;
case mdfDouble: *(double *)AVal = 0.0; break;
default: break;
} /* END switch(DFormat) */
return(FAILURE);
}
break;
default:
return(FAILURE);
/*NOTREACHED*/
break;
} /* END switch(DFormat) */
switch (DFormat)
{
case mdfInt:
*(int *)AVal = (int)strtol(tmpLine,NULL,10);
break;
case mdfLong:
*(long *)AVal = strtol(tmpLine,NULL,10);
break;
case mdfDouble:
*(double *)AVal = strtod(tmpLine,NULL);
break;
default:
*(char **)AVal = NULL;
return(FAILURE);
/*NOTREACHED*/
break;
} /* END switch (DFormat) */
return(SUCCESS);
} /* END MXMLGetAttrF() */
int MXMLGetAttr(
mxml_t *E, /* I */
char *AName, /* I/O */
int *ATok, /* I (optional) */
char *AVal, /* O (optional) */
int VSize) /* I */
{
/* NOTE: set AName to empty string to get Name */
int aindex;
int astart;
int EVSize;
if (AVal != NULL)
AVal[0] = '\0';
if (E == NULL)
{
return(FAILURE);
}
EVSize = (VSize > 0) ? VSize : MMAX_LINE;
if (ATok != NULL)
astart = *ATok;
else
astart = -1;
for (aindex = astart + 1;aindex < E->ACount;aindex++)
{
if ((AName == NULL) ||
(AName[0] == '\0') ||
!strcmp(AName,E->AName[aindex]))
{
if ((AName != NULL) && (AName[0] == '\0'))
{
strncpy(AName,E->AName[aindex],MMAX_NAME);
AName[MMAX_NAME - 1] = '\0';
}
if (AVal != NULL)
{
strncpy(AVal,E->AVal[aindex],EVSize);
AVal[EVSize - 1] = '\0';
}
if (ATok != NULL)
*ATok = aindex;
return(SUCCESS);
}
} /* END for (aindex) */
return(FAILURE);
} /* END MXMLGetAttr() */
int MXMLGetChild(
mxml_t *E, /* I */
char *CName, /* I (optional) */
int *CTok, /* I (optional) */
mxml_t **C) /* O */
{
int cindex;
int cstart;
if (C != NULL)
*C = NULL;
if ((E == NULL) || (C == NULL))
{
return(FAILURE);
}
if (CTok != NULL)
cstart = *CTok;
else
cstart = -1;
for (cindex = cstart + 1;cindex < E->CCount;cindex++)
{
if (E->C[cindex] == NULL)
continue;
if ((CName == NULL) || !strcmp(CName,E->C[cindex]->Name))
{
*C = E->C[cindex];
if (CTok != NULL)
*CTok = cindex;
return(SUCCESS);
}
} /* END for (cindex) */
return(FAILURE);
} /* END MXMLGetChild() */
int MXMLGetChildCI(
mxml_t *E, /* I */
char *CName, /* I (optional) */
int *CTok, /* I (optional) */
mxml_t **CP) /* O (optional) */
{
int cindex;
int cstart;
int SLen;
if (CP != NULL)
*CP = NULL;
#ifndef __MOPT
if (E == NULL)
{
return(FAILURE);
}
#endif /* __MOPT */
if (CTok != NULL)
cstart = *CTok;
else
cstart = -1;
if (CName != NULL)
SLen = strlen(CName) + 1;
else
SLen = 0;
for (cindex = cstart + 1;cindex < E->CCount;cindex++)
{
if (E->C[cindex] == NULL)
continue;
if ((CName == NULL) || !strncasecmp(CName,E->C[cindex]->Name,SLen))
{
if (CP != NULL)
*CP = E->C[cindex];
if (CTok != NULL)
*CTok = cindex;
return(SUCCESS);
}
} /* END for (cindex) */
return(FAILURE);
} /* END MXMLGetChildCI() */
#define MMAX_XBUFFER 131072
int MXMLFromString(
mxml_t **EP, /* O (populate or create - will be freed on failure) */
char *XMLString, /* I */
char **Tail, /* O (optional) */
char *EMsg) /* O (optional) */
{
mxml_t *E;
char *ptr;
char *tail;
int index;
mbool_t ElementIsClosed = FALSE;
mbool_t DoAppend = FALSE;
char tmpNLine[MMAX_LINE + 1];
char tmpVLine[MMAX_XBUFFER + 1];
if (EP != NULL)
*EP = NULL;
if (EMsg != NULL)
EMsg[0] = '\0';
if ((XMLString == NULL) || (EP == NULL))
{
if (EMsg != NULL)
strcpy(EMsg,"invalid arguments");
return(FAILURE);
}
if ((ptr = strchr(XMLString,'<')) == NULL)
{
if (EMsg != NULL)
strcpy(EMsg,"no XML in string");
return(FAILURE);
}
if (ptr[1] == '/')
{
/* located tail marker */
if (EMsg != NULL)
strcpy(EMsg,"premature termination marker");
return(FAILURE);
}
/* NOTE: should support append/overlay parameter (NYI) */
/* ignore 'meta' elements */
while ((ptr[1] == '?') || (ptr[1] == '!'))
{
ptr++;
/* ignore 'meta' elements */
if (*ptr == '?')
{
ptr++;
if ((ptr = strstr(ptr,"?>")) == NULL)
{
/* cannot locate end of meta element */
return(FAILURE);
}
if ((ptr = strchr(ptr,'<')) == NULL)
{
/* cannot locate next element */
if (EMsg != NULL)
strcpy(EMsg,"cannot locate post-meta XML");
return(FAILURE);
}
} /* END if (*ptr == '?') */
/* ignore 'comment' element */
if (!strncmp(ptr,"!--",3))
{
ptr += 3;
if ((ptr = strstr(ptr,"-->")) == NULL)
{
/* cannot locate end of comment element */
if (EMsg != NULL)
strcpy(EMsg,"cannot locate comment termination marker");
return(FAILURE);
}
if ((ptr = strchr(ptr,'<')) == NULL)
{
/* cannot locate next element */
if (EMsg != NULL)
strcpy(EMsg,"cannot locate post-comment XML");
return(FAILURE);
}
} /* END if (!strncmp(ptr,"!--",3)) */
else if (ptr[1] == '!')
{
char* ptr2;
ptr++;
ptr++;
while (*ptr != '\0')
{
if (strchr("<[>",*ptr) != NULL)
{
break;
}
ptr++;
}
if ((ptr2 = strchr("<[>",*ptr)) == NULL)
{
/* cannot locate end element */
if (EMsg != NULL)
strcpy(EMsg,"cannot locate post-comment XML");
return(FAILURE);
}
switch (*ptr2)
{
case '[':
ptr = strstr(ptr,"]>");
break;
default:
/* NYI */
return(FAILURE);
/* NOTREACHED */
break;
}
if ((ptr = strchr(ptr,'<')) == NULL)
{
/* cannot locate next element */
if (EMsg != NULL)
strcpy(EMsg,"cannot locate post-comment XML");
return(FAILURE);
}
} /* END if (*ptr == '!') */
} /* END while ((ptr[1] == '?') || (ptr[1] == '!')) */
/* remove whitespace */
while (isspace(*ptr))
ptr++;
/* extract root element */
if (*ptr != '<')
{
/* cannot located start of element */
if (EMsg != NULL)
strcpy(EMsg,"cannot locate start of root element");
return(FAILURE);
}
ptr++; /* ignore '<' */
index = 0;
while ((*ptr != ' ') && (*ptr != '>'))
{
if ((ptr[0] == '/') && (ptr[1] == '>'))
{
ElementIsClosed = TRUE;
break;
}
tmpNLine[index++] = *(ptr++);
if ((index >= MMAX_LINE) || (ptr[0] == '\0'))
{
if (EMsg != NULL)
sprintf(EMsg,"element name is too long - %.10s",
tmpNLine);
return(FAILURE);
}
}
tmpNLine[index] = '\0';
if ((*EP == NULL) && (MXMLCreateE(EP,tmpNLine) == FAILURE))
{
if (EMsg != NULL)
sprintf(EMsg,"cannot create XML element '%s'",
tmpNLine);
return(FAILURE);
}
E = *EP;
if ((E->ACount > 0) || (E->CCount > 0))
{
DoAppend = TRUE;
}
if (ElementIsClosed == TRUE)
{
ptr += 2; /* skip '/>' */
if (Tail != NULL)
*Tail = ptr;
return(SUCCESS);
}
while (*ptr == ' ')
ptr++;
while (*ptr != '>')
{
/* extract attributes */
/* FORMAT: <ATTR>="<VAL>" */
index = 0;
while ((*ptr != '=') && (*ptr != '\0'))
{
tmpNLine[index++] = *(ptr++);
if (index >= MMAX_LINE)
break;
}
tmpNLine[index] = '\0';
if (*ptr != '\0')
ptr++; /* skip '=' */
if (*ptr != '\0')
ptr++; /* skip '"' */
if (*ptr == '\0')
{
if (EMsg != NULL)
sprintf(EMsg,"string is corrupt - early termination");
MXMLDestroyE(EP);
return(FAILURE);
}
index = 0;
while ((*ptr != '"') ||
((ptr > XMLString) && (*(ptr - 1) == '\\')))
{
if (((*ptr == '&') && (*(ptr+1) == 'l') && (*(ptr+2) == 't') && (*(ptr+3) == ';')))
{
tmpVLine[index++] = '<';
ptr += 4;
}
else if (((*ptr == '&') && (*(ptr+1) == 'g') && (*(ptr+2) == 't') && (*(ptr+3) == ';')))
{
tmpVLine[index++] = '>';
ptr += 4;
}
else
{
tmpVLine[index++] = *(ptr++);
}
if ((index >= MMAX_XBUFFER) || (*ptr == '\0'))
{
MXMLDestroyE(EP);
/* locate tail */
if (Tail != NULL)
*Tail = ptr + strlen(ptr);
if (EMsg != NULL)
sprintf(EMsg,"attribute name is too long - %.10s",
tmpVLine);
return(FAILURE);
}
}
tmpVLine[index] = '\0';
MXMLSetAttr(E,tmpNLine,(void *)tmpVLine,mdfString);
ptr++; /* ignore '"' */
while (*ptr == ' ')
ptr++;
if ((ptr[0] == '/') && (ptr[1] == '>'))
{
/* element terminator reached */
ptr += 2; /* skip '/>' */
if (Tail != NULL)
*Tail = ptr;
return(SUCCESS);
}
} /* END while (*ptr != '>') */
ptr++; /* ignore '>' */
/* skip whitespace */
while (isspace(*ptr))
ptr++;
/* NOTE: value can occur before, after, or spread amongst children */
/* extract value */
if (*ptr != '<')
{
char *ptr2;
index = 0;
if (!strncmp(ptr,CRYPTHEAD,strlen(CRYPTHEAD)))
{
char *tail;
int len;
mxml_t *C;
char *tmpBuf;
/* compressed data detected, '<' symbol guaranteed to not be part of string */
tail = strchr(ptr,'<');
/* determine size of value */
len = tail - ptr;
/* uncompress data */
tmpBuf = NULL;
/* NOTE: CRYPTHEAD header indicates encryption/compression */
MSecDecompress((unsigned char *)ptr,(unsigned int)len,NULL,(unsigned int)0,(unsigned char **)&tmpBuf,NULL);
/* process expanded buffer (guaranteed to be a single element */
if ((MXMLFromString(&C,tmpBuf,NULL,EMsg) == FAILURE) ||
(MXMLAddE(E,C) == FAILURE))
{
MXMLDestroyE(EP);
if ((EMsg != NULL) &&
(EMsg[0] == '\0'))
{
strcpy(EMsg,"cannot add child element");
}
return(FAILURE);
}
tmpBuf = NULL;
/* move pointer to end of compressed data */
ptr = tail;
} /* END if (!strncmp(ptr,CRYPTHEAD,strlen(CRYPTHEAD))) */
while (*ptr != '<')
{
tmpVLine[index++] = *(ptr++);
if (index >= MMAX_XBUFFER)
break;
}
tmpVLine[index] = '\0';
E->Val = strdup(tmpVLine);
/* restore '<' symbols */
for (ptr2 = strchr(E->Val,(char)14);ptr2 != NULL;ptr2 = strchr(ptr2,(char)14))
*ptr2 = '<';
} /* END if (*ptr != '<') */
/* extract children */
while (ptr[1] != '/')
{
mxml_t *C;
C = NULL;
if (DoAppend == TRUE)
{
char *ptr2;
char tmpCName[MMAX_NAME];
int index;
/* FORMAT: <NAME>... */
/* locate name */
ptr2 = ptr + 1; /* ignore '<' */
index = 0;
while ((*ptr2 != ' ') && (*ptr2 != '>'))
{
if ((ptr2[0] == '/') && (ptr2[1] == '>'))
{
break;
}
tmpCName[index++] = *(ptr2++);
if ((index >= MMAX_LINE) || (ptr2[0] == '\0'))
{
if (EMsg != NULL)
sprintf(EMsg,"element name is too long - %.10s",
tmpCName);
MXMLDestroyE(EP);
return(FAILURE);
}
}
tmpCName[index] = '\0';
MXMLGetChild(E,tmpCName,NULL,&C);
}
if ((MXMLFromString(&C,ptr,&tail,EMsg) == FAILURE) ||
(MXMLAddE(E,C) == FAILURE))
{
break;
}
ptr = tail;
if ((ptr == NULL) || (ptr[0] == '\0'))
{
/* XML is corrupt */
if (Tail != NULL)
*Tail = ptr;
if ((EMsg != NULL) && (EMsg[0] == '\0'))
strcpy(EMsg,"cannot extract child");
MXMLDestroyE(EP);
return(FAILURE);
}
} /* END while (ptr[1] != '/') */
/* ignore whitespace */
while (isspace(*ptr))
ptr++;
/* value may follow children */
if (E->Val == NULL)
{
if (!strncmp(ptr,CRYPTHEAD,strlen(CRYPTHEAD)))
{
char *tail;
int len;
mxml_t *C;
char *tmpBuf;
/* compressed data detected, '<' symbol guaranteed to not be part of string */
tail = strchr(ptr,'<');
/* determine size of value */
len = tail - ptr;
/* uncompress data */
tmpBuf = NULL;
/* NOTE: CRYPTHEAD header indicates encryption/compression */
MSecDecompress((unsigned char *)ptr,(unsigned int)len,NULL,(unsigned int)0,(unsigned char **)&tmpBuf,NULL);
/* process expanded buffer (guaranteed to be a single element */
if ((MXMLFromString(&C,tmpBuf,NULL,EMsg) == FAILURE) ||
(MXMLAddE(E,C) == FAILURE))
{
MXMLDestroyE(EP);
if ((EMsg != NULL) &&
(EMsg[0] == '\0'))
{
strcpy(EMsg,"cannot add child element");
}
return(FAILURE);
}
tmpBuf = NULL;
/* move pointer to end of compressed data */
ptr = tail;
} /* END if (!strncmp(ptr,CRYPTHEAD,strlen(CRYPTHEAD))) */
index = 0;
while (*ptr != '<')
{
tmpVLine[index++] = *(ptr++);
if ((index >= MMAX_XBUFFER) || (*ptr == '\0'))
{
if (EMsg != NULL)
sprintf(EMsg,"cannot load value line - %.10s (%s)",
tmpVLine,
(index >= MMAX_XBUFFER) ? "too long" : "corrupt");
MXMLDestroyE(EP);
return(FAILURE);
}
if ((*ptr == '/') && (ptr[1] == '>'))
break;
}
tmpVLine[index] = '\0';
if (index > 0)
E->Val = strdup(tmpVLine);
} /* END if (tmpVLine[0] == '\0') */
/* process tail */
if (*ptr == '/')
{
/* process '/>' */
ptr++; /* ignore '/' */
}
else if (*ptr != '\0')
{
/* NOTE: corrupt XML string may move ptr beyond string terminator */
ptr++; /* ignore '<' */
ptr++; /* ignore '/' */
ptr += strlen(E->Name);
}
if (*ptr == '\0')
{
if (EMsg != NULL)
sprintf(EMsg,"xml tail is corrupt");
MXMLDestroyE(EP);
return(FAILURE);
}
ptr++; /* ignore '>' */
if (Tail != NULL)
*Tail = ptr;
return(SUCCESS);
} /* END MXMLFromString() */
mbool_t MXMLStringIsValid(
char *Buf) /* I */
{
char *ptr;
/* NOTE: only limited checks performed */
/* check if line starts with '<' */
if ((Buf == NULL) || (Buf[0] == '\0'))
{
return(FALSE);
}
ptr = strchr(Buf,'<');
if (ptr == NULL)
{
return(FALSE);
}
ptr--;
while (ptr > Buf)
{
if (!isspace(*ptr))
{
return(FALSE);
}
ptr--;
} /* END while (ptr > Buf) */
/* check if line contains '<' */
ptr = strchr(Buf,'>');
if (ptr == NULL)
{
return(FALSE);
}
return(TRUE);
} /* END MXMLStringIsValid() */
int MXMLDupE(
mxml_t *SrcE, /* I */
mxml_t **DstEP) /* O */
{
char Buffer[MMAX_BUFFER];
if (DstEP == NULL)
{
return(FAILURE);
}
*DstEP = NULL;
if (SrcE == NULL)
{
return(FAILURE);
}
if (MXMLToString(SrcE,Buffer,sizeof(Buffer),NULL,TRUE) == FAILURE)
{
return(FAILURE);
}
if (MXMLFromString(DstEP,Buffer,NULL,NULL) == FAILURE)
{
return(FAILURE);
}
return(SUCCESS);
} /* END MXMLDupE() */
/* END MXML.c */