From c8b0e10348ea28da418985c997b324cfce865064 Mon Sep 17 00:00:00 2001 From: Jared Adams Date: Thu, 8 Apr 2010 21:42:29 -0600 Subject: Fix handling of "../" and fix a bug in TSX handling --- src/resources/mapreader.cpp | 43 ++++++++++++++++++++++++++++++++++++------- src/resources/mapreader.h | 5 ----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 0f7ad749..219eb317 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -38,6 +38,34 @@ #include #include +// DO NOT CHANGE THESE STRINGS TO BE PASSED BY REFERENCE, AS THIS METHOD ALTERS +// (THAT IS, DESTROYS) THEM. +static std::string resolveRelativePath(std::string base, std::string relative) +{ + // Remove trailing "/", if present + size_t i = base.length(); + if (base.at(i - 1) == '/') + base.erase(i - 1, i); + + while (relative.substr(0, 3) == "../") + { + relative.erase(0, 3); // Remove "../" + if (!base.empty()) // If base is already empty, we can't trim anymore + { + i = base.find_last_of('/'); + if (i == std::string::npos) + i = 0; + base.erase(i, base.length()); // Remove deepest folder in base + } + } + + // Re-add trailing slash, if needed + if (!base.empty() && base[base.length() - 1] != '/') + base += '/'; + + return base + relative; +} + /** * Inflates either zlib or gzip deflated memory. The inflated memory is * expected to be freed by the caller. @@ -497,22 +525,24 @@ void MapReader::readLayer(xmlNodePtr node, Map *map) } } -Tileset *MapReader::readTileset(xmlNodePtr node, - const std::string &path, +Tileset *MapReader::readTileset(xmlNodePtr node, const std::string &path, Map *map) { int firstGid = XML::getProperty(node, "firstgid", 0); XML::Document* doc = NULL; Tileset *set = NULL; + std::string pathDir(path); if (xmlHasProp(node, BAD_CAST "source")) { std::string filename = XML::getProperty(node, "source", ""); - while (filename.substr(0, 3) == "../") - filename.erase(0, 3); // Remove "../" + filename = resolveRelativePath(path, filename); + doc = new XML::Document(filename); node = doc->rootNode(); - firstGid += XML::getProperty(node, "firstgid", 0); + + // Reset path to be realtive to the tsx file + pathDir = filename.substr(0, filename.rfind("/") + 1); } const int tw = XML::getProperty(node, "tilewidth", map->getTileWidth()); @@ -526,8 +556,7 @@ Tileset *MapReader::readTileset(xmlNodePtr node, if (!source.empty()) { - std::string sourceStr = source; - sourceStr.erase(0, 3); // Remove "../" + std::string sourceStr = resolveRelativePath(pathDir, source); ResourceManager *resman = ResourceManager::getInstance(); Image* tilebmp = resman->getImage(sourceStr); diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h index e815e0c9..dc8a48ec 100644 --- a/src/resources/mapreader.h +++ b/src/resources/mapreader.h @@ -67,11 +67,6 @@ class MapReader */ static Tileset *readTileset(xmlNodePtr node, const std::string &path, Map *map); - - /** - * Gets an integer property from an xmlNodePtr. - */ - static int getProperty(xmlNodePtr node, const char* name, int def); }; #endif -- cgit v1.2.3-60-g2f50