PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/ATF2/control-software/epics-3.14.8/extensions/src/ChannelArchiver/ThirdParty/xerces-c-src2_4_0/src/xercesc/validators/DTD/DTDValidator.cpp

http://atf2flightsim.googlecode.com/
C++ | 647 lines | 357 code | 67 blank | 223 comment | 123 complexity | feadef6f1c3cd7f5d3e473bfdadfe346 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution,
  20. * if any, must include the following acknowledgment:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgment may appear in the software itself,
  24. * if and wherever such third-party acknowledgments normally appear.
  25. *
  26. * 4. The names "Xerces" and "Apache Software Foundation" must
  27. * not be used to endorse or promote products derived from this
  28. * software without prior written permission. For written
  29. * permission, please contact apache\@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache",
  32. * nor may "Apache" appear in their name, without prior written
  33. * permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation, and was
  51. * originally based on software copyright (c) 1999, International
  52. * Business Machines, Inc., http://www.ibm.com . For more information
  53. * on the Apache Software Foundation, please see
  54. * <http://www.apache.org/>.
  55. */
  56. /*
  57. * $Id: DTDValidator.cpp,v 1.1.1.1 2009/03/14 06:43:04 whitegr Exp $
  58. */
  59. // ---------------------------------------------------------------------------
  60. // Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/Janitor.hpp>
  63. #include <xercesc/util/XMLUniDefs.hpp>
  64. #include <xercesc/util/XMLUni.hpp>
  65. #include <xercesc/internal/ReaderMgr.hpp>
  66. #include <xercesc/internal/XMLScanner.hpp>
  67. #include <xercesc/validators/DTD/DTDValidator.hpp>
  68. XERCES_CPP_NAMESPACE_BEGIN
  69. // ---------------------------------------------------------------------------
  70. // DTDValidator: Constructors and Destructor
  71. // ---------------------------------------------------------------------------
  72. DTDValidator::DTDValidator(XMLErrorReporter* const errReporter) :
  73. XMLValidator(errReporter)
  74. , fDTDGrammar(0)
  75. {
  76. reset();
  77. }
  78. DTDValidator::~DTDValidator()
  79. {
  80. }
  81. // ---------------------------------------------------------------------------
  82. // DTDValidator: Implementation of the XMLValidator interface
  83. // ---------------------------------------------------------------------------
  84. int DTDValidator::checkContent(XMLElementDecl* const elemDecl
  85. , QName** const children
  86. , const unsigned int childCount)
  87. {
  88. //
  89. // Look up the element id in our element decl pool. This will get us
  90. // the element decl in our own way of looking at them.
  91. //
  92. if (!elemDecl)
  93. ThrowXML(RuntimeException, XMLExcepts::Val_InvalidElemId);
  94. //
  95. // Get the content spec type of this element. This will tell us what
  96. // to do to validate it.
  97. //
  98. const DTDElementDecl::ModelTypes modelType = ((DTDElementDecl*) elemDecl)->getModelType();
  99. if (modelType == DTDElementDecl::Empty)
  100. {
  101. //
  102. // We can do this one here. It cannot have any children. If it does
  103. // we return 0 as the index of the first bad child.
  104. //
  105. if (childCount)
  106. return 0;
  107. }
  108. else if (modelType == DTDElementDecl::Any)
  109. {
  110. // We pass no judgement on this one, anything goes
  111. }
  112. else if ((modelType == DTDElementDecl::Mixed_Simple)
  113. || (modelType == DTDElementDecl::Children))
  114. {
  115. // Get the element's content model or fault it in
  116. const XMLContentModel* elemCM = elemDecl->getContentModel();
  117. // Ask it to validate and return its return
  118. return elemCM->validateContent(children, childCount, getScanner()->getEmptyNamespaceId());
  119. }
  120. else
  121. {
  122. ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMType);
  123. }
  124. // Went ok, so return success
  125. return -1;
  126. }
  127. void DTDValidator::faultInAttr(XMLAttr& toFill, const XMLAttDef& attDef) const
  128. {
  129. //
  130. // At this level, we cannot set the URI id. So we just set it to zero
  131. // and leave it at that. The scanner, who called us, will look at the
  132. // prefix we stored (if any), resolve it, and store the URL id if any.
  133. //
  134. const XMLCh* fullName = attDef.getFullName();
  135. const int colonInd = XMLString::indexOf(fullName, chColon);
  136. if (colonInd == -1)
  137. {
  138. // There is no prefix, so we just do a simple and quick setting
  139. toFill.set
  140. (
  141. 0
  142. , fullName
  143. , XMLUni::fgZeroLenString
  144. , attDef.getValue()
  145. , attDef.getType()
  146. );
  147. }
  148. else
  149. {
  150. //
  151. // There is a colon, so we have to split apart the name and prefix
  152. // part.
  153. //
  154. XMLCh* tmpNameBuf = XMLString::replicate(fullName);
  155. ArrayJanitor<XMLCh> janNameBuf(tmpNameBuf);
  156. // Put a null where the colon is, to split it into two strings
  157. tmpNameBuf[colonInd] = chNull;
  158. //
  159. // And now we can set the attribute object with the prefix and name
  160. // parts.
  161. //
  162. toFill.set
  163. (
  164. 0
  165. , &tmpNameBuf[colonInd+1]
  166. , tmpNameBuf
  167. , attDef.getValue()
  168. , attDef.getType()
  169. );
  170. }
  171. }
  172. void DTDValidator::reset()
  173. {
  174. }
  175. bool DTDValidator::requiresNamespaces() const
  176. {
  177. // Namespaces are not supported for DTDs
  178. return false;
  179. }
  180. void
  181. DTDValidator::validateAttrValue(const XMLAttDef* attDef
  182. , const XMLCh* const attrValue
  183. , bool preValidation
  184. , const XMLElementDecl* elemDecl)
  185. {
  186. //
  187. // Get quick refs to lost of of the stuff in the passed objects in
  188. // order to simplify the code below, which will reference them very
  189. // often.
  190. //
  191. const XMLAttDef::AttTypes type = attDef->getType();
  192. const XMLAttDef::DefAttTypes defType = attDef->getDefaultType();
  193. const XMLCh* const valueText = attDef->getValue();
  194. const XMLCh* const fullName = attDef->getFullName();
  195. const XMLCh* const enumList = attDef->getEnumeration();
  196. //
  197. // If the default type is fixed, then make sure the passed value maps
  198. // to the fixed value.
  199. // If during preContentValidation, the value we are validating is the fixed value itself
  200. // so no need to compare.
  201. // Only need to do this for regular attribute value validation
  202. //
  203. if (defType == XMLAttDef::Fixed && !preValidation)
  204. {
  205. if (!XMLString::equals(attrValue, valueText))
  206. emitError(XMLValid::NotSameAsFixedValue, fullName, attrValue, valueText);
  207. }
  208. //
  209. // If its a CDATA attribute, then we are done with any DTD level
  210. // validation else do the rest.
  211. //
  212. if (type == XMLAttDef::CData)
  213. return;
  214. // An empty string cannot be valid for any of the other types
  215. if (!attrValue[0])
  216. {
  217. emitError(XMLValid::InvalidEmptyAttValue, fullName);
  218. return;
  219. }
  220. // See whether we are doing multiple values or not
  221. const bool multipleValues =
  222. (
  223. (type == XMLAttDef::IDRefs)
  224. || (type == XMLAttDef::Entities)
  225. || (type == XMLAttDef::NmTokens)
  226. || (type == XMLAttDef::Notation)
  227. || (type == XMLAttDef::Enumeration)
  228. );
  229. // And whether we must check for a first name char
  230. const bool firstNameChar =
  231. (
  232. (type == XMLAttDef::ID)
  233. || (type == XMLAttDef::IDRef)
  234. || (type == XMLAttDef::IDRefs)
  235. || (type == XMLAttDef::Entity)
  236. || (type == XMLAttDef::Entities)
  237. || (type == XMLAttDef::Notation)
  238. );
  239. // Whether it requires ref checking stuff
  240. const bool isARefType
  241. (
  242. (type == XMLAttDef::ID)
  243. || (type == XMLAttDef::IDRef)
  244. || (type == XMLAttDef::IDRefs)
  245. );
  246. // Some trigger flags to avoid issuing redundant errors and whatnot
  247. bool sawOneValue;
  248. bool alreadyCapped = false;
  249. //
  250. // Make a copy of the text that we can mangle and get a pointer we can
  251. // move through the value
  252. //
  253. // Use a stack-based buffer, when possible...
  254. XMLCh tempBuffer[100];
  255. XMLCh* pszTmpVal = 0;
  256. ArrayJanitor<XMLCh> janTmpVal(0);
  257. if (XMLString::stringLen(attrValue) < sizeof(tempBuffer) / sizeof(tempBuffer[0]))
  258. {
  259. XMLString::copyString(tempBuffer, attrValue);
  260. pszTmpVal = tempBuffer;
  261. }
  262. else
  263. {
  264. janTmpVal.reset(XMLString::replicate(attrValue));
  265. pszTmpVal = janTmpVal.get();
  266. }
  267. XMLCh* valPtr = pszTmpVal;
  268. bool doNamespace = getScanner()->getDoNamespaces();
  269. while (true)
  270. {
  271. // Reset the trigger flags
  272. sawOneValue = false;
  273. //
  274. // Make sure the first character is a valid first name char, i.e.
  275. // if its a Name value. For NmToken values we don't treat the first
  276. // char any differently.
  277. //
  278. if (firstNameChar)
  279. {
  280. // If its not, emit and error but try to keep going
  281. if (!getReaderMgr()->getCurrentReader()->isFirstNameChar(*valPtr))
  282. emitError(XMLValid::AttrValNotName, fullName);
  283. valPtr++;
  284. }
  285. // Make sure all the remaining chars are valid name chars
  286. while (*valPtr)
  287. {
  288. //
  289. // If we hit a whitespace, its either a break between two
  290. // or more values, or an error if we have a single value.
  291. //
  292. if (getReaderMgr()->getCurrentReader()->isWhitespace(*valPtr))
  293. {
  294. if (!multipleValues)
  295. {
  296. emitError(XMLValid::NoMultipleValues, fullName);
  297. return;
  298. }
  299. break;
  300. }
  301. // Now this attribute can be of type
  302. // ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENS, ENUMERATION
  303. // All these must be valid XMLName
  304. // If namespace is enabled, colon is not allowed in the first 6
  305. if (doNamespace && *valPtr == chColon && firstNameChar)
  306. emitError(XMLValid::ColonNotValidWithNS);
  307. if (!getReaderMgr()->getCurrentReader()->isNameChar(*valPtr))
  308. {
  309. emitError(XMLValid::AttrValNotName, fullName);
  310. return;
  311. }
  312. valPtr++;
  313. }
  314. //
  315. // Cap it off at the current non-name char. If already capped,
  316. // then remember this.
  317. //
  318. if (!(*valPtr))
  319. alreadyCapped = true;
  320. *valPtr = 0;
  321. //
  322. // If this type of attribute requires that we track reference
  323. // stuff, then handle that.
  324. //
  325. if (isARefType)
  326. {
  327. if ((type == XMLAttDef::ID)
  328. || (type == XMLAttDef::IDRef)
  329. || (type == XMLAttDef::IDRefs))
  330. {
  331. XMLRefInfo* find = getScanner()->getIDRefList()->get(pszTmpVal);
  332. if (find)
  333. {
  334. if (find->getDeclared() && (type == XMLAttDef::ID))
  335. emitError(XMLValid::ReusedIDValue, pszTmpVal);
  336. }
  337. else
  338. {
  339. find = new (getScanner()->getMemoryManager()) XMLRefInfo
  340. (
  341. pszTmpVal
  342. , false
  343. , false
  344. , getScanner()->getMemoryManager()
  345. );
  346. getScanner()->getIDRefList()->put((void*)find->getRefName(), find);
  347. }
  348. //
  349. // Mark it declared or used, which might be redundant in some cases
  350. // but not worth checking
  351. //
  352. if (type == XMLAttDef::ID)
  353. find->setDeclared(true);
  354. else {
  355. if (!preValidation) {
  356. find->setUsed(true);
  357. }
  358. }
  359. }
  360. }
  361. else if ((type == XMLAttDef::Entity) || (type == XMLAttDef::Entities))
  362. {
  363. //
  364. // If its refering to a entity, then look up the name in the
  365. // general entity pool. If not there, then its an error. If its
  366. // not an external unparsed entity, then its an error.
  367. //
  368. const XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(pszTmpVal);
  369. if (decl)
  370. {
  371. if (!decl->isUnparsed())
  372. emitError(XMLValid::BadEntityRefAttr, fullName);
  373. }
  374. else
  375. {
  376. emitError
  377. (
  378. XMLValid::UnknownEntityRefAttr
  379. , fullName
  380. , pszTmpVal
  381. );
  382. }
  383. }
  384. else if ((type == XMLAttDef::Notation) || (type == XMLAttDef::Enumeration))
  385. {
  386. //
  387. // Make sure that this value maps to one of the enumeration or
  388. // notation values in the enumList parameter. We don't have to
  389. // look it up in the notation pool (if a notation) because we
  390. // will look up the enumerated values themselves. If they are in
  391. // the notation pool (after the DTD is parsed), then obviously
  392. // this value will be legal since it matches one of them.
  393. //
  394. if (!XMLString::isInList(pszTmpVal, enumList))
  395. emitError(XMLValid::DoesNotMatchEnumList, fullName);
  396. }
  397. // If not doing multiple values, then we are done
  398. if (!multipleValues)
  399. break;
  400. //
  401. // If we are at the end, then break out now, else move up to the
  402. // next char and update the base pointer.
  403. //
  404. if (alreadyCapped)
  405. break;
  406. valPtr++;
  407. pszTmpVal = valPtr;
  408. }
  409. }
  410. void DTDValidator::preContentValidation(bool reuseGrammar,
  411. bool validateDefAttr)
  412. {
  413. //
  414. // Lets enumerate all of the elements in the element decl pool
  415. // and put out an error for any that did not get declared.
  416. // We also check all of the attributes as well.
  417. //
  418. NameIdPoolEnumerator<DTDElementDecl> elemEnum = fDTDGrammar->getElemEnumerator();
  419. while (elemEnum.hasMoreElements())
  420. {
  421. const DTDElementDecl& curElem = elemEnum.nextElement();
  422. const DTDElementDecl::CreateReasons reason = curElem.getCreateReason();
  423. //
  424. // See if this element decl was ever marked as declared. If
  425. // not, then put out an error. In some cases its just
  426. // a warning, such as being referenced in a content model.
  427. //
  428. if (reason != XMLElementDecl::Declared)
  429. {
  430. if (reason == XMLElementDecl::AttList)
  431. {
  432. getScanner()->emitError
  433. (
  434. XMLErrs::UndeclaredElemInAttList
  435. , curElem.getFullName()
  436. );
  437. }
  438. else if (reason == XMLElementDecl::AsRootElem)
  439. {
  440. // It's ok that the root element is not declared in the DTD
  441. /*
  442. emitError
  443. (
  444. XMLValid::UndeclaredElemInDocType
  445. , curElem.getFullName()
  446. );*/
  447. }
  448. else if (reason == XMLElementDecl::InContentModel)
  449. {
  450. getScanner()->emitError
  451. (
  452. XMLErrs::UndeclaredElemInCM
  453. , curElem.getFullName()
  454. );
  455. }
  456. else
  457. {
  458. #if defined(XERCES_DEBUG)
  459. if(reuseGrammar && reason == XMLElementDecl::JustFaultIn){
  460. }
  461. else
  462. ThrowXML(RuntimeException, XMLExcepts::DTD_UnknownCreateReason);
  463. #endif
  464. }
  465. }
  466. //
  467. // Check all of the attributes of the current element.
  468. // We check for:
  469. //
  470. // 1) Multiple ID attributes
  471. // 2) That all of the default values of attributes are
  472. // valid for their type.
  473. // 3) That for any notation types, that their lists
  474. // of possible values refer to declared notations.
  475. //
  476. XMLAttDefList& attDefList = curElem.getAttDefList();
  477. bool seenId = false;
  478. for(unsigned int i=0; i<attDefList.getAttDefCount(); i++)
  479. {
  480. const XMLAttDef& curAttDef = attDefList.getAttDef(i);
  481. if (curAttDef.getType() == XMLAttDef::ID)
  482. {
  483. if (seenId)
  484. {
  485. emitError
  486. (
  487. XMLValid::MultipleIdAttrs
  488. , curElem.getFullName()
  489. );
  490. break;
  491. }
  492. seenId = true;
  493. }
  494. else if (curAttDef.getType() == XMLAttDef::Notation && curAttDef.getEnumeration())
  495. {
  496. //
  497. // We need to verify that all of its possible values
  498. // (in the enum list) refer to valid notations.
  499. //
  500. XMLCh* list = XMLString::replicate(curAttDef.getEnumeration());
  501. ArrayJanitor<XMLCh> janList(list);
  502. //
  503. // Search forward for a space or a null. If a null,
  504. // we are done. If a space, cap it and look it up.
  505. //
  506. bool breakFlag = false;
  507. XMLCh* listPtr = list;
  508. XMLCh* lastPtr = listPtr;
  509. while (true)
  510. {
  511. while (*listPtr && (*listPtr != chSpace))
  512. listPtr++;
  513. //
  514. // If at the end, indicate we need to break after
  515. // this one. Else, cap it off here.
  516. //
  517. if (!*listPtr)
  518. breakFlag = true;
  519. else
  520. *listPtr = chNull;
  521. if (!fDTDGrammar->getNotationDecl(lastPtr))
  522. {
  523. emitError
  524. (
  525. XMLValid::UnknownNotRefAttr
  526. , curAttDef.getFullName()
  527. , lastPtr
  528. );
  529. }
  530. // Break out if we hit the end last time
  531. if (breakFlag)
  532. break;
  533. // Else move upwards and try again
  534. listPtr++;
  535. lastPtr = listPtr;
  536. }
  537. }
  538. // If it has a default/fixed value, then validate it
  539. if (validateDefAttr && curAttDef.getValue())
  540. {
  541. validateAttrValue
  542. (
  543. &curAttDef
  544. , curAttDef.getValue()
  545. , true
  546. , &curElem
  547. );
  548. }
  549. }
  550. }
  551. //
  552. // And enumerate all of the general entities. If any of them
  553. // reference a notation, then make sure the notation exists.
  554. //
  555. NameIdPoolEnumerator<DTDEntityDecl> entEnum = fDTDGrammar->getEntityEnumerator();
  556. while (entEnum.hasMoreElements())
  557. {
  558. const DTDEntityDecl& curEntity = entEnum.nextElement();
  559. if (!curEntity.getNotationName())
  560. continue;
  561. // It has a notation name, so look it up
  562. if (!fDTDGrammar->getNotationDecl(curEntity.getNotationName()))
  563. {
  564. emitError
  565. (
  566. XMLValid::NotationNotDeclared
  567. , curEntity.getNotationName()
  568. );
  569. }
  570. }
  571. }
  572. void DTDValidator::postParseValidation()
  573. {
  574. //
  575. // At this time, there is nothing to do here. The scanner itself handles
  576. // ID/IDREF validation, since that is the same no matter what kind of
  577. // validator.
  578. //
  579. }
  580. XERCES_CPP_NAMESPACE_END