Ticket #245: xml_validation_r16600.patch
File xml_validation_r16600.patch, 33.2 KB (added by , 9 years ago) |
---|
-
source/graphics/MapReader.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 358 358 VfsPath filename_xml = pathname.ChangeExtension(L".xml"); 359 359 360 360 CXeromyces xmb_file; 361 if (xmb_file.Load(g_VFS, filename_xml ) != PSRETURN_OK)361 if (xmb_file.Load(g_VFS, filename_xml, "scenario") != PSRETURN_OK) 362 362 return PSRETURN_File_ReadFailed; 363 363 364 364 // Define all the relevant elements used in the XML file … … 468 468 // must only assign once, so do it here 469 469 node_idx = entity_idx = 0; 470 470 471 if (xmb_file.Load(g_VFS, xml_filename ) != PSRETURN_OK)471 if (xmb_file.Load(g_VFS, xml_filename, "scenario") != PSRETURN_OK) 472 472 throw PSERROR_File_ReadFailed(); 473 473 474 474 // define the elements and attributes that are frequently used in the XML file, -
source/graphics/MaterialManager.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 22 22 #include "lib/ogl.h" 23 23 #include "maths/MathUtil.h" 24 24 #include "maths/Vector4D.h" 25 #include "ps/CLogger.h" 25 26 #include "ps/ConfigDB.h" 26 27 #include "ps/Filesystem.h" 27 28 #include "ps/PreprocessorWrapper.h" … … 35 36 qualityLevel = 5.0; 36 37 CFG_GET_VAL("materialmgr.quality", qualityLevel); 37 38 qualityLevel = clamp(qualityLevel, 0.0f, 10.0f); 39 40 if (!CXeromyces::AddValidator(g_VFS, "material", "art/materials/material.rng")) 41 LOGERROR("CMaterialManager: failed to load grammar file 'art/materials/material.rng'"); 38 42 } 39 43 40 44 CMaterial CMaterialManager::LoadMaterial(const VfsPath& pathname) … … 47 51 return iter->second; 48 52 49 53 CXeromyces xeroFile; 50 if (xeroFile.Load(g_VFS, pathname ) != PSRETURN_OK)54 if (xeroFile.Load(g_VFS, pathname, "material") != PSRETURN_OK) 51 55 return CMaterial(); 52 56 53 57 #define EL(x) int el_##x = xeroFile.GetElementID(#x) -
source/graphics/ObjectBase.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 44 44 m_UsedFiles.insert(pathname); 45 45 46 46 CXeromyces XeroFile; 47 if (XeroFile.Load(g_VFS, pathname ) != PSRETURN_OK)47 if (XeroFile.Load(g_VFS, pathname, "actor") != PSRETURN_OK) 48 48 return false; 49 49 50 50 // Define all the elements used in the XML file -
source/graphics/ObjectManager.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 25 25 #include "ps/Game.h" 26 26 #include "ps/Profile.h" 27 27 #include "ps/Filesystem.h" 28 #include "ps/XML/Xeromyces.h" 28 29 #include "simulation2/Simulation2.h" 29 30 #include "simulation2/components/ICmpTerrain.h" 30 31 #include "simulation2/components/ICmpVisual.h" … … 62 63 : m_MeshManager(meshManager), m_SkeletonAnimManager(skeletonAnimManager), m_Simulation(simulation) 63 64 { 64 65 RegisterFileReloadFunc(ReloadChangedFileCB, this); 66 67 if (!CXeromyces::AddValidator(g_VFS, "actor", "art/actors/actor.rng")) 68 LOGERROR("CObjectManager: failed to load actor grammar file 'art/actors/actor.rng'"); 65 69 } 66 70 67 71 CObjectManager::~CObjectManager() -
source/graphics/ParticleEmitterType.cpp
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 361 361 m_Texture = g_Renderer.GetTextureManager().GetErrorTexture(); 362 362 363 363 CXeromyces XeroFile; 364 PSRETURN ret = XeroFile.Load(g_VFS, path );364 PSRETURN ret = XeroFile.Load(g_VFS, path, "particle"); 365 365 if (ret != PSRETURN_OK) 366 366 return false; 367 367 368 // TODO: should do some RNG schema validation369 370 368 // Define all the elements and attributes used in the XML file 371 369 #define EL(x) int el_##x = XeroFile.GetElementID(#x) 372 370 #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) -
source/graphics/ShaderManager.cpp
28 28 #include "ps/Filesystem.h" 29 29 #include "ps/PreprocessorWrapper.h" 30 30 #include "ps/Profile.h" 31 #if USE_SHADER_XML_VALIDATION 32 # include "ps/XML/RelaxNG.h" 33 #endif 31 34 #include "ps/XML/Xeromyces.h" 32 35 #include "ps/XML/XMLWriter.h" 33 36 #include "renderer/Renderer.h" … … 47 50 #if USE_SHADER_XML_VALIDATION 48 51 { 49 52 TIMER_ACCRUE(tc_ShaderValidation); 50 CVFSFile grammar; 51 if (grammar.Load(g_VFS, L"shaders/program.rng") != PSRETURN_OK) 52 LOGERROR("Failed to read grammar shaders/program.rng"); 53 else 54 { 55 if (!m_Validator.LoadGrammar(grammar.GetAsString())) 56 LOGERROR("Failed to load grammar shaders/program.rng"); 57 } 53 54 if (!CXeromyces::AddValidator(g_VFS, "shader", "shaders/program.rng")) 55 LOGERROR("CShaderManager: failed to load grammar shaders/program.rng"); 58 56 } 59 57 #endif 60 58 … … 141 139 XML_Start(); 142 140 XML_SetPrettyPrint(false); 143 141 XML_WriteXMB(XeroFile); 144 bool ok = m_Validator.ValidateEncoded(wstring_from_utf8(name), XML_GetOutput());142 bool ok = CXeromyces::GetValidator("shader").ValidateEncoded(wstring_from_utf8(name), XML_GetOutput()); 145 143 if (!ok) 146 144 return false; 147 145 } -
source/graphics/ShaderManager.h
121 121 typedef boost::unordered_map<VfsPath, std::set<std::weak_ptr<CShaderProgram>, std::owner_less<std::weak_ptr<CShaderProgram>>>> HotloadFilesMap; 122 122 HotloadFilesMap m_HotloadFiles; 123 123 124 #if USE_SHADER_XML_VALIDATION125 RelaxNGValidator m_Validator;126 #endif127 128 124 bool NewProgram(const char* name, const CShaderDefines& defines, CShaderProgramPtr& program); 129 125 bool NewEffect(const char* name, const CShaderDefines& defines, CShaderTechniquePtr& tech); 130 126 -
source/graphics/TerrainProperties.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 46 46 CTerrainPropertiesPtr CTerrainProperties::FromXML(const CTerrainPropertiesPtr& parent, const VfsPath& pathname) 47 47 { 48 48 CXeromyces XeroFile; 49 if (XeroFile.Load(g_VFS, pathname ) != PSRETURN_OK)49 if (XeroFile.Load(g_VFS, pathname, "terrain") != PSRETURN_OK) 50 50 return CTerrainPropertiesPtr(); 51 51 52 52 XMBElement root = XeroFile.GetRoot(); -
source/graphics/TerrainTextureEntry.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 45 45 ENSURE(properties); 46 46 47 47 CXeromyces XeroFile; 48 if (XeroFile.Load(g_VFS, path ) != PSRETURN_OK)48 if (XeroFile.Load(g_VFS, path, "terrain_texture") != PSRETURN_OK) 49 49 { 50 50 LOGERROR("Terrain xml not found (%s)", path.string8()); 51 51 return; -
source/graphics/TerrainTextureManager.cpp
1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 30 30 31 31 #include "ps/CLogger.h" 32 32 #include "ps/Filesystem.h" 33 #include "ps/XML/Xeromyces.h" 33 34 34 35 #include <boost/algorithm/string.hpp> 35 36 36 37 37 38 CTerrainTextureManager::CTerrainTextureManager(): 38 39 m_LastGroupIndex(0) 39 {} 40 { 41 if (!CXeromyces::AddValidator(g_VFS, "terrain", "art/terrains/terrain.rng")) 42 LOGERROR("CTerrainTextureManager: failed to load grammar file 'art/terrains/terrain.rng'"); 43 if (!CXeromyces::AddValidator(g_VFS, "terrain_texture", "art/terrains/terrain_texture.rng")) 44 LOGERROR("CTerrainTextureManager: failed to load grammar file 'art/terrains/terrain_texture.rng'"); 45 } 40 46 41 47 CTerrainTextureManager::~CTerrainTextureManager() 42 48 { -
source/graphics/TextureConverter.cpp
96 96 CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath& path) const 97 97 { 98 98 CXeromyces XeroFile; 99 if (XeroFile.Load(m_VFS, path ) != PSRETURN_OK)99 if (XeroFile.Load(m_VFS, path, "texture") != PSRETURN_OK) 100 100 return NULL; 101 101 102 102 // Define all the elements used in the XML file -
source/gui/CGUI.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 929 929 Paths.insert(Filename); 930 930 931 931 CXeromyces XeroFile; 932 if (XeroFile.Load(g_VFS, Filename ) != PSRETURN_OK)932 if (XeroFile.Load(g_VFS, Filename, "gui") != PSRETURN_OK) 933 933 // Fail silently 934 934 return; 935 935 … … 1353 1353 if (!directory.empty()) 1354 1354 LOGWARNING("GUI: Include element found with file name (%s) and directory name (%s). Only the file will be processed.", utf8_from_wstring(filename), utf8_from_wstring(directory)); 1355 1355 1356 Paths.insert(filename);1357 1358 1356 CXeromyces XeroIncluded; 1359 if (XeroIncluded.Load(g_VFS, filename ) != PSRETURN_OK)1357 if (XeroIncluded.Load(g_VFS, filename, "gui") != PSRETURN_OK) 1360 1358 { 1361 1359 LOGERROR("GUI: Error reading included XML: '%s'", utf8_from_wstring(filename)); 1362 1360 continue; … … 1380 1378 // one might use the same parts of the GUI in different situations 1381 1379 Paths.insert(*it); 1382 1380 CXeromyces XeroIncluded; 1383 if (XeroIncluded.Load(g_VFS, *it ) != PSRETURN_OK)1381 if (XeroIncluded.Load(g_VFS, *it, "gui") != PSRETURN_OK) 1384 1382 { 1385 1383 LOGERROR("GUI: Error reading included XML: '%s'", (*it).string8()); 1386 1384 continue; -
source/gui/GUIManager.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 59 59 m_ScriptInterface.reset(new ScriptInterface("Engine", "GUIManager", m_ScriptRuntime)); 60 60 m_ScriptInterface->SetCallbackData(this); 61 61 m_ScriptInterface->LoadGlobalScripts(); 62 63 if (!CXeromyces::AddValidator(g_VFS, "gui_page", "gui/gui_page.rng")) 64 LOGERROR("CGUIManager: failed to load GUI page grammar file 'gui/gui_page.rng'"); 65 if (!CXeromyces::AddValidator(g_VFS, "gui", "gui/gui.rng")) 66 LOGERROR("CGUIManager: failed to load GUI XML grammar file 'gui/gui.rng'"); 67 62 68 RegisterFileReloadFunc(ReloadChangedFileCB, this); 63 69 } 64 70 … … 192 198 page.inputs.insert(path); 193 199 194 200 CXeromyces xero; 195 if (xero.Load(g_VFS, path ) != PSRETURN_OK)201 if (xero.Load(g_VFS, path, "gui_page") != PSRETURN_OK) 196 202 // Fail silently (Xeromyces reported the error) 197 203 return; 198 204 -
source/gui/MiniMap.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 38 38 #include "ps/Game.h" 39 39 #include "ps/Profile.h" 40 40 #include "ps/World.h" 41 #include "ps/XML/Xeromyces.h" 41 42 #include "renderer/Renderer.h" 42 43 #include "renderer/WaterManager.h" 43 44 #include "scriptinterface/ScriptInterface.h" … … 70 71 m_Clicking = false; 71 72 m_MouseHovering = false; 72 73 74 // Register Relax NG validator 75 CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); 76 73 77 // Get the maximum height for unit passage in water. 74 78 CParamNode externalParamNode; 75 CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml" );79 CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml", "pathfinder"); 76 80 const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses"); 77 81 if (pathingSettings.GetChild("default").IsOk() && pathingSettings.GetChild("default").GetChild("MaxWaterDepth").IsOk()) 78 82 m_ShallowPassageHeight = pathingSettings.GetChild("default").GetChild("MaxWaterDepth").ToFloat(); -
source/ps/GameSetup/GameSetup.cpp
1071 1071 1072 1072 ogl_WarnIfError(); 1073 1073 1074 // TODO: where should this go? 1075 CXeromyces::AddValidator(g_VFS, "map", "maps/scenario.rng"); 1076 1074 1077 try 1075 1078 { 1076 1079 if (!Autostart(args)) -
source/ps/XML/RelaxNG.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 22 22 #include "lib/timer.h" 23 23 #include "lib/utf8.h" 24 24 #include "ps/CLogger.h" 25 #include "ps/Filesystem.h" 25 26 26 27 #include <libxml/relaxng.h> 27 28 #include <map> … … 33 34 * To minimise that problem, keep a global cache of parsed schemas, so we don't 34 35 * leak an indefinitely large amount of memory when repeatedly restarting the simulation. 35 36 */ 37 class RelaxNGSchema; 38 static std::map<std::string, shared_ptr<RelaxNGSchema> > g_SchemaCache; 39 static CMutex g_SchemaCacheLock; 40 41 void ClearSchemaCache() 42 { 43 CScopeLock lock(g_SchemaCacheLock); 44 g_SchemaCache.clear(); 45 } 46 47 static void relaxNGErrorHandler(void* UNUSED(userData), xmlErrorPtr error) 48 { 49 // Strip a trailing newline 50 std::string message = error->message; 51 if (message.length() > 0 && message[message.length()-1] == '\n') 52 message.erase(message.length()-1); 53 54 LOGERROR("RelaxNGValidator: Validation %s: %s:%d: %s", 55 error->level == XML_ERR_WARNING ? "warning" : "error", 56 error->file, error->line, message.c_str()); 57 } 36 58 37 59 class RelaxNGSchema 38 60 { … … 56 78 } 57 79 }; 58 80 59 static std::map<std::string, shared_ptr<RelaxNGSchema> > g_SchemaCache;60 static CMutex g_SchemaCacheLock;61 62 81 RelaxNGValidator::RelaxNGValidator() : 63 82 m_Schema(NULL) 64 83 { … … 70 89 71 90 bool RelaxNGValidator::LoadGrammar(const std::string& grammar) 72 91 { 73 TIMER_ACCRUE(xml_validation);74 75 92 shared_ptr<RelaxNGSchema> schema; 76 93 77 94 { … … 89 106 } 90 107 91 108 m_Schema = schema->m_Schema; 92 93 109 if (!m_Schema) 94 110 return false; 111 112 MD5 hash; 113 hash.Update((const u8*)grammar.c_str(), grammar.length()); 114 m_Hash = hash; 115 95 116 return true; 96 117 } 97 118 98 bool RelaxNGValidator::Validate(const std::wstring& filename, const std::wstring& document) 119 bool RelaxNGValidator::LoadGrammarFile(const PIVFS& vfs, const VfsPath& grammarPath) 120 { 121 CVFSFile file; 122 if (file.Load(vfs, grammarPath) != PSRETURN_OK) 123 return false; 124 125 return LoadGrammar(file.DecodeUTF8()); 126 } 127 128 bool RelaxNGValidator::Validate(const std::wstring& filename, const std::wstring& document) const 99 129 { 100 130 std::string docutf8 = "<?xml version='1.0' encoding='utf-8'?>" + utf8_from_wstring(document); 101 131 102 132 return ValidateEncoded(filename, docutf8); 103 133 } 104 134 105 bool RelaxNGValidator::ValidateEncoded(const std::wstring& filename, const std::string& document) 135 bool RelaxNGValidator::ValidateEncoded(const std::wstring& filename, const std::string& document) const 106 136 { 107 137 TIMER_ACCRUE(xml_validation); 108 138 … … 115 145 xmlDocPtr doc = xmlReadMemory(document.c_str(), (int)document.size(), utf8_from_wstring(filename).c_str(), NULL, XML_PARSE_NONET); 116 146 if (doc == NULL) 117 147 { 118 LOGERROR("RelaxNGValidator: Failed to parse document ");148 LOGERROR("RelaxNGValidator: Failed to parse document '%s'", utf8_from_wstring(filename).c_str()); 119 149 return false; 120 150 } 121 151 152 bool ret = ValidateEncoded(doc); 153 xmlFreeDoc(doc); 154 return ret; 155 } 156 157 bool RelaxNGValidator::ValidateEncoded(xmlDocPtr doc) const 158 { 122 159 xmlRelaxNGValidCtxtPtr ctxt = xmlRelaxNGNewValidCtxt(m_Schema); 160 xmlRelaxNGSetValidStructuredErrors(ctxt, &relaxNGErrorHandler, NULL); 123 161 int ret = xmlRelaxNGValidateDoc(ctxt, doc); 124 162 xmlRelaxNGFreeValidCtxt(ctxt); 125 xmlFreeDoc(doc);126 163 127 164 if (ret == 0) 128 165 { … … 130 167 } 131 168 else if (ret > 0) 132 169 { 133 LOGERROR("RelaxNGValidator: Validation failed ");170 LOGERROR("RelaxNGValidator: Validation failed for '%s'", doc->name); 134 171 return false; 135 172 } 136 173 else … … 139 176 return false; 140 177 } 141 178 } 179 180 bool RelaxNGValidator::CanValidate() const 181 { 182 return m_Schema != NULL; 183 } -
source/ps/XML/RelaxNG.h
1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 18 18 #ifndef INCLUDED_RELAXNG 19 19 #define INCLUDED_RELAXNG 20 20 21 #include "lib/file/vfs/vfs.h" 22 #include "maths/MD5.h" 23 21 24 typedef struct _xmlRelaxNG xmlRelaxNG; 22 25 typedef xmlRelaxNG *xmlRelaxNGPtr; 26 typedef struct _xmlDoc xmlDoc; 27 typedef xmlDoc *xmlDocPtr; 28 29 class IRelaxNGGrammar; 23 30 24 31 class RelaxNGValidator 25 32 { … … 29 36 30 37 bool LoadGrammar(const std::string& grammar); 31 38 32 bool Validate(const std::wstring& filename, const std::wstring& document); 39 bool LoadGrammarFile(const PIVFS& vfs, const VfsPath& grammarPath); 40 41 MD5 GetGrammarHash() const { return m_Hash; } 42 43 bool Validate(const std::wstring& filename, const std::wstring& document) const; 33 44 34 bool ValidateEncoded(const std::wstring& filename, const std::string& document); 45 bool ValidateEncoded(const std::wstring& filename, const std::string& document) const; 46 47 bool ValidateEncoded(xmlDocPtr doc) const; 48 49 bool CanValidate() const; 35 50 36 51 private: 52 MD5 m_Hash; 37 53 xmlRelaxNGPtr m_Schema; 38 54 }; 39 55 56 void ClearSchemaCache(); 57 40 58 #endif // INCLUDED_RELAXNG -
source/ps/XML/Xeromyces.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 27 27 #include "ps/CacheLoader.h" 28 28 #include "ps/CLogger.h" 29 29 #include "ps/Filesystem.h" 30 #include "RelaxNG.h" 30 31 #include "Xeromyces.h" 31 32 32 33 #include <libxml/parser.h> 33 34 35 static CMutex g_ValidatorCacheLock; 36 static std::map<const std::string, RelaxNGValidator> g_ValidatorCache; 37 static bool g_XeromycesStarted = false; 38 34 39 static void errorHandler(void* UNUSED(userData), xmlErrorPtr error) 35 40 { 36 41 // Strip a trailing newline … … 45 50 // so the caching is less transparent than it should be 46 51 } 47 52 48 static bool g_XeromycesStarted = false;49 53 void CXeromyces::Startup() 50 54 { 51 55 ENSURE(!g_XeromycesStarted); 52 56 xmlInitParser(); 53 57 xmlSetStructuredErrorFunc(NULL, &errorHandler); 54 58 g_XeromycesStarted = true; 59 60 g_ValidatorCache.insert(std::make_pair("", RelaxNGValidator())); 55 61 } 56 62 57 63 void CXeromyces::Terminate() … … 59 65 ENSURE(g_XeromycesStarted); 60 66 xmlCleanupParser(); 61 67 xmlSetStructuredErrorFunc(NULL, NULL); 68 g_ValidatorCache.clear(); 69 ClearSchemaCache(); 62 70 g_XeromycesStarted = false; 63 71 } 64 72 65 PSRETURN CXeromyces::Load(const PIVFS& vfs, const VfsPath& filename) 73 bool CXeromyces::AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath) 74 { 75 ENSURE(g_XeromycesStarted); 76 77 RelaxNGValidator validator; 78 if (!validator.LoadGrammarFile(vfs, grammarPath)) 79 { 80 LOGERROR("CXeromyces: failed adding validator for '%s'", grammarPath.string8()); 81 return false; 82 } 83 { 84 CScopeLock lock(g_ValidatorCacheLock); 85 std::map<const std::string, RelaxNGValidator>::iterator it = g_ValidatorCache.find(name); 86 if (it != g_ValidatorCache.end()) 87 g_ValidatorCache.erase(it); 88 g_ValidatorCache.insert(std::make_pair(name, validator)); 89 } 90 return true; 91 } 92 93 RelaxNGValidator& CXeromyces::GetValidator(const std::string &name) 94 { 95 CScopeLock lock(g_ValidatorCacheLock); 96 if (g_ValidatorCache.find(name) == g_ValidatorCache.end()) 97 return g_ValidatorCache.find("")->second; 98 return g_ValidatorCache.find(name)->second; 99 } 100 101 PSRETURN CXeromyces::Load(const PIVFS& vfs, const VfsPath& filename, const std::string& validatorName /* = "" */) 66 102 { 67 103 ENSURE(g_XeromycesStarted); 68 104 69 105 CCacheLoader cacheLoader(vfs, L".xmb"); 70 106 107 RelaxNGValidator& validator = GetValidator(validatorName); 71 108 VfsPath xmbPath; 72 Status ret = cacheLoader.TryLoadingCached(filename, MD5(), XMBVersion, xmbPath);109 Status ret = cacheLoader.TryLoadingCached(filename, validator.GetGrammarHash(), XMBVersion, xmbPath); 73 110 74 111 if (ret == INFO::OK) 75 112 { … … 94 131 } 95 132 96 133 // XMB isn't up to date with the XML, so rebuild it 97 return ConvertFile(vfs, filename, xmbPath );134 return ConvertFile(vfs, filename, xmbPath, validatorName); 98 135 } 99 136 100 bool CXeromyces::GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath, VfsPath& archiveCachePath )137 bool CXeromyces::GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath, VfsPath& archiveCachePath, const std::string& validatorName /* = "" */) 101 138 { 102 139 CCacheLoader cacheLoader(vfs, L".xmb"); 103 140 104 141 archiveCachePath = cacheLoader.ArchiveCachePath(sourcePath); 105 142 106 return (ConvertFile(vfs, sourcePath, VfsPath("cache") / archiveCachePath ) == PSRETURN_OK);143 return (ConvertFile(vfs, sourcePath, VfsPath("cache") / archiveCachePath, validatorName) == PSRETURN_OK); 107 144 } 108 145 109 PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath )146 PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath, const std::string& validatorName) 110 147 { 111 148 CVFSFile input; 112 149 if (input.Load(vfs, filename)) … … 115 152 return PSRETURN_Xeromyces_XMLOpenFailed; 116 153 } 117 154 118 CStr8 filename8(CStrW(filename.string()).ToUTF8()); 119 xmlDocPtr doc = xmlReadMemory((const char*)input.GetBuffer(), (int)input.GetBufferSize(), 120 filename8.c_str(), NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA); 121 if (! doc) 155 xmlDocPtr doc = xmlReadMemory((const char*)input.GetBuffer(), input.GetBufferSize(), CStrW(filename.string()).ToUTF8().c_str(), NULL, 156 XML_PARSE_NONET|XML_PARSE_NOCDATA); 157 if (!doc) 122 158 { 123 159 LOGERROR("CXeromyces: Failed to parse XML file %s", filename.string8()); 124 160 return PSRETURN_Xeromyces_XMLParseError; 125 161 } 126 162 163 RelaxNGValidator& validator = GetValidator(validatorName); 164 if (validator.CanValidate() && !validator.ValidateEncoded(doc)) 165 { 166 // For now, log the error and continue, in the future we might fail 167 LOGERROR("CXeromyces: failed to validate XML file %s", filename.string8()); 168 } 169 127 170 WriteBuffer writeBuffer; 128 171 CreateXMB(doc, writeBuffer); 129 172 … … 160 203 return true; 161 204 } 162 205 163 PSRETURN CXeromyces::LoadString(const char* xml )206 PSRETURN CXeromyces::LoadString(const char* xml, const std::string& validatorName /* = "" */) 164 207 { 165 208 ENSURE(g_XeromycesStarted); 166 209 167 xmlDocPtr doc = xmlReadMemory(xml, (int)strlen(xml), " ", NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA);168 if (! 210 xmlDocPtr doc = xmlReadMemory(xml, (int)strlen(xml), "(no file)", NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA); 211 if (!doc) 169 212 { 170 213 LOGERROR("CXeromyces: Failed to parse XML string"); 171 214 return PSRETURN_Xeromyces_XMLParseError; 172 215 } 173 216 217 RelaxNGValidator& validator = GetValidator(validatorName); 218 if (validator.CanValidate() && !validator.ValidateEncoded(doc)) 219 { 220 // For now, log the error and continue, in the future we might fail 221 LOGERROR("CXeromyces: failed to validate XML string"); 222 } 223 174 224 WriteBuffer writeBuffer; 175 225 CreateXMB(doc, writeBuffer); 176 226 -
source/ps/XML/Xeromyces.h
1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 33 33 34 34 #include "lib/file/vfs/vfs.h" 35 35 36 class RelaxNGValidator; 36 37 class WriteBuffer; 37 class MD5;38 38 39 39 typedef struct _xmlDoc xmlDoc; 40 40 typedef xmlDoc* xmlDocPtr; … … 46 46 /** 47 47 * Load from an XML file (with invisible XMB caching). 48 48 */ 49 PSRETURN Load(const PIVFS& vfs, const VfsPath& filename );49 PSRETURN Load(const PIVFS& vfs, const VfsPath& filename, const std::string& validatorName = ""); 50 50 51 51 /** 52 52 * Load from an in-memory XML string (with no caching). 53 53 */ 54 PSRETURN LoadString(const char* xml );54 PSRETURN LoadString(const char* xml, const std::string& validatorName = ""); 55 55 56 56 /** 57 57 * Convert the given XML file into an XMB in the archive cache. 58 58 * Returns the XMB path in @p archiveCachePath. 59 59 * Returns false on error. 60 60 */ 61 bool GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath, VfsPath& archiveCachePath );61 bool GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath, VfsPath& archiveCachePath, const std::string& validatorName = ""); 62 62 63 63 /** 64 64 * Call once when initialising the program, to load libxml2. … … 71 71 */ 72 72 static void Terminate(); 73 73 74 static bool AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath); 75 76 static RelaxNGValidator& GetValidator(const std::string& name); 77 74 78 private: 75 PSRETURN ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath );79 PSRETURN ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath, const std::string& validatorName); 76 80 77 81 bool ReadXMBFile(const PIVFS& vfs, const VfsPath& filename); 78 82 -
source/ps/XML/tests/test_RelaxNG.h
1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 44 44 { 45 45 TestLogger logger; 46 46 TS_ASSERT(!v.Validate(L"doc", L"<bogus/>")); 47 TS_ASSERT_STR_CONTAINS(logger.GetOutput(), " Parseerror: doc:1: Expecting element test, got bogus");47 TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "Validation error: doc:1: Expecting element test, got bogus"); 48 48 } 49 49 50 50 { -
source/simulation2/components/CCmpPathfinder.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 27 27 #include "ps/CLogger.h" 28 28 #include "ps/CStr.h" 29 29 #include "ps/Profile.h" 30 #include "ps/XML/Xeromyces.h" 30 31 #include "renderer/Scene.h" 31 32 #include "simulation2/MessageTypes.h" 32 33 #include "simulation2/components/ICmpObstruction.h" … … 56 57 57 58 m_SameTurnMovesCount = 0; 58 59 60 // Register Relax NG validator 61 CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); 62 59 63 // Since this is used as a system component (not loaded from an entity template), 60 64 // we can't use the real paramNode (it won't get handled properly when deserializing), 61 65 // so load the data from a special XML file. 62 66 CParamNode externalParamNode; 63 CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml" );67 CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml", "pathfinder"); 64 68 65 69 // Previously all move commands during a turn were 66 70 // queued up and processed asynchronously at the start -
source/simulation2/components/CCmpTerritoryManager.cpp
1 /* Copyright (C) 201 2Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 26 26 #include "graphics/TerritoryBoundary.h" 27 27 #include "maths/MathUtil.h" 28 28 #include "maths/Vector2D.h" 29 #include "ps/XML/Xeromyces.h" 29 30 #include "renderer/Renderer.h" 30 31 #include "renderer/Scene.h" 31 32 #include "renderer/TerrainOverlay.h" … … 122 123 123 124 m_AnimTime = 0.0; 124 125 126 // Register Relax NG validator 127 CXeromyces::AddValidator(g_VFS, "territorymanager", "simulation/data/territorymanager.rng"); 128 125 129 CParamNode externalParamNode; 126 CParamNode::LoadXML(externalParamNode, L"simulation/data/territorymanager.xml" );130 CParamNode::LoadXML(externalParamNode, L"simulation/data/territorymanager.xml", "territorymanager"); 127 131 128 132 int impassableCost = externalParamNode.GetChild("TerritoryManager").GetChild("ImpassableCost").ToInt(); 129 133 ENSURE(0 <= impassableCost && impassableCost <= 255); -
source/simulation2/system/ParamNode.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 42 42 ret.ApplyLayer(xmb, xmb.GetRoot(), sourceIdentifier); 43 43 } 44 44 45 void CParamNode::LoadXML(CParamNode& ret, const VfsPath& path )45 void CParamNode::LoadXML(CParamNode& ret, const VfsPath& path, const std::string& validatorName) 46 46 { 47 47 CXeromyces xero; 48 PSRETURN ok = xero.Load(g_VFS, path );48 PSRETURN ok = xero.Load(g_VFS, path, validatorName); 49 49 if (ok != PSRETURN_OK) 50 50 return; // (Xeromyces already logged an error) 51 51 -
source/simulation2/system/ParamNode.h
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 134 134 * Any existing data in @a ret will be overwritten or else kept, so this 135 135 * can be called multiple times to build up a node from multiple inputs. 136 136 */ 137 static void LoadXML(CParamNode& ret, const VfsPath& path );137 static void LoadXML(CParamNode& ret, const VfsPath& path, const std::string& validatorName); 138 138 139 139 /** 140 140 * See LoadXML, but parses the XML string @a xml. -
source/soundmanager/SoundManager.cpp
30 30 #include "ps/ConfigDB.h" 31 31 #include "ps/Filesystem.h" 32 32 #include "ps/Profiler2.h" 33 #include "ps/XML/Xeromyces.h" 33 34 34 35 ISoundManager* g_SoundManager = NULL; 35 36 … … 253 254 m_PlayListItems = new PlayList; 254 255 } 255 256 257 if (!CXeromyces::AddValidator(g_VFS, "sound_group", "audio/sound_group.rng")) 258 LOGERROR("CSoundManager: failed to load grammar file 'audio/sound_group.rng'"); 259 256 260 RegisterFileReloadFunc(ReloadChangedFileCB, this); 257 261 } 258 262 -
source/soundmanager/scripting/SoundGroup.cpp
283 283 bool CSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML) 284 284 { 285 285 CXeromyces XeroFile; 286 if (XeroFile.Load(g_VFS, pathnameXML ) != PSRETURN_OK)286 if (XeroFile.Load(g_VFS, pathnameXML, "sound_group") != PSRETURN_OK) 287 287 { 288 288 HandleError(L"error loading file", pathnameXML, ERR::FAIL); 289 289 return false;