+TransferStatusPtr
+AddonManager::request_install_addon(const AddonId& addon_id)
+{
+ if (m_transfer_status)
+ {
+ throw std::runtime_error("only one addon install request allowed at a time");
+ }
+ else
+ {
+ { // remove addon if it already exists
+ auto it = std::find_if(m_installed_addons.begin(), m_installed_addons.end(),
+ [&addon_id](const std::unique_ptr<Addon>& addon)
+ {
+ return addon->get_id() == addon_id;
+ });
+ if (it != m_installed_addons.end())
+ {
+ log_debug << "reinstalling addon " << addon_id << std::endl;
+ if ((*it)->is_enabled())
+ {
+ disable_addon((*it)->get_id());
+ }
+ m_installed_addons.erase(it);
+ }
+ else
+ {
+ log_debug << "installing addon " << addon_id << std::endl;
+ }
+ }
+
+ Addon& addon = get_repository_addon(addon_id);
+
+ std::string install_filename = FileSystem::join(m_addon_directory, addon.get_filename());
+
+ m_transfer_status = m_downloader.request_download(addon.get_url(), install_filename);
+
+ m_transfer_status->then(
+ [this, install_filename, addon_id](bool success)
+ {
+ m_transfer_status = {};
+
+ if (success)
+ {
+ // complete the addon install
+ Addon& repository_addon = get_repository_addon(addon_id);
+
+ MD5 md5 = md5_from_file(install_filename);
+ if (repository_addon.get_md5() != md5.hex_digest())
+ {
+ if (PHYSFS_delete(install_filename.c_str()) == 0)
+ {
+ log_warning << "PHYSFS_delete failed: " << PHYSFS_getLastError() << std::endl;
+ }
+
+ throw std::runtime_error("Downloading Add-on failed: MD5 checksums differ");
+ }
+ else
+ {
+ const char* realdir = PHYSFS_getRealDir(install_filename.c_str());
+ if (!realdir)
+ {
+ throw std::runtime_error("PHYSFS_getRealDir failed: " + install_filename);
+ }
+ else
+ {
+ add_installed_archive(install_filename, md5.hex_digest());
+ }
+ }
+ }
+ });
+
+ return m_transfer_status;
+ }
+}
+