summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2010-04-08 21:42:29 -0600
committerJared Adams <jaxad0127@gmail.com>2010-04-08 22:00:52 -0600
commitc8b0e10348ea28da418985c997b324cfce865064 (patch)
tree5d1f047064295d203a4734f2099d8ecb61c7f2ae
parentdb3bc0a260cd26ee58d53d2b0531d0c0c471ccd0 (diff)
downloadMana-c8b0e10348ea28da418985c997b324cfce865064.tar.gz
Mana-c8b0e10348ea28da418985c997b324cfce865064.tar.bz2
Mana-c8b0e10348ea28da418985c997b324cfce865064.tar.xz
Mana-c8b0e10348ea28da418985c997b324cfce865064.zip
Fix handling of "../" and fix a bug in TSX handling
-rw-r--r--src/resources/mapreader.cpp43
-rw-r--r--src/resources/mapreader.h5
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 <iostream>
#include <zlib.h>
+// 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