// 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
#include <stdexcept>
#include <sstream>
-#include "addon/md5.hpp"
#include "lisp/parser.hpp"
#include "util/reader.hpp"
#include "util/writer.hpp"
#include "util/log.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;
- }
-
- if (calculated_md5 != "") return calculated_md5;
+namespace {
- if (installed_physfs_filename == "") throw std::runtime_error("Tried to calculate MD5 of Add-on with unknown filename");
+static const char* s_allowed_characters = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- // 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();
-
- 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
+} // 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
{
- writer.start_list("supertux-addoninfo");
- if (kind != "") writer.write("kind", kind);
- if (title != "") writer.write("title", title);
- if (author != "") writer.write("author", author);
- if (license != "") writer.write("license", license);
- if (http_url != "") writer.write("http-url", http_url);
- if (suggested_filename != "") writer.write("file", suggested_filename);
- if (stored_md5 != "") writer.write("md5", stored_md5);
- writer.end_list("supertux-addoninfo");
+ return get_id() + ".zip";
}
-void
-Addon::write(std::string fname) const
+std::string
+Addon::get_install_filename() const
{
- lisp::Writer writer(fname);
- write(writer);
+ return m_install_filename;
}
-bool
-Addon::operator==(Addon addon2) const
+bool
+Addon::is_installed() const
{
- std::string s1 = this->get_md5();
- std::string s2 = addon2.get_md5();
+ return !m_install_filename.empty();
+}
- if ((s1 != "") && (s2 != "")) return (s1 == s2);
+bool
+Addon::is_enabled() const
+{
+ return m_enabled;
+}
- 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_install_filename(const std::string& absolute_filename, const std::string& md5)
+{
+ m_install_filename = absolute_filename;
+ m_md5 = md5;
}
+void
+Addon::set_enabled(bool v)
+{
+ m_enabled = v;
+}
+
+
/* EOF */