1 // Copyright (C) 2017, 2020 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 //  02110-1301, USA.
17 
18 #include "tarfile.h"
19 #include "tarhelper.h"
20 
TarFile(Glib::ustring name,Glib::ustring ext)21 TarFile::TarFile(Glib::ustring name, Glib::ustring ext)
22   : d_dir(""), d_basename(name), d_extension(ext), d_tmp_filename("")
23 {
24 }
25 
TarFile(const TarFile & s)26 TarFile::TarFile(const TarFile &s)
27   : d_dir(s.d_dir), d_basename(s.d_basename), d_extension(s.d_extension),
28     d_tmp_filename ("")
29 {
30 }
31 
moved(Glib::ustring filename)32 void TarFile::moved(Glib::ustring filename)
33 {
34   created (filename);
35 }
36 
created(Glib::ustring filename)37 void TarFile::created(Glib::ustring filename)
38 {
39   setDirectory(File::get_dirname(filename));
40   setBaseName(File::get_basename(filename, false));
41   setExtension(File::get_extension(filename));
42 }
43 
getConfigurationFile(bool master) const44 Glib::ustring TarFile::getConfigurationFile(bool master) const
45 {
46   if (!master)
47     {
48       if (d_tmp_filename != "")
49         return d_tmp_filename;
50     }
51   return getDirectory() + getBaseName() + d_extension;
52 }
53 
getFileFromConfigurationFile(Glib::ustring file)54 Glib::ustring TarFile::getFileFromConfigurationFile(Glib::ustring file)
55 {
56   if (getConfigurationFile () == "")
57     return "";
58   bool broken = false;
59   Tar_Helper t(getConfigurationFile(), std::ios::in, broken);
60   if (broken == false)
61     {
62       Glib::ustring filename = t.getFile(file, broken);
63       t.Close(false);
64 
65       if (broken == false)
66         return filename;
67     }
68   return "";
69 }
70 
removeFileInCfgFile(Glib::ustring file)71 bool TarFile::removeFileInCfgFile(Glib::ustring file)
72 {
73   bool broken = false;
74   Glib::ustring infile = d_tmp_filename;
75   if (infile == "")
76     infile = getConfigurationFile();
77   Tar_Helper t(infile, std::ios::in, broken);
78   if (broken == false)
79     {
80       broken = !t.replaceFile(file, "", "");
81       t.Close();
82     }
83   return !broken;
84 }
85 
replaceFileInCfgFile(Glib::ustring file,Glib::ustring new_file,Glib::ustring & out)86 bool TarFile::replaceFileInCfgFile(Glib::ustring file, Glib::ustring new_file, Glib::ustring &out)
87 {
88   bool broken = false;
89   Glib::ustring infile = d_tmp_filename;
90   if (infile == "")
91     infile = getConfigurationFile();
92   Tar_Helper t(infile, std::ios::in, broken);
93   if (broken == false)
94     {
95       Glib::ustring bname = File::get_basename (new_file, true);
96       Glib::ustring outfile = t.makeNameUnique (bname);
97       Tar_Helper::reopen (&t);
98       if (bname != outfile && bname == file)
99         outfile = file;
100       broken = !t.replaceFile(file, new_file, outfile);
101       t.Close();
102       if (!broken)
103         out = outfile;
104     }
105   return !broken;
106 }
107 
addFileInCfgFile(Glib::ustring new_file,Glib::ustring & out)108 bool TarFile::addFileInCfgFile(Glib::ustring new_file, Glib::ustring &out)
109 {
110   bool broken = false;
111   Glib::ustring infile = d_tmp_filename;
112   if (infile == "")
113     infile = getConfigurationFile();
114   Tar_Helper t(infile, std::ios::in, broken);
115   if (broken == false)
116     {
117       Glib::ustring bname = File::get_basename (new_file, true);
118       Glib::ustring outfile = t.makeNameUnique (bname);
119       Tar_Helper::reopen (&t);
120       broken = !t.replaceFile("", new_file, outfile);
121       t.Close();
122       if (!broken)
123         out = outfile;
124     }
125   return !broken;
126 }
127 
clean_tmp_dir()128 void TarFile::clean_tmp_dir()
129 {
130   Tar_Helper::clean_tmp_dir(getConfigurationFile());
131   if (d_tmp_filename != "" && File::exists (d_tmp_filename))
132     {
133       File::erase (d_tmp_filename);
134       d_tmp_filename = "";
135     }
136 }
137 
saveTar(Glib::ustring tmpfile,Glib::ustring tmptar,Glib::ustring dest,bool add_sets) const138 bool TarFile::saveTar(Glib::ustring tmpfile, Glib::ustring tmptar, Glib::ustring dest, bool add_sets) const
139 {
140   bool broken = false;
141   Tar_Helper t(tmptar, std::ios::out, broken);
142   if (broken == true)
143     return false;
144   t.saveFile(tmpfile, File::get_basename(dest, true));
145   //now the images, go get 'em from the tarball we were made from.
146   Glib::ustring infile = d_tmp_filename;
147   if (infile == "")
148     infile = getConfigurationFile ();
149   if (infile != "")
150     {
151       std::list<Glib::ustring> delfiles;
152       Tar_Helper orig(infile, std::ios::in, broken);
153       if (broken == false)
154         {
155           std::list<Glib::ustring> extensions;
156           extensions.push_back (".png");
157           extensions.push_back (".ogg");
158           if (add_sets)
159             {
160               extensions.push_back (ARMYSET_EXT);
161               extensions.push_back (TILESET_EXT);
162               extensions.push_back (SHIELDSET_EXT);
163               extensions.push_back (CITYSET_EXT);
164             }
165           for (auto ext : extensions)
166             {
167               std::list<Glib::ustring> files = orig.getFilenames(ext);
168               for (std::list<Glib::ustring>::iterator it = files.begin();
169                    it != files.end(); it++)
170                 {
171                   Glib::ustring file = orig.getFile(*it, broken);
172                   if (broken == false)
173                     {
174                       t.saveFile(file);
175                       delfiles.push_back(file);
176                     }
177                   else
178                     break;
179                 }
180               if (broken)
181                 break;
182             }
183           orig.Close();
184           for (std::list<Glib::ustring>::iterator it = delfiles.begin();
185                it != delfiles.end(); it++)
186             File::erase(*it);
187         }
188       else
189         {
190           FILE *fileptr = fopen (infile.c_str(), "r");
191           if (fileptr)
192             fclose (fileptr);
193           else
194             broken = false;
195         }
196     }
197   t.Close();
198   File::erase(tmpfile);
199   if (broken == false)
200     {
201       if (File::copy(tmptar, dest) == true)
202         File::erase(tmptar);
203       else
204         {
205           int save_errno = errno;
206           //all that work for nothing
207           File::erase(tmptar);
208           errno = save_errno;
209           broken = true;
210         }
211     }
212   return broken == false;
213 }
214 
setNewTemporaryFile()215 void TarFile::setNewTemporaryFile ()
216 {
217   d_tmp_filename = File::get_tmp_file ();
218   bool broken = false;
219   Tar_Helper t(d_tmp_filename, std::ios::out, broken);
220   if (broken == true)
221     return;
222   t.Close ();
223 }
224 
setLoadTemporaryFile()225 void TarFile::setLoadTemporaryFile ()
226 {
227   Glib::ustring f = File::get_tmp_file ();
228   File::copy (getConfigurationFile (), f);
229   d_tmp_filename = f;
230 }
231 
isTemporaryFile() const232 bool TarFile::isTemporaryFile () const
233 {
234   return d_tmp_filename != "";
235 }
236