wfut  0.2.4
A client side C++ implementation of WFUT (WorldForge Update Tool).
WFUT.cpp
1 // This file may be redistributed and modified only under the terms of
2 // the GNU Lesser General Public License (See COPYING for details).
3 // Copyright (C) 2005 - 2007 Simon Goodall
4 
5 #include "libwfut/WFUT.h"
6 #include "libwfut/types.h"
7 #include "libwfut/IO.h"
8 #include "libwfut/FileIO.h"
9 #include "libwfut/ChannelIO.h"
10 #include "libwfut/ChannelFileList.h"
11 #include "libwfut/crc32.h"
12 #include "libwfut/platform.h"
13 
14 namespace WFUT {
15 
16 void WFUTClient::onDownloadComplete(const std::string &u, const std::string &f) {
17  DownloadComplete.emit(u, f);
18 }
19 void WFUTClient::onDownloadFailed(const std::string &u, const std::string &f, const std::string &r) {
20  DownloadFailed.emit(u,f,r);
21 }
22 
23 WFUTError WFUTClient::init() {
24  assert (m_initialised == false);
25 
26  m_io = new IO();
27  if (m_io->init()) {
28  delete m_io;
29  m_io = NULL;
30  return WFUT_GENERAL_ERROR;
31  }
32 
33  m_io->DownloadComplete.connect(sigc::mem_fun(this, &WFUTClient::onDownloadComplete));
34  m_io->DownloadFailed.connect(sigc::mem_fun(this, &WFUTClient::onDownloadFailed));
35 
36  m_initialised = true;
37 
38  return WFUT_NO_ERROR;
39 }
40 
41 WFUTError WFUTClient::shutdown() {
42  assert (m_initialised == true);
43 
44  m_io->shutdown();
45  delete m_io;
46  m_io = NULL;
47 
48  m_initialised = false;
49 
50  return WFUT_NO_ERROR;
51 }
52 
54  const std::string &urlPrefix,
55  const std::string &pathPrefix) {
56  assert (m_initialised == true);
57  const FileMap &files = updates.getFiles();
58 
59  FileMap::const_iterator I = files.begin();
60  FileMap::const_iterator Iend = files.end();
61  while (I != Iend) {
62  const FileObject &f = (I++)->second;
63  if (f.deleted) continue;
64 
65  const std::string &url = urlPrefix + updates.getName() + "/" + f.filename;
66  m_io->queueFile(pathPrefix, f.filename, url, f.crc32, f.execute);
67  }
68 }
69 
70 
72  const std::string &urlPrefix,
73  const std::string &pathPrefix) {
74  assert (m_initialised == true);
75  if (file.deleted) return;
76 
77  const std::string &url = urlPrefix + "/" + file.filename;
78  m_io->queueFile(pathPrefix, file.filename, url, file.crc32, false);
79 }
80 
81 WFUTError WFUTClient::getMirrorList(const std::string &url, MirrorList &mirrors) {
82  assert (m_initialised == true);
83 
84  FILE *fp = os_create_tmpfile();
85  if (!fp) {
86  return WFUT_GENERAL_ERROR;
87  }
88 
89  if (m_io->downloadFile(fp, url, 0)) {
90  // error
91 // fprintf(stderr, "Error downloading file list\n");
92  os_free_tmpfile(fp);
93  return WFUT_DOWNLOAD_ERROR;
94  }
95 
96  std::string xml;
97  // Pre-allocate string memory
98  xml.reserve(ftell(fp));
99  rewind(fp);
100  char buf[1024];
101  size_t n;
102  while ((n = fread(buf, sizeof(char), 1024, fp) ) > 0) {
103  xml.append(buf, n);
104  }
105 
106  os_free_tmpfile(fp);
107 
108  if (parseMirrorListXML(xml, mirrors)) {
109  // Error
110 // fprintf(stderr, "Error parsing file list\n");
111  return WFUT_PARSE_ERROR;
112  }
113 
114  return WFUT_NO_ERROR;
115 }
116 
117 
118 WFUTError WFUTClient::getChannelList(const std::string &url, ChannelList &channels) {
119  assert (m_initialised == true);
120 
121  FILE *fp = os_create_tmpfile();
122  if (!fp) {
123  return WFUT_GENERAL_ERROR;
124  }
125 
126  if (m_io->downloadFile(fp, url, 0)) {
127  // error
128 // fprintf(stderr, "Error downloading file list\n");
129  os_free_tmpfile(fp);
130  return WFUT_DOWNLOAD_ERROR;
131  }
132 
133  std::string xml;
134  // Pre-allocate string memory
135  xml.reserve(ftell(fp));
136  rewind(fp);
137  char buf[1024];
138  size_t n;
139  while ((n = fread(buf, sizeof(char), 1024, fp) ) > 0) {
140  xml.append(buf, n);
141  }
142 
143  os_free_tmpfile(fp);
144 
145  if (parseChannelListXML(xml, channels)) {
146  // Error
147 // fprintf(stderr, "Error parsing file list\n");
148  return WFUT_PARSE_ERROR;
149  }
150 
151  return WFUT_NO_ERROR;
152 }
153 
154 WFUTError WFUTClient::getFileList(const std::string &url, ChannelFileList &files) {
155  assert (m_initialised == true);
156 
157  FILE *fp = os_create_tmpfile();
158  if (!fp) {
159 // fprintf(stderr, "Unable to create temporary file\n");
160 // perror("");
161  return WFUT_GENERAL_ERROR;
162  }
163 
164  if (m_io->downloadFile(fp, url, 0)) {
165  // error
166 // fprintf(stderr, "Error downloading file list\n");
167  os_free_tmpfile(fp);
168  return WFUT_DOWNLOAD_ERROR;
169  }
170 
171  std::string xml;
172  // Pre-allocate string memory
173  xml.reserve(ftell(fp));
174  rewind(fp);
175  char buf[1024];
176  size_t n;
177  while ((n = fread(buf, sizeof(char), 1024, fp) ) > 0) {
178  xml.append(buf, n);
179  }
180 
181  os_free_tmpfile(fp);
182 
183  if (parseFileListXML(xml, files)) {
184  // Error
185 // fprintf(stderr, "Error parsing file list\n");
186  return WFUT_PARSE_ERROR;
187  }
188 
189  return WFUT_NO_ERROR;
190 }
191 
192 WFUTError WFUTClient::getLocalList(const std::string &filename, ChannelFileList &files) {
193  assert (m_initialised == true);
194  if (parseFileList(filename, files)) {
195 // printf("Error parsing local file list\n");
196  return WFUT_PARSE_ERROR;
197  }
198  return WFUT_NO_ERROR;
199 }
200 
201 WFUTError WFUTClient::saveLocalList(const ChannelFileList &files, const std::string &filename) {
202  assert (m_initialised == true);
203  if (writeFileList(filename, files)) {
204  // Error
205  return WFUT_WRITE_ERROR;
206  }
207  return WFUT_NO_ERROR;
208 }
209 
211  assert (m_initialised == true);
212  return m_io->poll();
213 }
214 
215 WFUTError WFUTClient::calculateUpdates(const ChannelFileList &server, const ChannelFileList &system, const ChannelFileList &local, ChannelFileList &updates, const std::string &prefix) {
216  const FileMap &server_map = server.getFiles();
217  const FileMap &system_map = system.getFiles();
218  const FileMap &local_map = local.getFiles();
219 
220  FileMap::const_iterator I = server_map.begin();
221  FileMap::const_iterator Iend = server_map.end();
222 
223  for (; I != Iend; ++I) {
224  const FileObject &server_obj = I->second;
225  // Server side deleted? Just ignore for now
226  if (server_obj.deleted) {
227  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_DELETED);
228  continue;
229  }
230  // find the matching local one
231  FileMap::const_iterator sys_iter = system_map.find(I->first);
232  FileMap::const_iterator loc_iter = local_map.find(I->first);
233 
234  if (loc_iter == local_map.end()) {
235  if (sys_iter == system_map.end()) {
236  // No local version, or system version
237  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_NO_LOCAL);
238  updates.addFile(server_obj);
239  } else if (server_obj.version > sys_iter->second.version) {
240  // Servere version is newer than sys version, and no local version
241  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_SERVER_SYSTEM);
242  updates.addFile(server_obj);
243  } else {
244  // Assume the sys location is valid, so no need to update
245  // No update required
246  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_NONE);
247  }
248  } else if (server_obj.version > loc_iter->second.version) {
249  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_SERVER_LOCAL);
250  updates.addFile(server_obj);
251  } else {
252  // According to xml files, the local version is the same as the server
253  // Lets check that it exists and has a matching CRC value.
254  uLong crc32;
255  if (calcCRC32(prefix + loc_iter->second.filename.c_str(), crc32) == -1) {
256  // Can't read file, so lets add it
257  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_MISSING);
258  updates.addFile(server_obj);
259  } else {
260  // Do a CRC check and warn user that the file is modified.
261  if (crc32 != server_obj.crc32) {
262  // Modified!
263  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_MODIFIED);
264  } else {
265  // No update required
266  UpdateReason.emit(server_obj.filename, WFUT_UPDATE_NONE);
267  }
268  }
269  }
270  }
271  return WFUT_NO_ERROR;
272 }
273 
274 void WFUTClient::abortDownload(const std::string &filename) {
275  m_io->abortDownload(filename);
276 }
277 
279  m_io->abortAll();
280 }
281 
282 }
WFUT::IO::downloadFile
int downloadFile(const std::string &filename, const std::string &url, uLong expected_crc32)
Definition: IO.cpp:160
WFUT::WFUTClient::DownloadComplete
sigc::signal< void, const std::string &, const std::string & > DownloadComplete
Definition: WFUT.h:149
WFUT::IO::DownloadComplete
sigc::signal< void, const std::string &, const std::string & > DownloadComplete
Definition: IO.h:98
WFUT::WFUTClient::calculateUpdates
WFUTError calculateUpdates(const ChannelFileList &server, const ChannelFileList &system, const ChannelFileList &local, ChannelFileList &updates, const std::string &prefix)
Definition: WFUT.cpp:215
WFUT::IO::abortAll
void abortAll()
Definition: IO.cpp:351
WFUT::WFUTClient::abortAll
void abortAll()
Definition: WFUT.cpp:278
WFUT::WFUTClient::abortDownload
void abortDownload(const std::string &filename)
Definition: WFUT.cpp:274
WFUT::ChannelFileList
Definition: ChannelFileList.h:17
WFUT::WFUTClient::poll
int poll()
Definition: WFUT.cpp:210
WFUT::WFUTClient::shutdown
WFUTError shutdown()
Definition: WFUT.cpp:41
WFUT::WFUTClient::updateChannel
void updateChannel(const ChannelFileList &updates, const std::string &urlPrefix, const std::string &pathPrefix)
Definition: WFUT.cpp:53
WFUT::IO::poll
int poll()
Definition: IO.cpp:251
WFUT::IO
Definition: IO.h:37
WFUT::IO::abortDownload
void abortDownload(const std::string &)
Definition: IO.cpp:364
WFUT::IO::init
int init()
Definition: IO.cpp:117
WFUT::WFUTClient::saveLocalList
WFUTError saveLocalList(const ChannelFileList &files, const std::string &filename)
Definition: WFUT.cpp:201
WFUT::IO::queueFile
int queueFile(const std::string &path, const std::string &filename, const std::string &url, uLong expected_crc32, bool executable)
Definition: IO.cpp:221
WFUT::WFUTClient::DownloadFailed
sigc::signal< void, const std::string &, const std::string &, const std::string & > DownloadFailed
Definition: WFUT.h:158
WFUT::IO::DownloadFailed
sigc::signal< void, const std::string &, const std::string &, const std::string & > DownloadFailed
Definition: IO.h:103
WFUT::ChannelFileList::getFiles
const FileMap & getFiles() const
Definition: ChannelFileList.h:36
WFUT::WFUTClient::getMirrorList
WFUTError getMirrorList(const std::string &url, MirrorList &mirrors)
Definition: WFUT.cpp:81
WFUT::ChannelFileList::getName
std::string getName() const
Definition: ChannelFileList.h:25
WFUT::IO::shutdown
int shutdown()
Definition: IO.cpp:132
WFUT::WFUTClient::UpdateReason
sigc::signal< void, const std::string &, const WFUTUpdateReason > UpdateReason
Definition: WFUT.h:166
WFUT::WFUTClient::init
WFUTError init()
Definition: WFUT.cpp:23
WFUT::WFUTClient::getChannelList
WFUTError getChannelList(const std::string &url, ChannelList &channels)
Definition: WFUT.cpp:118
WFUT::ChannelFileList::addFile
void addFile(const FileObject &fo)
Definition: ChannelFileList.h:41
WFUT::FileObject
Definition: types.h:27
WFUT::WFUTClient::getLocalList
WFUTError getLocalList(const std::string &filename, ChannelFileList &files)
Definition: WFUT.cpp:192
WFUT::WFUTClient::getFileList
WFUTError getFileList(const std::string &url, ChannelFileList &files)
Definition: WFUT.cpp:154
WFUT::WFUTClient::updateFile
void updateFile(const FileObject &file, const std::string &urlPrefix, const std::string &pathPrefix)
Definition: WFUT.cpp:71