New font definition files for qMax <qwiglydee@gmail.com>'s font patch
[supertux.git] / src / addon / addon.cpp
1 //  $Id$
2 //
3 //  SuperTux - Add-on
4 //  Copyright (C) 2007 Christoph Sommer <christoph.sommer@2007.expires.deltadevelopment.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20 //
21
22 #include <string>
23 #include <sstream>
24 #include <stdexcept>
25 #include <physfs.h>
26 #include "addon/addon.hpp"
27 #include "addon/addon_manager.hpp"
28 #include "log.hpp"
29 #include "addon/md5.hpp"
30
31 std::string
32 Addon::get_md5() const
33 {
34   if (!installed) {
35     if (stored_md5 == "") log_warning << "Add-on not installed and no stored MD5 available" << std::endl;
36     return stored_md5;
37   }
38
39   if (calculated_md5 != "") return calculated_md5;
40
41   if (installed_physfs_filename == "") throw std::runtime_error("Tried to calculate MD5 of Add-on with unknown filename");
42
43   // TODO: this does not work as expected for some files -- IFileStream seems to not always behave like an ifstream.
44   //IFileStream ifs(installed_physfs_filename);
45   //std::string md5 = MD5(ifs).hex_digest();
46
47   MD5 md5;
48   PHYSFS_file* file;
49   file = PHYSFS_openRead(installed_physfs_filename.c_str());
50   unsigned char buffer[1024];
51   while (true) {
52     PHYSFS_sint64 len = PHYSFS_read(file, buffer, 1, sizeof(buffer));
53     if (len <= 0) break;
54     md5.update(buffer, len);
55   }
56   PHYSFS_close(file);
57
58   calculated_md5 = md5.hex_digest();
59   log_debug << "MD5 of " << title << ": " << calculated_md5 << std::endl;
60
61   return calculated_md5;
62 }
63
64 void
65 Addon::parse(const lisp::Lisp& lisp)
66 {
67   try {
68     lisp.get("kind", kind);  
69     lisp.get("title", title);
70     lisp.get("author", author);
71     lisp.get("license", license);
72     lisp.get("http-url", http_url);
73     lisp.get("file", suggested_filename);
74     lisp.get("md5", stored_md5);
75   } catch(std::exception& e) {
76     std::stringstream msg;
77     msg << "Problem when parsing addoninfo: " << e.what();
78     throw std::runtime_error(msg.str());
79   }
80 }
81
82 void
83 Addon::parse(std::string fname)
84 {
85   try {
86     lisp::Parser parser;
87     const lisp::Lisp* root = parser.parse(fname);
88     const lisp::Lisp* addon = root->get_lisp("supertux-addoninfo");
89     if(!addon) throw std::runtime_error("file is not a supertux-addoninfo file.");
90     parse(*addon);
91   } catch(std::exception& e) {
92     std::stringstream msg;
93     msg << "Problem when reading addoninfo '" << fname << "': " << e.what();
94     throw std::runtime_error(msg.str());
95   }
96 }
97
98 void
99 Addon::write(lisp::Writer& writer) const
100 {
101   writer.start_list("supertux-addoninfo");
102   if (kind != "") writer.write_string("kind", kind);  
103   if (title != "") writer.write_string("title", title);
104   if (author != "") writer.write_string("author", author);
105   if (license != "") writer.write_string("license", license);
106   if (http_url != "") writer.write_string("http-url", http_url);
107   if (suggested_filename != "") writer.write_string("file", suggested_filename);
108   if (stored_md5 != "") writer.write_string("md5", stored_md5);
109   writer.end_list("supertux-addoninfo");
110 }
111
112 void 
113 Addon::write(std::string fname) const
114 {
115   lisp::Writer writer(fname);
116   write(writer);
117 }
118
119 bool 
120 Addon::operator==(Addon addon2) const
121 {
122   std::string s1 = this->get_md5();
123   std::string s2 = addon2.get_md5();
124
125   if ((s1 != "") && (s2 != "")) return (s1 == s2);
126
127   if (this->title != addon2.title) return false;
128   if (this->author != addon2.author) return false;
129   if (this->kind != addon2.kind) return false;
130   return true; 
131 }
132