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