-// $Id$
-//
// SuperTux - Add-on
// Copyright (C) 2007 Christoph Sommer <christoph.sommer@2007.expires.deltadevelopment.de>
+// 2014 Ingo Ruhnke <grumbel@gmail.com>
//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include <string>
-#include <sstream>
-#include <stdexcept>
-#include <physfs.h>
#include "addon/addon.hpp"
-#include "addon/addon_manager.hpp"
-#include "log.hpp"
-#include "addon/md5.hpp"
-std::string
-Addon::get_md5() const
-{
- if (!installed) {
- if (stored_md5 == "") log_warning << "Add-on not installed and no stored MD5 available" << std::endl;
- return stored_md5;
- }
+#include <physfs.h>
+#include <stdexcept>
+#include <sstream>
- if (calculated_md5 != "") return calculated_md5;
+#include "lisp/parser.hpp"
+#include "util/reader.hpp"
+#include "util/writer.hpp"
+#include "util/log.hpp"
- if (installed_physfs_filename == "") throw std::runtime_error("Tried to calculate MD5 of Add-on with unknown filename");
+namespace {
- // TODO: this does not work as expected for some files -- IFileStream seems to not always behave like an ifstream.
- //IFileStream ifs(installed_physfs_filename);
- //std::string md5 = MD5(ifs).hex_digest();
+static const char* s_allowed_characters = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- MD5 md5;
- PHYSFS_file* file;
- file = PHYSFS_openRead(installed_physfs_filename.c_str());
- unsigned char buffer[1024];
- while (true) {
- PHYSFS_sint64 len = PHYSFS_read(file, buffer, 1, sizeof(buffer));
- if (len <= 0) break;
- md5.update(buffer, len);
+Addon::Type addon_type_from_string(const std::string& type)
+{
+ if (type == "world")
+ {
+ return Addon::WORLD;
+ }
+ else if (type == "worldmap")
+ {
+ return Addon::WORLDMAP;
+ }
+ else if (type == "levelset")
+ {
+ return Addon::LEVELSET;
+ }
+ else
+ {
+ throw std::runtime_error("not a valid Addon::Type: " + type);
}
- PHYSFS_close(file);
-
- calculated_md5 = md5.hex_digest();
- log_debug << "MD5 of " << title << ": " << calculated_md5 << std::endl;
-
- return calculated_md5;
}
-void
-Addon::parse(const lisp::Lisp& lisp)
+} // namespace
+
+std::unique_ptr<Addon>
+Addon::parse(const Reader& lisp)
{
- try {
- lisp.get("kind", kind);
- lisp.get("title", title);
- lisp.get("author", author);
- lisp.get("license", license);
- lisp.get("http-url", http_url);
- lisp.get("file", suggested_filename);
- lisp.get("md5", stored_md5);
- } catch(std::exception& e) {
+ std::unique_ptr<Addon> addon(new Addon);
+
+ try
+ {
+ if (!lisp.get("id", addon->m_id))
+ {
+ throw std::runtime_error("(id ...) field missing from addon description");
+ }
+
+ if (addon->m_id.empty())
+ {
+ throw std::runtime_error("addon id is empty");
+ }
+
+ if (addon->m_id.find_first_not_of(s_allowed_characters) != std::string::npos)
+ {
+ throw std::runtime_error("addon id contains illegal characters: " + addon->m_id);
+ }
+
+ lisp.get("version", addon->m_version);
+
+ std::string type;
+ lisp.get("type", type);
+ addon->m_type = addon_type_from_string(type);
+
+ lisp.get("title", addon->m_title);
+ lisp.get("author", addon->m_author);
+ lisp.get("license", addon->m_license);
+ lisp.get("url", addon->m_url);
+ lisp.get("md5", addon->m_md5);
+
+ return addon;
+ }
+ catch(const std::exception& err)
+ {
std::stringstream msg;
- msg << "Problem when parsing addoninfo: " << e.what();
+ msg << "Problem when parsing addoninfo: " << err.what();
throw std::runtime_error(msg.str());
}
}
-void
-Addon::parse(std::string fname)
+std::unique_ptr<Addon>
+Addon::parse(const std::string& fname)
{
- try {
+ try
+ {
lisp::Parser parser;
const lisp::Lisp* root = parser.parse(fname);
const lisp::Lisp* addon = root->get_lisp("supertux-addoninfo");
- if(!addon) throw std::runtime_error("file is not a supertux-addoninfo file.");
- parse(*addon);
- } catch(std::exception& e) {
+ if(!addon)
+ {
+ throw std::runtime_error("file is not a supertux-addoninfo file.");
+ }
+ else
+ {
+ return parse(*addon);
+ }
+ }
+ catch(const std::exception& err)
+ {
std::stringstream msg;
- msg << "Problem when reading addoninfo '" << fname << "': " << e.what();
+ msg << "Problem when reading addoninfo '" << fname << "': " << err.what();
throw std::runtime_error(msg.str());
}
}
-void
-Addon::write(lisp::Writer& writer) const
+Addon::Addon() :
+ m_id(),
+ m_version(0),
+ m_type(),
+ m_title(),
+ m_author(),
+ m_license(),
+ m_url(),
+ m_md5(),
+ m_install_filename(),
+ m_enabled(false)
+{}
+
+std::string
+Addon::get_filename() const
+{
+ return get_id() + ".zip";
+}
+
+std::string
+Addon::get_install_filename() const
{
- writer.start_list("supertux-addoninfo");
- if (kind != "") writer.write_string("kind", kind);
- if (title != "") writer.write_string("title", title);
- if (author != "") writer.write_string("author", author);
- if (license != "") writer.write_string("license", license);
- if (http_url != "") writer.write_string("http-url", http_url);
- if (suggested_filename != "") writer.write_string("file", suggested_filename);
- if (stored_md5 != "") writer.write_string("md5", stored_md5);
- writer.end_list("supertux-addoninfo");
+ return m_install_filename;
}
-void
-Addon::write(std::string fname) const
+bool
+Addon::is_installed() const
{
- lisp::Writer writer(fname);
- write(writer);
+ return !m_install_filename.empty();
}
-bool
-Addon::operator==(Addon addon2) const
+bool
+Addon::is_enabled() const
{
- std::string s1 = this->get_md5();
- std::string s2 = addon2.get_md5();
+ return m_enabled;
+}
- if ((s1 != "") && (s2 != "")) return (s1 == s2);
+void
+Addon::set_install_filename(const std::string& absolute_filename, const std::string& md5)
+{
+ m_install_filename = absolute_filename;
+ m_md5 = md5;
+}
- if (this->title != addon2.title) return false;
- if (this->author != addon2.author) return false;
- if (this->kind != addon2.kind) return false;
- return true;
+void
+Addon::set_enabled(bool v)
+{
+ m_enabled = v;
}
+
+/* EOF */