The Battle for Wesnoth  1.15.2+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 
393  if(!gui2::dialogs::install_dependencies::execute(options)) {
394  return result; // the user has chosen to continue without installing anything.
395  }
396  }
397 
398  //
399  // Install dependencies now.
400  //
401 
402  std::vector<std::string> failed_titles;
403 
404  for(const std::string& dep : missing_deps) {
405  const addon_info& missing_addon = addons.at(dep);
406 
407  if(!try_fetch_addon(missing_addon)) {
408  failed_titles.push_back(missing_addon.title);
409  } else {
410  result.wml_changed = true;
411  }
412  }
413 
414  if(!failed_titles.empty()) {
415  const std::string& failed_deps_report = _n(
416  "The following dependency could not be installed. Do you still wish to continue?",
417  "The following dependencies could not be installed. Do you still wish to continue?",
418  failed_titles.size()) + std::string("\n\n") + utils::bullet_list(failed_titles);
419 
420  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.
421  return result;
422  }
423 
424  return result;
425 }
426 
428 {
429  const std::string& addon_id = addon.id;
430 
431  const bool pbl = have_addon_pbl_info(addon_id);
432  const bool vcs = have_addon_in_vcs_tree(addon_id);
433 
434  if(!pbl && !vcs) {
435  return true;
436  }
437 
438  utils::string_map symbols;
439  symbols["addon"] = font::escape_text(addon.title);
440  std::string text;
441  std::vector<std::string> extra_items;
442 
443  text = VGETTEXT("The add-on '$addon|' is already installed and contains additional information that will be permanently lost if you continue:", symbols);
444  text += "\n\n";
445 
446  if(pbl) {
447  extra_items.push_back(_("Publishing information file (.pbl)"));
448  }
449 
450  if(vcs) {
451  extra_items.push_back(_("Version control system (VCS) information"));
452  }
453 
454  text += utils::bullet_list(extra_items) + "\n\n";
455  text += _("Do you really wish to continue?");
456 
458 }
459 
461 {
462  if(!(do_check_before_overwriting_addon(addon))) {
463  // Just do nothing and leave.
464  install_result result;
466  result.wml_changed = false;
467 
468  return result;
469  }
470 
471  // Resolve any dependencies
472  install_result res = do_resolve_addon_dependencies(addons, addon);
473  if(res.outcome != install_outcome::success) { // this function only returns SUCCESS and ABORT as outcomes
474  return res; // user aborted
475  }
476 
477  if(!try_fetch_addon(addon)) {
479  return res; //wml_changed should have whatever value was obtained in resolving dependencies
480  } else {
481  res.wml_changed = true;
482  return res; //we successfully installed something, so now the wml was definitely changed
483  }
484 }
485 
487 {
488  if(const config& error = response_cfg.child("error")) {
489  this->last_error_ = font::escape_text(error["message"].str());
490  this->last_error_data_ = font::escape_text(error["extra_data"].str());
491  ERR_ADDONS << "server error: " << error << '\n';
492  return true;
493  } else {
494  this->last_error_.clear();
495  this->last_error_data_.clear();
496  return false;
497  }
498 }
499 
501 {
502  assert(conn_ != nullptr);
503  if(conn_ == nullptr) {
504  ERR_ADDONS << "not connected to server" << std::endl;
505  throw not_connected_to_server();
506  }
507 }
508 
509 void addons_client::send_request(const config& request, config& response)
510 {
511  check_connected();
512 
513  response.clear();
514  this->conn_->transfer(request, response);
515 }
516 
517 void addons_client::send_simple_request(const std::string& request_string, config& response)
518 {
519  config request;
520  request.add_child(request_string);
521  this->send_request(request, response);
522 }
523 struct read_addon_connection_data : public network_transmission::connection_data
524 {
526  : conn_(conn), client_(client) {}
527  std::size_t total() override { return conn_.bytes_to_read(); }
528  virtual std::size_t current() override { return conn_.bytes_read(); }
529  virtual bool finished() override { return conn_.done(); }
530  virtual void cancel() override { client_.connect(); }
531  virtual void poll() override { conn_.poll(); }
534 };
535 struct connect_connection_data : public network_transmission::connection_data
536 {
538  : conn_(conn), client_(client) {}
539  std::size_t total() override { return conn_.bytes_to_read(); }
540  std::size_t current() override { return conn_.bytes_read(); }
541  bool finished() override { return conn_.done(); }
542  void cancel() override { client_.disconnect(); }
543  void poll() override { conn_.poll(); }
546 };
547 struct write_addon_connection_data : public network_transmission::connection_data
548 {
550  : conn_(conn), client_(client) {}
551  std::size_t total() override { return conn_.bytes_to_write(); }
552  virtual std::size_t current() override { return conn_.bytes_written(); }
553  virtual bool finished() override { return conn_.done(); }
554  virtual void cancel() override { client_.connect(); }
555  virtual void poll() override { conn_.poll(); }
558 };
559 void addons_client::wait_for_transfer_done(const std::string& status_message, transfer_mode mode)
560 {
561  check_connected();
562  std::unique_ptr<network_transmission::connection_data> cd;
563  switch(mode) {
565  cd.reset(new read_addon_connection_data{*conn_, *this});
566  break;
568  cd.reset(new connect_connection_data{*conn_, *this});
569  break;
571  cd.reset(new write_addon_connection_data{*conn_, *this});
572  break;
573  default:
574  throw std::invalid_argument("Addon client: invalid transfer mode");
575  }
576 
577  gui2::dialogs::network_transmission stat(*cd, _("Add-ons Manager"), status_message);
578 
579  if(!stat.show()) {
580  // Notify the caller chain that the user aborted the operation.
581  if(mode == transfer_mode::connect) {
582  throw user_disconnect();
583  } else {
584  throw user_exit();
585  }
586  }
587 }
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:223
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:232
std::string port_
Definition: client.hpp:134
std::map< std::string, t_string > string_map
virtual bool finished() override
Definition: client.cpp:553
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:555
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:486
addons_client(const addons_client &)=delete
virtual std::size_t current() override
Definition: client.cpp:552
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:529
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:500
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:509
void poll() override
Definition: client.cpp:543
connect_connection_data(network_asio::connection &conn, addons_client &client)
Definition: client.cpp:537
static lg::log_domain log_addons_client("addons-client")
#define LOG_ADDONS
Definition: client.cpp:41
const config & options()
Definition: game.cpp:579
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Definition: parser.cpp:762
virtual void poll() override
Definition: client.cpp:531
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:557
read_addon_connection_data(network_asio::connection &conn, addons_client &client)
Definition: client.cpp:525
std::size_t current() override
Definition: client.cpp:540
virtual void cancel() override
Definition: client.cpp:554
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:533
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:559
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:532
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:539
Add-ons (campaignd) client class.
Definition: client.hpp:29
network_asio::connection & conn_
Definition: client.cpp:544
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:541
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:91
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:427
Thrown by operations encountering invalid UTF-8 data.
network_asio::connection & conn_
Definition: client.cpp:556
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:551
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:527
write_addon_connection_data(network_asio::connection &conn, addons_client &client)
Definition: client.cpp:549
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:25
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:545
Dialog was closed with the OK button.
Definition: retval.hpp:34
virtual std::size_t current() override
Definition: client.cpp:528
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
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:530
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:460
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:517
void cancel() override
Definition: client.cpp:542