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