📄 cpl_minixml.cpp
字号:
/********************************************************************** * $Id: cpl_minixml.cpp,v 1.23 2003/05/21 03:32:43 warmerda Exp $ * * Project: CPL - Common Portability Library * Purpose: Implementation of MiniXML Parser and handling. * Author: Frank Warmerdam, warmerdam@pobox.com * ********************************************************************** * Copyright (c) 2001, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ********************************************************************** * * Independent Security Audit 2003/04/05 Andrey Kiselev: * Completed audit of this module. Any documents may be parsed without * buffer overflows and stack corruptions. * * Security Audit 2003/03/28 warmerda: * Completed security audit. I believe that this module may be safely used * to parse, and serialize arbitrary documents provided by a potentially * hostile source. * * $Log: cpl_minixml.cpp,v $ * Revision 1.23 2003/05/21 03:32:43 warmerda * expand tabs * * Revision 1.22 2003/04/05 07:12:25 dron * Completed security audit. * * Revision 1.21 2003/03/28 17:38:39 warmerda * Added NULL check in CPLParseXMLString(). * * Revision 1.20 2003/03/28 05:05:18 warmerda * Completed security audit. Several bugs related to possible buffer * overruns correct, notably with regard to CPLError() calls. * * Revision 1.19 2003/03/27 18:12:41 warmerda * Added NULL pszNameSpace support in namespace stripper (all namespaces). * Added XML file read/write functions. * * Revision 1.18 2003/03/24 16:47:30 warmerda * Added CPLStripXMLNamespace(). * CPLAddXMLChild() will now ensure that attributes are inserted before * non-attributes nodes. * * Revision 1.17 2003/02/14 18:44:29 warmerda * proper tokens may include a dash * * Revision 1.16 2002/11/16 20:42:40 warmerda * improved inline comments * * Revision 1.15 2002/11/16 20:38:34 warmerda * added support for literals like DOCTYPE * * Revision 1.14 2002/07/16 15:06:26 warmerda * ensure that attributes are serialized properly regardless of their order * * Revision 1.13 2002/07/09 20:25:25 warmerda * expand tabs * * Revision 1.12 2002/05/28 18:54:05 warmerda * added escaping/unescaping support * * Revision 1.11 2002/05/24 04:09:10 warmerda * added clone and SetXMLValue functions * * Revision 1.10 2002/04/01 16:08:21 warmerda * allow periods in tokens * * Revision 1.9 2002/03/07 22:19:20 warmerda * don't do operations within CPLAssert(), in UnreadChar() * * Revision 1.8 2002/03/05 14:26:57 warmerda * expanded tabs * * Revision 1.7 2002/01/23 20:45:05 warmerda * handle <?...?> and comment elements * * Revision 1.6 2002/01/22 18:54:48 warmerda * ensure text is property initialized when serializing * * Revision 1.5 2002/01/16 03:58:51 warmerda * support single quotes as well as double quotes * * Revision 1.4 2001/12/06 18:13:49 warmerda * added CPLAddXMLChild and CPLCreateElmentAndValue * * Revision 1.3 2001/11/16 21:20:16 warmerda * fixed typo * * Revision 1.2 2001/11/16 20:29:58 warmerda * fixed lost char in normal CString tokens * * Revision 1.1 2001/11/16 15:39:48 warmerda * New */#include <ctype.h>#include "cpl_minixml.h"#include "cpl_error.h"#include "cpl_conv.h"#include "cpl_string.h"CPL_CVSID("$Id: cpl_minixml.cpp,v 1.23 2003/05/21 03:32:43 warmerda Exp $");typedef enum { TNone, TString, TOpen, TClose, TEqual, TToken, TSlashClose, TQuestionClose, TComment, TLiteral} TokenType;typedef struct { const char *pszInput; int nInputOffset; int nInputLine; int bInElement; TokenType eTokenType; char *pszToken; int nTokenMaxSize; int nTokenSize; int nStackMaxSize; int nStackSize; CPLXMLNode **papsStack; CPLXMLNode *psFirstNode;} ParseContext;/************************************************************************//* ReadChar() *//************************************************************************/static char ReadChar( ParseContext *psContext ){ char chReturn; chReturn = psContext->pszInput[psContext->nInputOffset++]; if( chReturn == '\0' ) psContext->nInputOffset--; else if( chReturn == 10 ) psContext->nInputLine++; return chReturn;}/************************************************************************//* UnreadChar() *//************************************************************************/static void UnreadChar( ParseContext *psContext, char chToUnread ){ if( chToUnread == '\0' ) { /* do nothing */ } else { CPLAssert( chToUnread == psContext->pszInput[psContext->nInputOffset-1] ); psContext->nInputOffset--; if( chToUnread == 10 ) psContext->nInputLine--; }}/************************************************************************//* AddToToken() *//************************************************************************/static void AddToToken( ParseContext *psContext, char chNewChar ){ if( psContext->pszToken == NULL ) { psContext->nTokenMaxSize = 10; psContext->pszToken = (char *) CPLMalloc(psContext->nTokenMaxSize); } else if( psContext->nTokenSize >= psContext->nTokenMaxSize - 2 ) { psContext->nTokenMaxSize *= 2; psContext->pszToken = (char *) CPLRealloc(psContext->pszToken,psContext->nTokenMaxSize); } psContext->pszToken[psContext->nTokenSize++] = chNewChar; psContext->pszToken[psContext->nTokenSize] = '\0';}/************************************************************************//* ReadToken() *//************************************************************************/static TokenType ReadToken( ParseContext *psContext ){ char chNext; psContext->nTokenSize = 0; psContext->pszToken[0] = '\0'; chNext = ReadChar( psContext ); while( isspace(chNext) ) chNext = ReadChar( psContext );/* -------------------------------------------------------------------- *//* Handle comments. *//* -------------------------------------------------------------------- */ if( chNext == '<' && EQUALN(psContext->pszInput+psContext->nInputOffset,"!--",3) ) { psContext->eTokenType = TComment; // Skip "!--" characters ReadChar(psContext); ReadChar(psContext); ReadChar(psContext); while( !EQUALN(psContext->pszInput+psContext->nInputOffset,"-->",3) && (chNext = ReadChar(psContext)) != '\0' ) AddToToken( psContext, chNext ); // Skip "-->" characters ReadChar(psContext); ReadChar(psContext); ReadChar(psContext); }/* -------------------------------------------------------------------- *//* Handle DOCTYPE or other literals. *//* -------------------------------------------------------------------- */ else if( chNext == '<' && EQUALN(psContext->pszInput+psContext->nInputOffset,"!DOCTYPE",8) ) { int bInQuotes = FALSE; psContext->eTokenType = TLiteral; AddToToken( psContext, '<' ); do { chNext = ReadChar(psContext); if( chNext == '\0' ) { CPLError( CE_Failure, CPLE_AppDefined, "Parse error in DOCTYPE on or before line %d, " "reached end of file without '>'.", psContext->nInputLine ); break; } if( chNext == '\"' ) bInQuotes = !bInQuotes; if( chNext == '>' && !bInQuotes ) { AddToToken( psContext, '>' ); break; } AddToToken( psContext, chNext ); } while( TRUE ); }/* -------------------------------------------------------------------- *//* Simple single tokens of interest. *//* -------------------------------------------------------------------- */ else if( chNext == '<' && !psContext->bInElement ) { psContext->eTokenType = TOpen; psContext->bInElement = TRUE; } else if( chNext == '>' && psContext->bInElement ) { psContext->eTokenType = TClose; psContext->bInElement = FALSE; } else if( chNext == '=' && psContext->bInElement ) { psContext->eTokenType = TEqual; } else if( chNext == '\0' ) { psContext->eTokenType = TNone; }/* -------------------------------------------------------------------- *//* Handle the /> token terminator. *//* -------------------------------------------------------------------- */ else if( chNext == '/' && psContext->bInElement && psContext->pszInput[psContext->nInputOffset] == '>' ) { chNext = ReadChar( psContext ); CPLAssert( chNext == '>' ); psContext->eTokenType = TSlashClose; psContext->bInElement = FALSE; }/* -------------------------------------------------------------------- *//* Handle the ?> token terminator. *//* -------------------------------------------------------------------- */ else if( chNext == '?' && psContext->bInElement && psContext->pszInput[psContext->nInputOffset] == '>' ) { chNext = ReadChar( psContext ); CPLAssert( chNext == '>' ); psContext->eTokenType = TQuestionClose; psContext->bInElement = FALSE; }/* -------------------------------------------------------------------- *//* Collect a quoted string. *//* -------------------------------------------------------------------- */ else if( psContext->bInElement && chNext == '"' ) { psContext->eTokenType = TString; while( (chNext = ReadChar(psContext)) != '"' && chNext != '\0' ) AddToToken( psContext, chNext ); if( chNext != '"' ) { psContext->eTokenType = TNone; CPLError( CE_Failure, CPLE_AppDefined, "Parse error on line %d, reached EOF before closing quote.",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -