The Battle for Wesnoth  1.15.1+dev
client.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
3  2008 - 2015 by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "addon/info.hpp"
17 #include "addon/manager.hpp"
18 #include "addon/state.hpp"
19 #include "addon/validation.hpp"
20 #include "cursor.hpp"
21 #include "font/pango/escape.hpp"
22 #include "formula/string_utils.hpp"
23 #include "gettext.hpp"
25 #include "gui/dialogs/message.hpp"
26 #include "gui/widgets/retval.hpp"
27 #include "log.hpp"
28 #include "random.hpp"
29 #include "serialization/parser.hpp"
33 
34 #include <stdexcept>
35 
36 #include "addon/client.hpp"
37 
38 static lg::log_domain log_addons_client("addons-client");
39 #define ERR_ADDONS LOG_STREAM(err , log_addons_client)
40 #define WRN_ADDONS LOG_STREAM(warn, log_addons_client)
41 #define LOG_ADDONS LOG_STREAM(info, log_addons_client)
42 #define DBG_ADDONS LOG_STREAM(debug, log_addons_client)
43 
45 
46 addons_client::addons_client(const std::string& address)
47  : addr_(address)
48  , host_()
49  , port_()
50  , conn_(nullptr)
51  , last_error_()
52  , last_error_data_()
53 {
54  try {
55  std::tie(host_, port_) = parse_network_address(addr_, std::to_string(default_campaignd_port));
56  } catch(const std::runtime_error&) {
57  throw invalid_server_address();
58  }
59 }
60 
62 {
63  LOG_ADDONS << "connecting to server " << host_ << " on port " << port_ << '\n';
64 
65  utils::string_map i18n_symbols;
66  i18n_symbols["server_address"] = addr_;
67 
68  conn_.reset(new network_asio::connection(host_, port_));
69 
71  VGETTEXT("Connecting to $server_address|...", i18n_symbols),
73 }
74 
76 {
77  cfg.clear();
78 
79  config response_buf;
80 
81  /** @todo FIXME: get rid of this legacy "campaign"/"campaigns" silliness
82  */
83 
84  this->send_simple_request("request_campaign_list", response_buf);
85  this->wait_for_transfer_done(_("Downloading list of add-ons..."));
86 
87  std::swap(cfg, response_buf.child("campaigns"));
88 
89  return !this->update_last_error(response_buf);
90 }
91 
93 {
94  terms.clear();
95 
96  config response_buf;
97 
98  this->send_simple_request("request_terms", response_buf);
99  this->wait_for_transfer_done(_("Requesting distribution terms..."));
100 
101  if(const config& msg_cfg = response_buf.child("message")) {
102  terms = msg_cfg["message"].str();
103  }
104 
105  return !this->update_last_error(response_buf);
106 }
107 
108 bool addons_client::upload_addon(const std::string& id, std::string& response_message, config& cfg)
109 {
110  LOG_ADDONS << "preparing to upload " << id << '\n';
111 
112  response_message.clear();
113 
114  utils::string_map i18n_symbols;
115  i18n_symbols["addon_title"] = font::escape_text(cfg["title"]);
116  if(i18n_symbols["addon_title"].empty()) {
117  i18n_symbols["addon_title"] = font::escape_text(make_addon_title(id));
118  }
119 
120  if(!addon_name_legal(id)){
121  i18n_symbols["addon_id"] = font::escape_text(id);
122  this->last_error_ =
123  VGETTEXT("The add-on <i>$addon_title</i> has an invalid id '$addon_id' "
124  "and cannot be published.", i18n_symbols);
125  return false;
126  }
127 
128  std::string passphrase = cfg["passphrase"];
129  // generate a random passphrase and write it to disk
130  // if the .pbl file doesn't provide one already
131  if(passphrase.empty()) {
132  passphrase.resize(16);
133  for(std::size_t n = 0; n < passphrase.size(); ++n) {
134  passphrase[n] = randomness::generator->get_random_int('a', 'z');
135  }
136  cfg["passphrase"] = passphrase;
137  set_addon_pbl_info(id, cfg);
138 
139  LOG_ADDONS << "automatically generated an initial passphrase for " << id << '\n';
140  }
141 
142  cfg["name"] = id;
143 
144  config addon_data;
145  try {
146  archive_addon(id, addon_data);
147  } catch(const utf8::invalid_utf8_exception&){
148  this->last_error_ =
149  VGETTEXT("The add-on <i>$addon_title</i> has a file or directory "
150  "containing invalid characters and cannot be published.", i18n_symbols);
151  return false;
152  }
153 
154  std::vector<std::string> badnames;
155  if(!check_names_legal(addon_data, &badnames)){
156  this->last_error_ =
157  VGETTEXT("The add-on <i>$addon_title</i> has an invalid file or directory "
158  "name and cannot be published. "
159 
160  "File or directory names may not contain '..' or end with '.' or be longer than 255 characters. "
161  "It also may not contain whitespace, control characters, or any of the following characters:\n\n&quot; * / : &lt; &gt; ? \\ | ~"
162  , i18n_symbols);
163  this->last_error_data_ = font::escape_text(utils::join(badnames, "\n"));
164  return false;
165  }
166  if(!check_case_insensitive_duplicates(addon_data, &badnames)){
167  this->last_error_ =
168  VGETTEXT("The add-on <i>$addon_title</i> contains files or directories with case conflicts. "
169  "File or directory names may not be differently-cased versions of the same string.", i18n_symbols);
170  this->last_error_data_ = font::escape_text(utils::join(badnames, "\n"));
171  return false;
172  }
173 
174  config request_buf, response_buf;
175  request_buf.add_child("upload", cfg).add_child("data", std::move(addon_data));
176 
177  LOG_ADDONS << "sending " << id << '\n';
178 
179  this->send_request(request_buf, response_buf);
180  this->wait_for_transfer_done(VGETTEXT("Sending add-on <i>$addon_title</i>...", i18n_symbols
182 
183  if(const config& message_cfg = response_buf.child("message")) {
184  response_message = message_cfg["message"].str();
185  LOG_ADDONS << "server response: " << response_message << '\n';
186  }
187 
188  return !this->update_last_error(response_buf);
189 
190 }
191 
192 bool addons_client::delete_remote_addon(const std::string& id, std::string& response_message)
193 {
194  response_message.clear();
195 
196  config cfg = get_addon_pbl_info(id);
197 
198  utils::string_map i18n_symbols;
199  i18n_symbols["addon_title"] = font::escape_text(cfg["title"]);
200  if(i18n_symbols["addon_title"].empty()) {
201  i18n_symbols["addon_title"] = font::escape_text(make_addon_title(id));
202  }
203 
204  config request_buf, response_buf;
205  config& request_body = request_buf.add_child("delete");
206 
207  request_body["name"] = id;
208  request_body["passphrase"] = cfg["passphrase"];
209 
210  LOG_ADDONS << "requesting server to delete " << id << '\n';
211 
212  this->send_request(request_buf, response_buf);
213  this->wait_for_transfer_done(VGETTEXT("Removing add-on <i>$addon_title</i> from the server...", i18n_symbols
214  ));
215 
216  if(const config& message_cfg = response_buf.child("message")) {
217  response_message = message_cfg["message"].str();
218  LOG_ADDONS << "server response: " << response_message << '\n';
219  }
220 
221  return !this->update_last_error(response_buf);
222 }
223 
224 bool addons_client::download_addon(config& archive_cfg, const std::string& id, const std::string& title, bool increase_downloads)
225 {
226  archive_cfg.clear();
227 
228  config request_buf;
229  config& request_body = request_buf.add_child("request_campaign");
230 
231  request_body["name"] = id;
232  request_body["increase_downloads"] = increase_downloads;
233 
234  utils::string_map i18n_symbols;
235  i18n_symbols["addon_title"] = font::escape_text(title);
236 
237  LOG_ADDONS << "downloading " << id << '\n';
238 
239  this->send_request(request_buf, archive_cfg);
240  this->wait_for_transfer_done(VGETTEXT("Downloading add-on <i>$addon_title</i>...", i18n_symbols));
241 
242  return !this->update_last_error(archive_cfg);
243 }
244 
246 {
247  const cursor::setter cursor_setter(cursor::WAIT);
248 
249  utils::string_map i18n_symbols;
250  i18n_symbols["addon_title"] = font::escape_text(info.title);
251 
252  if(!check_names_legal(archive_cfg)) {
254  VGETTEXT("The add-on <i>$addon_title</i> has an invalid file or directory "
255  "name and cannot be installed.", i18n_symbols));
256  return false;
257  }
258  if(!check_case_insensitive_duplicates(archive_cfg)){
260  VGETTEXT("The add-on <i>$addon_title</i> has file or directory names "
261  "with case conflicts. This may cause problems.", i18n_symbols));
262  }
263 
264  // Add local version information before unpacking
265 
266  config* maindir = &archive_cfg.find_child("dir", "name", info.id);
267  if(!*maindir) {
268  LOG_ADDONS << "downloaded add-on '" << info.id << "' is missing its directory in the archive; creating it\n";
269  maindir = &archive_cfg.add_child("dir");
270  (*maindir)["name"] = info.id;
271  }
272 
273  LOG_ADDONS << "generating version info for add-on '" << info.id << "'\n";
274 
275  std::ostringstream info_contents;
276  config wml;
277 
278  info_contents <<
279  "#\n"
280  "# File automatically generated by Wesnoth to keep track\n"
281  "# of version information on installed add-ons. DO NOT EDIT!\n"
282  "#\n";
283 
284  info.write_minimal(wml.add_child("info"));
285  write(info_contents, wml);
286 
287  config file;
288  file["name"] = "_info.cfg";
289  file["contents"] = info_contents.str();
290 
291  maindir->add_child("file", file);
292 
293  LOG_ADDONS << "unpacking " << info.id << '\n';
294 
295  // Remove any previously installed versions
296  if(!remove_local_addon(info.id)) {
297  WRN_ADDONS << "failed to uninstall previous version of " << info.id << "; the add-on may not work properly!" << std::endl;
298  }
299 
300  unarchive_addon(archive_cfg);
301  LOG_ADDONS << "unpacking finished\n";
302 
303  return true;
304 }
305 
307 {
308  config archive;
309 
310  if(!(
311  download_addon(archive, addon.id, addon.title, !is_addon_installed(addon.id)) &&
312  install_addon(archive, addon)
313  )) {
314  const std::string& server_error = get_last_server_error();
315  if(!server_error.empty()) {
317  _("The server responded with an error:") + "\n" + server_error);
318  }
319  return false;
320  } else {
321  return true;
322  }
323 }
324 
326 {
327  install_result result;
329  result.wml_changed = false;
330 
331  auto cursor_setter = std::make_unique<cursor::setter>(cursor::WAIT);
332 
333  // TODO: We don't currently check for the need to upgrade. I'll probably
334  // work on that when implementing dependency tiers later.
335 
336  const std::set<std::string>& deps = addon.resolve_dependencies(addons);
337 
338  std::vector<std::string> missing_deps;
339  std::vector<std::string> broken_deps;
340 
341  for(const std::string& dep : deps) {
342  try {
344 
345  // ADDON_NONE means not installed.
346  if(info.state == ADDON_NONE) {
347  missing_deps.push_back(dep);
348  } else if(info.state == ADDON_INSTALLED_UPGRADABLE) {
349  // Tight now, we don't need to distinguish the lists of missing
350  // and outdated addons, so just add them to missing.
351  missing_deps.push_back(dep);
352  }
353  } catch(const std::out_of_range&) {
354  // Dependency wasn't found on server, check locally directly.
355  if(!is_addon_installed(dep)) {
356  broken_deps.push_back(dep);
357  }
358  }
359  }
360 
361  cursor_setter.reset();
362 
363  if(!broken_deps.empty()) {
364  std::string broken_deps_report;
365 
366  broken_deps_report = _n(
367  "The selected add-on has the following dependency, which is not currently installed or available from the server. Do you wish to continue?",
368  "The selected add-on has the following dependencies, which are not currently installed or available from the server. Do you wish to continue?",
369  broken_deps.size());
370  broken_deps_report += "\n";
371 
372  for(const std::string& broken_dep_id : broken_deps) {
373  broken_deps_report += "\n " + font::unicode_bullet + " " + make_addon_title(broken_dep_id);
374  }
375 
376  if(gui2::show_message(_("Broken Dependencies"), broken_deps_report, gui2::dialogs::message::yes_no_buttons) != gui2::retval::OK) {
378  return result; // canceled by user
379  }
380  }
381 
382  if(missing_deps.empty()) {
383  // No dependencies to install, carry on.
384  return result;
385  }
386 
387  {
389  for(const std::string& dep : missing_deps) {
390  options[dep] = addons.at(dep);
391  }
392 
394  bool cont = dlg.show();
395  if(!cont) {
396  return result; // the user has chosen to continue without installing anything.
397  }
398  }
399 
400  //
401  // Install dependencies now.
402  //
403 
404  std::vector<std::string> failed_titles;
405 
406  for(const std::string& dep : missing_deps) {
407  const addon_info& missing_addon = addons.at(dep);
408 
409  if(!try_fetch_addon(missing_addon)) {
410  failed_titles.push_back(missing_addon.title);
411  } else {
412  result.wml_changed = true;
413  }
414  }
415 
416  if(!failed_titles.empty()) {
417  const std::string& failed_deps_report = _n(
418  "The following dependency could not be installed. Do you still wish to continue?",
419  "The following dependencies could not be installed. Do you still wish to continue?",
420  failed_titles.size()) + std::string("\n\n") + utils::bullet_list(failed_titles);
421 
422  result.outcome = gui2::show_message(_("Dependencies Installation Failed"), failed_deps_report, gui2::dialogs::message::yes_no_buttons) == gui2::retval::OK ? install_outcome::success : install_outcome::abort; // If the user cancels, return abort. Otherwise, return success, since the user chose to ignore the failure.
423  return result;
424  }
425 
426  return result;
427 }
428 
430 {
431  const std::string& addon_id = addon.id;
432 
433  const bool pbl = have_addon_pbl_info(addon_id);
434  const bool vcs = have_addon_in_vcs_tree(addon_id);
435 
436  if(!pbl && !vcs) {
437  return true;
438  }
439 
440  utils::string_map symbols;
441  symbols["addon"] = font::escape_text(addon.title);
442  std::string text;
443  std::vector<std::string> extra_items;
444 
445  text = VGETTEXT("The add-on '$addon|' is already installed and contains additional information that will be permanently lost if you continue:", symbols);
446  text += "\n\n";
447 
448  if(pbl) {
449  extra_items.push_back(_("Publishing information file (.pbl)"));
450  }
451 
452  if(vcs) {
453  extra_items.push_back(_("Version control system (VCS) information"));
454  }
455 
456  text += utils::bullet_list(extra_items) + "\n\n";
457  text += _("Do you really wish to continue?");
458 
460 }
461 
463 {
464  if(!(do_check_before_overwriting_addon(addon))) {
465  // Just do nothing and leave.
466  install_result result;
468  result.wml_changed = false;
469 
470  return result;
471  }
472 
473  // Resolve any dependencies
474  install_result res = do_resolve_addon_dependencies(addons, addon);
475  if(res.outcome != install_outcome::success) { // this function only returns SUCCESS and ABORT as outcomes
476  return res; // user aborted
477  }
478 
479  if(!try_fetch_addon(addon)) {
481  return res; //wml_changed should have whatever value was obtained in resolving dependencies
482  } else {
483  res.wml_changed = true;
484  return res; //we successfully installed something, so now the wml was definitely changed
485  }
486 }
487 
489 {
490  if(const config& error = response_cfg.child("error")) {
491  this->last_error_ = font::escape_text(error["message"].str());
492  this->last_error_data_ = font::escape_text(error["extra_data"].str());
493  ERR_ADDONS << "server error: " << error << '\n';
494  return true;
495  } else {
496  this->last_error_.clear();
497  this->last_error_data_.clear();
498  return false;
499  }
500 }
501 
503 {
504  assert(conn_ != nullptr);
505  if(conn_ == nullptr) {
506  ERR_ADDONS << "not connected to server" << std::endl;
507  throw not_connected_to_server();
508  }
509 }
510 
511 void addons_client::send_request(const config& request, config& response)
512 {
513  check_connected();
514 
515  response.clear();
516  this->conn_->transfer(request, response);
517 }
518 
519 void addons_client::send_simple_request(const std::string& request_string, config& response)
520 {
521  config request;
522  request.add_child(request_string);
523  this->send_request(request, response);
524 }
525 struct read_addon_connection_data : public network_transmission::connection_data
526 {
528  : conn_(conn), client_(client) {}
529  std::size_t total() override { return conn_.bytes_to_read(); }
530  virtual std::size_t current() override { return conn_.bytes_read(); }
531  virtual bool finished() override { return conn_.done(); }
532  virtual void cancel() override { client_.connect(); }
533  virtual void poll() override { conn_.poll(); }
536 };
537 struct connect_connection_data : public network_transmission::connection_data
538 {
540  : conn_(conn), client_(client) {}
541  std::size_t total() override { return conn_.bytes_to_read(); }
542  std::size_t current() override { return conn_.bytes_read(); }
543  bool finished() override { return conn_.done(); }
544  void cancel() override { client_.disconnect(); }
545  void poll() override { conn_.poll(); }
548 };
549 struct write_addon_connection_data : public network_transmission::connection_data
550 {
552  : conn_(conn), client_(client) {}
553  std::size_t total() override { return conn_.bytes_to_write(); }
554  virtual std::size_t current() override { return conn_.bytes_written(); }
555  virtual bool finished() override { return conn_.done(); }
556  virtual void cancel() override { client_.connect(); }
557  virtual void poll() override { conn_.poll(); }
560 };
561 void addons_client::wait_for_transfer_done(const std::string& status_message, transfer_mode mode)
562 {
563  check_connected();
564  std::unique_ptr<network_transmission::connection_data> cd;
565  switch(mode) {
567  cd.reset(new read_addon_connection_data{*conn_, *this});
568  break;
570  cd.reset(new connect_connection_data{*conn_, *this});
571  break;
573  cd.reset(new write_addon_connection_data{*conn_, *this});
574  break;
575  default:
576  throw std::invalid_argument("Addon client: invalid transfer mode");
577  }
578 
579  gui2::dialogs::network_transmission stat(*cd, _("Add-ons Manager"), status_message);
580 
581  if(!stat.show()) {
582  // Notify the caller chain that the user aborted the operation.
583  if(mode == transfer_mode::connect) {
584  throw user_disconnect();
585  } else {
586  throw user_exit();
587  }
588  }
589 }
install_result do_resolve_addon_dependencies(const addons_list &addons, const addon_info &addon)
Warns the user about unresolved dependencies and installs them if they choose to do so...
Definition: client.cpp:325
const std::string & get_last_server_error() const
Returns the last error message sent by the server, or an empty string.
Definition: client.hpp:66
bool check_names_legal(const config &dir, std::vector< std::string > *badlist)
Scans an add-on archive for illegal names.
Definition: validation.cpp:222
ADDON_STATUS state
Definition: state.hpp:56
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition: message.cpp:152
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:420
bool check_case_insensitive_duplicates(const config &dir, std::vector< std::string > *badlist)
Scans an add-on archive for case-conflicts.
Definition: validation.cpp:231
std::string port_
Definition: client.hpp:134
std::map< std::string, t_string > string_map
virtual bool finished() override
Definition: client.cpp:555
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
config & find_child(config_key_type key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition: config.cpp:836
bool download_addon(config &archive_cfg, const std::string &id, const std::string &title, bool increase_downloads=true)
Downloads the specified add-on from the server.
Definition: client.cpp:224
std::string host_
Definition: client.hpp:133
virtual void poll() override
Definition: client.cpp:557
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
logger & info()
Definition: log.cpp:90
bool try_fetch_addon(const addon_info &addon)
Definition: client.cpp:306
bool is_addon_installed(const std::string &addon_name)
Check whether the specified add-on is currently installed.
Definition: manager.cpp:163
bool update_last_error(config &response_cfg)
Definition: client.cpp:488
addons_client(const addons_client &)=delete
virtual std::size_t current() override
Definition: client.cpp:554
std::pair< std::string, std::string > parse_network_address(const std::string &address, const std::string &default_port)
Parse a host:port style network address, supporting [] notation for ipv6 addresses.
#define ERR_ADDONS
Definition: client.cpp:39
virtual bool finished() override
Definition: client.cpp:531
std::string last_error_
Definition: client.hpp:136
bool install_addon(config &archive_cfg, const addon_info &info)
Installs the specified add-on using an archive received from the server.
Definition: client.cpp:245
void clear()
Definition: config.cpp:863
bool have_addon_in_vcs_tree(const std::string &addon_name)
Returns true if the specified add-ons appear to be managed by a &#39;supported&#39; VCS.
Definition: manager.cpp:65
void check_connected() const
Makes sure the add-ons server connection is working.
Definition: client.cpp:502
bool show(const unsigned auto_close_time=0)
Shows the window.
void write_minimal(config &cfg) const
Write only minimal WML used for state tracking (_info.cfg) files.
Definition: info.cpp:116
Add-on is not installed.
Definition: state.hpp:23
void send_request(const config &request, config &response)
Sends a request to the add-ons server.
Definition: client.cpp:511
void poll() override
Definition: client.cpp:545
connect_connection_data(network_asio::connection &conn, addons_client &client)
Definition: client.cpp:539
static lg::log_domain log_addons_client("addons-client")
#define LOG_ADDONS
Definition: client.cpp:41
const config & options()
Definition: game.cpp:582
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Definition: parser.cpp:762
virtual void poll() override
Definition: client.cpp:533
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:91
std::string bullet_list(const T &v, std::size_t indent=4, const std::string &bullet=font::unicode_bullet)
Generates a new string containing a bullet list.
addons_client & client_
Definition: client.cpp:559
read_addon_connection_data(network_asio::connection &conn, addons_client &client)
Definition: client.cpp:527
std::size_t current() override
Definition: client.cpp:542
virtual void cancel() override
Definition: client.cpp:556
std::string id
Definition: info.hpp:31
Version in the server is newer than local installation.
Definition: state.hpp:27
addons_client & client_
Definition: client.cpp:535
void set_addon_pbl_info(const std::string &addon_name, const config &cfg)
Definition: manager.cpp:93
static UNUSEDNOWARN std::string _n(const char *str1, const char *str2, int n)
Definition: gettext.hpp:95
void wait_for_transfer_done(const std::string &status_message, transfer_mode mode=transfer_mode::download)
Waits for a network transfer, displaying a status window.
Definition: client.cpp:561
A class that represents a TCP/IP connection.
Shows a yes and no button.
Definition: message.hpp:79
network_asio::connection & conn_
Definition: client.cpp:534
bool remove_local_addon(const std::string &addon)
Definition: manager.cpp:117
void connect()
Try to establish a connection to the add-ons server.
Definition: client.cpp:61
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Definition: config.cpp:1386
std::size_t total() override
Definition: client.cpp:541
Add-ons (campaignd) client class.
Definition: client.hpp:29
network_asio::connection & conn_
Definition: client.cpp:546
config get_addon_pbl_info(const std::string &addon_name)
Gets the publish information for an add-on.
Definition: manager.cpp:79
bool finished() override
Definition: client.cpp:543
std::string addr_
Definition: client.hpp:132
bool addon_name_legal(const std::string &name)
Checks whether an add-on id/name is legal or not.
Definition: validation.cpp:90
std::string escape_text(const std::string &text)
Escapes the pango markup characters in a text.
Definition: escape.hpp:32
bool do_check_before_overwriting_addon(const addon_info &addon)
Checks whether the given add-on has local .pbl or VCS information and asks before overwriting it...
Definition: client.cpp:429
Thrown by operations encountering invalid UTF-8 data.
network_asio::connection & conn_
Definition: client.cpp:558
bool have_addon_pbl_info(const std::string &addon_name)
Returns true if there&#39;s a local .pbl file stored for the specified add-on.
Definition: manager.cpp:74
void archive_addon(const std::string &addon_name, config &cfg)
Archives an add-on into a config object for campaignd transactions.
Definition: manager.cpp:241
std::size_t total() override
Definition: client.cpp:553
int get_random_int(int min, int max)
This helper method provides a random int from the underlying generator, using results of next_random...
Definition: random.hpp:51
const std::string unicode_bullet
Definition: constants.cpp:43
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
std::size_t total() override
Definition: client.cpp:529
write_addon_connection_data(network_asio::connection &conn, addons_client &client)
Definition: client.cpp:551
install_outcome outcome
Definition: client.hpp:36
rng * generator
This generator is automatically synced during synced context.
Definition: random.cpp:60
config & add_child(config_key_type key)
Definition: config.cpp:476
#define WRN_ADDONS
Definition: client.cpp:40
std::string make_addon_title(const std::string &id)
Replaces underscores to dress up file or dirnames as add-on titles.
Definition: info.cpp:226
std::string last_error_data_
Definition: client.hpp:137
std::unique_ptr< network_asio::connection > conn_
Definition: client.hpp:135
addon_tracking_info get_addon_tracking_info(const addon_info &addon)
Get information about an add-on comparing its local state with the add-ons server entry...
Definition: state.cpp:24
const unsigned short default_campaignd_port
Default port number for the addon server.
Definition: validation.cpp:24
void unarchive_addon(const config &cfg)
Definition: manager.cpp:273
std::string title
Definition: info.hpp:32
std::set< std::string > resolve_dependencies(const addons_list &addons) const
Resolve an add-on&#39;s dependency tree in a recursive fashion.
Definition: info.cpp:184
bool upload_addon(const std::string &id, std::string &response_message, config &cfg)
Requests the specified add-on to be uploaded.
Definition: client.cpp:108
Standard logging facilities (interface).
Dialog that tracks network transmissions.
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
Definition: message.cpp:205
Stores additional status information about add-ons.
Definition: state.hpp:45
addons_client & client_
Definition: client.cpp:547
Dialog was closed with the OK button.
Definition: retval.hpp:34
virtual std::size_t current() override
Definition: client.cpp:530
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
bool delete_remote_addon(const std::string &id, std::string &response_message)
Requests the specified add-on to be removed from the server.
Definition: client.cpp:192
bool request_distribution_terms(std::string &terms)
Request the add-ons server distribution terms message.
Definition: client.cpp:92
static map_location::DIRECTION n
std::map< std::string, addon_info > addons_list
Definition: info.hpp:26
virtual void cancel() override
Definition: client.cpp:532
install_result install_addon_with_checks(const addons_list &addons, const addon_info &addon)
Do a &#39;smart&#39; fetch of an add-on, checking to avoid overwrites for devs and resolving dependencies...
Definition: client.cpp:462
bool request_addons_list(config &cfg)
Request the add-ons list from the server.
Definition: client.cpp:75
void send_simple_request(const std::string &request_string, config &response)
Sends a simple request message to the add-ons server.
Definition: client.cpp:519
void cancel() override
Definition: client.cpp:544