Index: src/campaign_server/campaign_server.cpp
===================================================================
--- src/campaign_server/campaign_server.cpp	(revision 54177)
+++ src/campaign_server/campaign_server.cpp	(working copy)
@@ -1,6 +1,5 @@
-/* $Id$ */
 /*
-   Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
+   Copyright (C) 2012 by Pierre Talbot <ptalbot@mopong.net>
    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
 
    This program is free software; you can redistribute it and/or modify
@@ -15,594 +14,45 @@
 
 /**
  * @file
- * Wesnoth addon server.
- * Expects a "server.cfg" config file in the current directory
- * and saves addons under data/.
+ * New Wesnoth addon server based on Boost.Asio.
  */
 
+#include <string>
+
+/* filesystem.hpp
+std::string get_addon_campaigns_dir();
+read_file
+*/
 #include "filesystem.hpp"
-#include "foreach.hpp"
-#include "log.hpp"
-#include "network_worker.hpp"
-#include "serialization/binary_or_text.hpp"
-#include "serialization/parser.hpp"
-#include "serialization/string_utils.hpp"
-#include "game_config.hpp"
-#include "addon/validation.hpp"
-#include "version.hpp"
-#include "server/input_stream.hpp"
-#include "util.hpp"
 
-#include <csignal>
+/* config.hpp
+class config just handle a single node. (Doesn't open a config file).
+*/
+#include "config.hpp"
 
-#include <boost/iostreams/filter/gzip.hpp>
 
-// the fork execute is unix specific only tested on Linux quite sure it won't
-// work on Windows not sure which other platforms have a problem with it.
-#if !(defined(_WIN32))
-#include <errno.h>
-#endif
+#include "serialization/parser.hpp"
 
-static lg::log_domain log_network("network");
-#define LOG_CS if (lg::err.dont_log(log_network)) ; else lg::err(log_network, false)
+#include "campaign_server/server_options.hpp"
+#include "campaign_server/server.hpp"
 
-//compatibility code for MS compilers
-#ifndef SIGHUP
-#define SIGHUP 20
-#endif
-/** @todo FIXME: should define SIGINT here too, but to what? */
+int main(int argc, char *argv[])
+{
+  try
+  {
+    server_options so(argc, argv);
+    if(!so.print_messages())
+    {
+      config cfg = so.build_config();
+      std::cout << "Configuration requested:\n" << cfg;
 
-static void exit_sighup(int signal) {
-	assert(signal == SIGHUP);
-	LOG_CS << "SIGHUP caught, exiting without cleanup immediately.\n";
-	exit(128 + SIGHUP);
+      server addon_server(cfg);
+      addon_server.run();
+    }
+  }
+  catch(std::exception &e)
+  {
+    std::cout << e.what() << std::endl;
+  }
+  return 0;
 }
-
-static void exit_sigint(int signal) {
-	assert(signal == SIGINT);
-	LOG_CS << "SIGINT caught, exiting without cleanup immediately.\n";
-	exit(0);
-}
-
-static void exit_sigterm(int signal) {
-	assert(signal == SIGTERM);
-	LOG_CS << "SIGTERM caught, exiting without cleanup immediately.\n";
-	exit(128 + SIGTERM);
-}
-
-namespace {
-	// Markup characters recognized by GUI1 code. These must be
-	// the same as the constants defined in marked-up_text.cpp.
-	const std::string illegal_markup_chars = "*`~{^}|@#<&";
-
-	inline bool is_text_markup_char(char c)
-	{
-		return illegal_markup_chars.find(c) != std::string::npos;
-	}
-
-	config construct_message(const std::string& msg)
-	{
-		config cfg;
-		cfg.add_child("message")["message"] = msg;
-		return cfg;
-	}
-
-	config construct_error(const std::string& msg)
-	{
-		config cfg;
-		cfg.add_child("error")["message"] = "#Error: " + msg;
-		LOG_CS << "ERROR: "<<msg<<"\n";
-		return cfg;
-	}
-
-	class campaign_server
-	{
-		public:
-			explicit campaign_server(const std::string& cfgfile,size_t min_thread = 10,size_t max_thread = 0);
-			void run();
-			~campaign_server()
-			{
-				delete input_;
-				scoped_ostream cfgfile = ostream_file(file_);
-				write(*cfgfile, cfg_);
-			}
-		private:
-			/**
-			 * Fires a script, if no script defined it will always return true
-			 * If a script is defined but can't be executed it will return false
-			 */
-			void fire(const std::string& hook, const std::string& addon);
-			void convert_binary_to_gzip();
-			int load_config(); // return the server port
-			const config &campaigns() const { return cfg_.child("campaigns"); }
-			config &campaigns() { return cfg_.child("campaigns"); }
-			config cfg_;
-			const std::string file_;
-			const network::manager net_manager_;
-			std::map<std::string, std::string> hooks_;
-			input_stream* input_;
-			int compress_level_;
-			const network::server_manager server_manager_;
-
-	};
-
-	void campaign_server::fire(const std::string& hook, const std::string& addon)
-	{
-		const std::map<std::string, std::string>::const_iterator itor = hooks_.find(hook);
-		if(itor == hooks_.end()) return;
-
-		const std::string& script = itor->second;
-		if(script == "") return;
-
-#if (defined(_WIN32))
-		LOG_CS << "ERROR: Tried to execute a script on an unsupported platform\n";
-		return;
-#else
-		pid_t childpid;
-
-		if((childpid = fork()) == -1) {
-			LOG_CS << "ERROR: fork failed while updating campaign " << addon << "\n";
-			return;
-		}
-
-		if(childpid == 0) {
-			/*** We're the child process ***/
-
-			// execute the script, we run is a separate thread and share the
-			// output which will make the logging look ugly.
-			execlp(script.c_str(), script.c_str(), addon.c_str(), static_cast<char *>(NULL));
-
-			// exec() and family never return; if they do, we have a problem
-			std::cerr << "ERROR: exec failed with errno " << errno << " for addon " << addon
-			          << '\n';
-			exit(errno);
-
-		} else {
-			return;
-		}
-
-#endif
-	}
-
-	int campaign_server::load_config()
-	{
-		scoped_istream stream = istream_file(file_);
-		read(cfg_, *stream);
-		bool network_use_system_sendfile = cfg_["network_use_system_sendfile"].to_bool();
-		network_worker_pool::set_use_system_sendfile(network_use_system_sendfile);
-		cfg_["network_use_system_sendfile"] = network_use_system_sendfile;
-		/** Seems like compression level above 6 is waste of cpu cycle */
-		compress_level_ = cfg_["compress_level"].to_int(6);
-		cfg_["compress_level"] = compress_level_;
-		return cfg_["port"].to_int(default_campaignd_port);
-	}
-
-	campaign_server::campaign_server(const std::string& cfgfile,
-			size_t min_thread, size_t max_thread) :
-		cfg_(),
-		file_(cfgfile),
-		net_manager_(min_thread,max_thread),
-		hooks_(),
-		input_(0),
-		compress_level_(0), // Will be properly set by load_config()
-		server_manager_(load_config())
-	{
-#ifndef _MSC_VER
-		signal(SIGHUP, exit_sighup);
-#endif
-		signal(SIGINT, exit_sigint);
-		signal(SIGTERM, exit_sigterm);
-
-		cfg_.child_or_add("campaigns");
-
-		// load the hooks
-		hooks_.insert(std::make_pair(std::string("hook_post_upload"), cfg_["hook_post_upload"]));
-		hooks_.insert(std::make_pair(std::string("hook_post_erase"), cfg_["hook_post_erase"]));
-	}
-
-	void find_translations(const config& cfg, config& campaign)
-	{
-		foreach (const config &dir, cfg.child_range("dir"))
-		{
-			if (dir["name"] == "LC_MESSAGES") {
-				config &language = campaign.add_child("translation");
-				language["language"] = cfg["name"];
-			} else {
-				find_translations(dir, campaign);
-			}
-		}
-	}
-
-	// Add a file COPYING.txt with the GPL to an uploaded campaign.
-	void add_license(config &data)
-	{
-		config &dir = data.find_child("dir", "name", data["campaign_name"]);
-		// No top-level directory? Hm..
-		if (!dir) return;
-
-		// Don't add if it already exists.
-		if (dir.find_child("file", "name", "COPYING.txt")) return;
-		if (dir.find_child("file", "name", "COPYING")) return;
-		if (dir.find_child("file", "name", "copying.txt")) return;
-		if (dir.find_child("file", "name", "Copying.txt")) return;
-		if (dir.find_child("file", "name", "COPYING.TXT")) return;
-
-		// Copy over COPYING.txt
-		std::string contents = read_file("COPYING.txt");
-		if (contents.empty()) {
-			LOG_CS << "Could not find COPYING.txt, path is \""
-				<< game_config::path << "\"\n";
-			return;
-		}
-		config &copying = dir.add_child("file");
-		copying["name"] = "COPYING.txt";
-		copying["contents"] = contents;
-
-	}
-	/// @todo Check if this function has any purpose left
-	void campaign_server::convert_binary_to_gzip()
-	{
-		if (!cfg_["encoded"].to_bool())
-		{
-			// Convert all addons to gzip
-			config::const_child_itors camps = campaigns().child_range("campaign");
-			LOG_CS << "Encoding all stored addons. Number of addons: "
-				<< std::distance(camps.first, camps.second) << '\n';
-
-			foreach (const config &cm, camps)
-			{
-				LOG_CS << "Encoding " << cm["name"] << '\n';
-				std::string filename = cm["filename"], newfilename = filename + ".new";
-
-				{
-					scoped_istream in_file = istream_file(filename);
-					boost::iostreams::filtering_stream<boost::iostreams::input> in_filter;
-					in_filter.push(boost::iostreams::gzip_decompressor());
-					in_filter.push(*in_file);
-
-					scoped_ostream out_file = ostream_file(newfilename);
-					boost::iostreams::filtering_stream<boost::iostreams::output> out_filter;
-					out_filter.push(boost::iostreams::gzip_compressor(boost::iostreams::gzip_params(compress_level_)));
-					out_filter.push(*out_file);
-
-					unsigned char c = in_filter.get();
-					while( in_filter.good())
-					{
-						if (needs_escaping(c) && c != '\x01')
-						{
-							out_filter.put('\x01');
-						   	out_filter.put(c+1);
-						} else {
-							out_filter.put(c);
-						}
-						c = in_filter.get();
-					}
-				}
-
-				std::remove(filename.c_str());
-				std::rename(newfilename.c_str(), filename.c_str());
-			}
-
-			cfg_["encoded"] = true;
-		}
- 	}
-
-	void campaign_server::run()
-	{
- 		convert_binary_to_gzip();
-
- 		if (!cfg_["control_socket"].empty())
- 			input_ = new input_stream(cfg_["control_socket"]);
-		network::connection sock = 0;
-		for(int increment = 0; ; ++increment) {
-			try {
- 				std::string admin_cmd;
- 				if (input_ && input_->read_line(admin_cmd))
- 				{
- 					// process command
- 					if (admin_cmd == "shut_down")
- 					{
- 						break;
- 					}
- 				}
-			//write config to disk every ten minutes
-				if((increment%(60*10*50)) == 0) {
-					scoped_ostream cfgfile = ostream_file(file_);
-					write(*cfgfile, cfg_);
-				}
-
-				network::process_send_queue();
-
-				sock = network::accept_connection();
-				if(sock) {
-					LOG_CS << "received connection from " << network::ip_address(sock) << "\n";
-				}
-
-				config data;
-				while((sock = network::receive_data(data, 0)) != network::null_connection) {
-					if (const config &req = data.child("request_campaign_list"))
-					{
-						LOG_CS << "sending campaign list to " << network::ip_address(sock) << " using gzip";
-						time_t epoch = time(NULL);
-						config campaign_list;
-						campaign_list["timestamp"] = lexical_cast<std::string>(epoch);
-						if (req["times_relative_to"] != "now") {
-							epoch = 0;
-						}
-
-						bool before_flag = false;
-						time_t before = epoch;
-						try {
-							before = before + lexical_cast<time_t>(req["before"]);
-							before_flag = true;
-						} catch(bad_lexical_cast) {}
-
-						bool after_flag = false;
-						time_t after = epoch;
-						try {
-							after = after + lexical_cast<time_t>(req["after"]);
-							after_flag = true;
-						} catch(bad_lexical_cast) {}
-
-						std::string name = req["name"], lang = req["language"];
-						foreach (const config &i, campaigns().child_range("campaign"))
-						{
-							if (!name.empty() && name != i["name"]) continue;
-							std::string tm = i["timestamp"];
-							if (before_flag && (tm.empty() || lexical_cast_default<time_t>(tm, 0) >= before)) continue;
-							if (after_flag && (tm.empty() || lexical_cast_default<time_t>(tm, 0) <= after)) continue;
-							if (!lang.empty()) {
-								bool found = false;
-								foreach (const config &j, i.child_range("translation")) {
-									if (j["language"] == lang) {
-										found = true;
-										break;
-									}
-								}
-								if (!found) continue;
-							}
-							campaign_list.add_child("campaign", i);
-						}
-
-						foreach (config &j, campaign_list.child_range("campaign")) {
-							j["passphrase"] = t_string();
-							j["upload_ip"] = t_string();
-							j["email"] = t_string();
-						}
-
-						config response;
-						response.add_child("campaigns",campaign_list);
-						std::cerr << " size: " << (network::send_data(response, sock)/1024) << "KiB\n";
-					}
-					else if (const config &req = data.child("request_campaign"))
-					{
-						LOG_CS << "sending campaign '" << req["name"] << "' to " << network::ip_address(sock)  << " using gzip";
-						config &campaign = campaigns().find_child("campaign", "name", req["name"]);
-						if (!campaign) {
-							network::send_data(construct_error("Add-on '" + req["name"].str() + "'not found."), sock);
-						} else {
-							std::cerr << " size: " << (file_size(campaign["filename"])/1024) << "KiB\n";
-							network::send_file(campaign["filename"], sock);
-							int downloads = campaign["downloads"].to_int() + 1;
-							campaign["downloads"] = downloads;
-						}
-
-					}
-					else if (data.child("request_terms"))
-					{
-						LOG_CS << "sending terms " << network::ip_address(sock) << "\n";
-						network::send_data(construct_message("All add-ons uploaded to this server must be licensed under the terms of the GNU General Public License (GPL). By uploading content to this server, you certify that you have the right to place the content under the conditions of the GPL, and choose to do so."), sock);
-						LOG_CS << " Done\n";
-					}
-					else if (config &upload = data.child("upload"))
-					{
-						LOG_CS << "uploading campaign '" << upload["name"] << "' from " << network::ip_address(sock) << ".\n";
-						config &data = upload.child("data");
-						const std::string& name = upload["name"];
-						std::string lc_name(name.size(), ' ');
-						std::transform(name.begin(), name.end(), lc_name.begin(), tolower);
-						config *campaign = NULL;
-						foreach (config &c, campaigns().child_range("campaign")) {
-							if (utils::lowercase(c["name"]) == lc_name) {
-								campaign = &c;
-								break;
-							}
-						}
-						if (!data) {
-							LOG_CS << "Upload aborted - no add-on data.\n";
-							network::send_data(construct_error("Add-on rejected: No add-on data was supplied."), sock);
-						} else if (!addon_name_legal(upload["name"])) {
-							LOG_CS << "Upload aborted - invalid add-on name.\n";
-							network::send_data(construct_error("Add-on rejected: The name of the add-on is invalid."), sock);
-						} else if (is_text_markup_char(upload["name"].str()[0])) {
-							LOG_CS << "Upload aborted - add-on name starts with an illegal formatting character.\n";
-							network::send_data(construct_error("Add-on rejected: The name of the add-on starts with an illegal formatting character."), sock);
-						} else if (upload["title"].empty()) {
-							LOG_CS << "Upload aborted - no add-on title specified.\n";
-							network::send_data(construct_error("Add-on rejected: You did not specify the title of the add-on in the pbl file!"), sock);
-						} else if (is_text_markup_char(upload["title"].str()[0])) {
-							LOG_CS << "Upload aborted - add-on title starts with an illegal formatting character.\n";
-							network::send_data(construct_error("Add-on rejected: The title of the add-on starts with an illegal formatting character."), sock);
-						} else if (get_addon_type(upload["type"]) == ADDON_UNKNOWN) {
-							LOG_CS << "Upload aborted - unknown add-on type specified.\n";
-							network::send_data(construct_error("Add-on rejected: You did not specify a known type for the add-on in the pbl file! (See PblWML: wiki.wesnoth.org/PblWML)"), sock);
-						} else if (upload["author"].empty()) {
-							LOG_CS << "Upload aborted - no add-on author specified.\n";
-							network::send_data(construct_error("Add-on rejected: You did not specify the author(s) of the add-on in the pbl file!"), sock);
-						} else if (upload["version"].empty()) {
-							LOG_CS << "Upload aborted - no add-on version specified.\n";
-							network::send_data(construct_error("Add-on rejected: You did not specify the version of the add-on in the pbl file!"), sock);
-						} else if (upload["description"].empty()) {
-							LOG_CS << "Upload aborted - no add-on description specified.\n";
-							network::send_data(construct_error("Add-on rejected: You did not specify a description of the add-on in the pbl file!"), sock);
-						} else if (upload["email"].empty()) {
-							LOG_CS << "Upload aborted - no add-on email specified.\n";
-							network::send_data(construct_error("Add-on rejected: You did not specify your email address in the pbl file!"), sock);
-						} else if (!check_names_legal(data)) {
-							LOG_CS << "Upload aborted - invalid file names in add-on data.\n";
-							network::send_data(construct_error("Add-on rejected: The add-on contains an illegal file or directory name."
-									" File or directory names may not contain any of the following characters: '/ \\ : ~'"), sock);
-						} else if (campaign && (*campaign)["passphrase"].str() != upload["passphrase"]) {
-							LOG_CS << "Upload aborted - incorrect passphrase.\n";
-							network::send_data(construct_error("Add-on rejected: The add-on already exists, and your passphrase was incorrect."), sock);
-						} else {
-							LOG_CS << "Upload is owner upload.\n";
-							std::string message = "Add-on accepted.";
-
-							if (!version_info(upload["version"]).good()) {
-								message += "\n<255,255,0>Note: The version you specified is invalid. This add-on will be ignored for automatic update checks.";
-							}
-
-							if(campaign == NULL) {
-								campaign = &campaigns().add_child("campaign");
-							}
-
-							(*campaign)["title"] = upload["title"];
-							(*campaign)["name"] = upload["name"];
-							(*campaign)["filename"] = "data/" + upload["name"].str();
-							(*campaign)["passphrase"] = upload["passphrase"];
-							(*campaign)["author"] = upload["author"];
-							(*campaign)["description"] = upload["description"];
-							(*campaign)["version"] = upload["version"];
-							(*campaign)["icon"] = upload["icon"];
-							(*campaign)["translate"] = upload["translate"];
-							(*campaign)["dependencies"] = upload["dependencies"];
-							(*campaign)["upload_ip"] = network::ip_address(sock);
-							(*campaign)["type"] = upload["type"];
-							(*campaign)["email"] = upload["email"];
-
-							if((*campaign)["downloads"].empty()) {
-								(*campaign)["downloads"] = 0;
-							}
-							(*campaign)["timestamp"] = lexical_cast<std::string>(time(NULL));
-
-							int uploads = (*campaign)["uploads"].to_int() + 1;
-							(*campaign)["uploads"] = uploads;
-
-							std::string filename = (*campaign)["filename"];
-							data["title"] = (*campaign)["title"];
-							data["name"] = "";
-							data["campaign_name"] = (*campaign)["name"];
-							data["author"] = (*campaign)["author"];
-							data["description"] = (*campaign)["description"];
-							data["version"] = (*campaign)["version"];
-							data["timestamp"] = (*campaign)["timestamp"];
-							data["icon"] = (*campaign)["icon"];
-							data["type"] = (*campaign)["type"];
-							(*campaign).clear_children("translation");
-							find_translations(data, *campaign);
-
-							add_license(data);
-
-							{
-								scoped_ostream campaign_file = ostream_file(filename);
-								config_writer writer(*campaign_file, true, compress_level_);
-								writer.write(data);
-							}
-//							write_compressed(*campaign_file, *data);
-
-							(*campaign)["size"] = lexical_cast<std::string>(
-									file_size(filename));
-							scoped_ostream cfgfile = ostream_file(file_);
-							write(*cfgfile, cfg_);
-							network::send_data(construct_message(message), sock);
-
-							fire("hook_post_upload", upload["name"]);
-						}
-					}
-					else if (const config &erase = data.child("delete"))
-					{
-						LOG_CS << "deleting campaign '" << erase["name"] << "' requested from " << network::ip_address(sock) << "\n";
-						const config &campaign = campaigns().find_child("campaign", "name", erase["name"]);
-						if (!campaign) {
-							network::send_data(construct_error("The add-on does not exist."), sock);
-							continue;
-						}
-
-						if (campaign["passphrase"] != erase["passphrase"]
-								&& (campaigns()["master_password"].empty()
-								|| campaigns()["master_password"] != erase["passphrase"]))
-						{
-							network::send_data(construct_error("The passphrase is incorrect."), sock);
-							continue;
-						}
-
-						//erase the campaign
-						write_file(campaign["filename"], std::string());
-						remove(campaign["filename"].str().c_str());
-
-						config::child_itors itors = campaigns().child_range("campaign");
-						for (size_t index = 0; itors.first != itors.second;
-						     ++index, ++itors.first)
-						{
-							if (&campaign == &*itors.first) {
-								campaigns().remove_child("campaign", index);
-								break;
-							}
-						}
-						scoped_ostream cfgfile = ostream_file(file_);
-						write(*cfgfile, cfg_);
-						network::send_data(construct_message("Add-on deleted."), sock);
-
-						fire("hook_post_erase", erase["name"]);
-					}
-					else if (const config &cpass = data.child("change_passphrase"))
-					{
-						config &campaign = campaigns().find_child("campaign", "name", cpass["name"]);
-						if (!campaign) {
-							network::send_data(construct_error("No add-on with that name exists."), sock);
-						} else if (campaign["passphrase"] != cpass["passphrase"]) {
-							network::send_data(construct_error("Your old passphrase was incorrect."), sock);
-						} else if (cpass["new_passphrase"].empty()) {
-							network::send_data(construct_error("No new passphrase was supplied."), sock);
-						} else {
-							campaign["passphrase"] = cpass["new_passphrase"];
-							scoped_ostream cfgfile = ostream_file(file_);
-							write(*cfgfile, cfg_);
-							network::send_data(construct_message("Passphrase changed."), sock);
-						}
-					}
-				}
-			} catch(network::error& e) {
-				if(!e.socket) {
-					LOG_CS << "fatal network error: " << e.message << "\n";
-					throw;
-				} else {
-					LOG_CS << "client disconnect: " << e.message << " " << network::ip_address(e.socket) << "\n";
-					e.disconnect();
-				}
-			} catch(config::error& /*e*/) {
-				LOG_CS << "error in receiving data...\n";
-				network::disconnect(sock);
-			}
-
-			SDL_Delay(20);
-		}
-	}
-
-}
-
-int main(int argc, char**argv)
-{
-	game_config::path = get_cwd();
-	lg::timestamps(true);
-	try {
-		printf("argc %d argv[0] %s 1 %s\n",argc,argv[0],argv[1]);
-		std::string cfg_path = normalize_path("server.cfg");
-		if(argc >= 2 && atoi(argv[1])){
-			campaign_server(cfg_path, atoi(argv[1])).run();
-		}else {
-			campaign_server(cfg_path).run();
-		}
-	} catch(config::error& /*e*/) {
-		std::cerr << "Could not parse config file\n";
-		return 1;
-	} catch(io_exception& /*e*/) {
-		std::cerr << "File I/O error\n";
-		return 2;
-	} catch(network::error& e) {
-		std::cerr << "Aborted with network error: " << e.message << '\n';
-		return 3;
-	}
-	return 0;
-}
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt	(revision 54177)
+++ src/CMakeLists.txt	(working copy)
@@ -789,6 +789,8 @@
 	network_worker.cpp # NEEDED when compiling with ANA support
 	addon/validation.cpp
 	campaign_server/campaign_server.cpp
+  campaign_server/server_options.cpp
+  campaign_server/server.cpp
 	server/input_stream.cpp
 	${network_implementation_files}
 	loadscreen_empty.cpp
@@ -798,7 +800,9 @@
 target_link_libraries(campaignd
 	wesnoth-core
 	${server-external-libs}
-	${SDLNET_LIBRARY} 				# NEEDED with ANA
+  ${Boost_THREAD_LIBRARY}
+  ${Boost_SYSTEM_LIBRARY}
+#	${SDLNET_LIBRARY} 				# NEEDED with ANA
 	${LIBINTL_LIBRARIES}
 	)
 set_target_properties(campaignd PROPERTIES OUTPUT_NAME ${BINARY_PREFIX}campaignd${BINARY_SUFFIX})
Index: doc/design/umcd.tex
===================================================================
--- doc/design/umcd.tex	(revision 54177)
+++ doc/design/umcd.tex	(working copy)
@@ -10,7 +10,14 @@
 \usepackage{cleveref}
 \usepackage{listings}
 
-\author{M.~de Wever}
+\lstset{
+  tabsize=2
+}
+
+\author{
+  Mark \textsc{de Wever} 
+  \and 
+  Pierre \textsc{Talbot}}
 \title{UMCD design document - DRAFT}
 
 \begin{document}
@@ -23,16 +30,10 @@
 
 \include{umcd/introduction}
 \include{umcd/communication_protocol}
+\include{umcd/uml_design}
 
-%\include{gui2/introduction}
-%\include{gui2/overall_design}
-%\include{gui2/design_details}
-%\include{gui2/creating_widgets_and_dialogs}
-
 \appendix
 
-%\include{gui2/files_for_the_widget}
-%\include{gui2/files_for_the_window}
 
 \end{document}
 
Index: doc/design/umcd/introduction.tex
===================================================================
--- doc/design/umcd/introduction.tex	(revision 54177)
+++ doc/design/umcd/introduction.tex	(working copy)
@@ -9,7 +9,6 @@
 \begin{description}
 \item[Dependency tracking]
 	
-
 \item[Translated messages]
 
 \item[Wescamp intergration]
Index: doc/design/umcd/communication_protocol.tex
===================================================================
--- doc/design/umcd/communication_protocol.tex	(revision 54177)
+++ doc/design/umcd/communication_protocol.tex	(working copy)
@@ -1,7 +1,27 @@
 \chapter{Communication protocol}
 \label{chapter:communication_protocol}
 
+\section{Document Convention}
 
+The following tokens will be used to further describe an item.
+
+\begin{description}
+\item[?]
+  The current item is optional (request) or should not appear every time under specified conditions (reply).
+\item[*]
+  The current item appears 0, 1 or multiple times.
+\item[+]
+  The current item appears 1 or multiple times.
+\end{description}
+The description of an item can take different formats:
+\begin{description}
+  \item[\textless{}value\textgreater{}]
+    A text between ``\textless{}\textgreater{}'' is replaced with the appropriate value in the current context.
+  \item[\{value\}]
+    A text between  ``\{\}'' is optional.
+\end{description}
+
+
 \section{Server configuration}
 \label{section:communication_protocol:server}
 
@@ -9,7 +29,7 @@
 \begin{itemize}
 \item
 	The main configuration file, umcd.cfg, this file is stored in the
-	data directory, which is a parameter for the programme. This file is
+	data directory, which is a parameter for the program. This file is
 	further discussed in \cref{section:communication_protocol:server:umcd.cfg}.
 
 \item
@@ -17,41 +37,40 @@
 	directories have the following files:
 	\begin{description}
 	\item[umc.cfg]
-		The config file for the umc, this file is based on the client's
+		The config file for the UMC, this file is based on the client's
 		pbl file. This file is further discussed in
 		\cref{section:communication_protocol:server:umc.cfg}.
 
 	\item[umc.gz]
-		The gzipped umc.
+		The gzipped UMC.
 
 	\item[umc-\emph{lang}.cfg]
-		The configuration file for the translation of the umc. The
+		The configuration file for the translation of the UMC. The
 		\emph{lang} is replace with the locale of the translation.
 		This file is further discussed in
 		\cref{section:communication_protocol:server:umc-lang.cfg}.
 
 	\item[umc-\emph{lang}.gz]
-		The gzipped mo-file for the translation. Note if the
-		compression-ratio for the mo-file is bad, the raw mo-file will be
-		stored instead. The final decision in the matter will be specified
-		later.
+		The gzipped mo-file for the translation.
 
 	\end{description}
 
 \end{itemize}
 
+\subsection{Compressed files}
 
+If the compression ratio is bad, the file could not be zipped. But, to facilitate
+sending data over the network, the files sent will be gather into a tarball (.tar).
+
 \subsection{umcd.cfg}
 \label{section:communication_protocol:server:umcd.cfg}
 
-This file contains the settings of the umcd.
+This file contains the settings of the UMCD.
 
 \begin{lstlisting}
-[umcd_configuration]
-	port = PORT
-	threads = THREADS
-
-[/umcd_configurattion]
+port = PORT
+threads = THREADS
+dir = DIR
 \end{lstlisting}
 
 The keys have the following meaning:
@@ -60,12 +79,15 @@
 	The TCP/IP port to listen to for incoming requests.
 
 \item[THREADS]
-	The number of listeners threads to start. A value of $0$ means start as
-	many threads as there are detected hardware cores\footnote{Whether
-	hyper-threading and Co. count as separate cores is unspecified.}.
+	The number of working threads to start. A value of $0$ means start as
+	many threads as there are detected hardware cores or hyperthreading units
+\footnote{as specified by \textbf{boost::thread::hardware\_concurrency()}}.
 
+\item[DIR]
+  The directory where the add-ons will be stored.
 \end{description}
 
+The values are not encapsulated into a global markup because we parse the options with \textit{Boost.Program\_options}.
 
 \subsection{umc.cfg}
 \label{section:communication_protocol:server:umc.cfg}
@@ -80,46 +102,52 @@
 The file is specified like:
 \begin{lstlisting}
 [umc]
-	id = ID
-	name = NAME
-	icon = ICON
-	type = TYPE
-	description = DESCRIPTION
-	version = VERSION
-	size = SIZE
-	authors = AUTHORS
-	email = EMAIL
-	uploader_ip_address = UPLOADER_IP_ADDRESS
-	timestamp = TIMESTAMP
-	downloads = DOWNLOADS
-	uploads = UPLOADS
-	password = PASSWORD
-	language = LANGUAGE
-	translatable = TRANSLATABLE
+  [info]
+    id = ID
+    name = NAME
+    description = DESCRIPTION
+    type = TYPE
+    version = VERSION
+    authors = AUTHORS
+    email = EMAIL
+    password = PASSWORD
+  [/info]
+  [language]
+    native_language = NATIVE_LANGUAGE
+    translatable = TRANSLATABLE
+  [/language]
 	[dependencies]?
 		[dependency]+
 			id = ID
 			version? = VERSION_MASK
 		[/dependency]
 	[/dependencies]
+  [state]
+    uploader_ip_address = UPLOADER_IP_ADDRESS
+    timestamp = TIMESTAMP
+    downloads = DOWNLOADS
+    uploads = UPLOADS
+  [/state]
 [/umc]
 \end{lstlisting}
 
 The keys have the following meaning:
 \begin{description}
+
+\item [[info]] The main informations provided by the UMC-creator.
+
+\begin{description}
 \item[ID]
 	The unique id of the content. When uploading this value determines
-	whether an umc is the same umc.
+	whether an UMC is the same UMC.
 
 \item[NAME]
-	The name of the content. This string is not unique. This allows two
-	versions of the UMC on the server. This can be used to allow a new beta
-	next to a stable, as long as the ID differs.
+  The name of the content. This string is not unique. This allows two
+  versions of the UMC on the server. This can be used to allow a new beta
+  next to a stable, as long as the ID differs.
 
-\item[ICON]
-	The icon of the umc, which is shown in the addon-list on the server.
-	TODO it is not yet specified how the icon is transferred to and from the
-	client.
+\item[DESCRIPTION]
+  The description of the UMC.
 
 \item[TYPE]
 	The type of the addon. At the moment the following values are allowed:
@@ -140,18 +168,13 @@
 	\item[OTHER] Everything that doesn't fit in one of the above.
 	\end{description}
 
-\item[DESCRIPTION]
-	The description of the umc.
-
 \item[VERSION]
-	A string determining the version. The string should formatted like:
-	`x.y.z' or `x.y.z-q'. When doing so the version can be parsed as version
-	number. The `-q' part is sorted alphabetically and is an empty string if
-	omitted, thus sorted first.
+	A string determining the version. The recommended string format like:
+	`x.y.z' or `x.y.z-q'. The version is parsed as version number and 
+comparisons are done considering all the number and letter
+$a < z < A < Z < 0 < 9 < Empty$, all other characters are parsed as separator.
+For example, ``aZ=4'' is lower than ``aZ'', and ``='' is the separator character.
 
-\item[SIZE]
-	The size of the umc in bytes packed on the server.
-
 \item[AUTHORS]
 	A colon separated list of authors of the umc. When there is only one
 	author no colon is required.
@@ -162,37 +185,28 @@
 	the authors, so make sure it's valid and doesn't need registration.
 	The address is not used in other ways nor shared with third-parties.
 
-\item[UPLOADER\_IP\_ADDRESS]
-	The ip address of the last uploader of the umc.
+\item[PASSWORD]
+	The password required to upload a new version of an UMC or remove an UMC
+	from the server. See also \cref{section:security:passwordstorage} and \cref{section:security:passwordtransmission}.
 
-\item[TIMESTAMP]
-	The timestamp of the last upload. 
+\end{description}
 
-\item[DOWNLOADS]
-	The number of times the UMC is downloaded.
+\item [[language]] The items related to the language files of the UMC.
 
-\item[UPLOADS]
-	The number of time a new version of the UMC is uploaded.
+\begin{description}
 
-\item[PASSWORD]
-	The password required to upload a new version of an umc or remove an umc
-	from the server.
+\item[NATIVE\_LANGUAGE]
+	The native language id of the UMC, and the language in which are the name and the description.
 
-\item[LANGUAGE]
-	The language id of the umc. If omitted American English is assumed.
-	This allows umc authors who are not able to create content in English to
-	still create content. However it's still recommended to try to write the
-	content in American English. (TODO determine whether omitted on the
-	server or only during the initial upload, if the latter the server
-	should set it if omitted during the upload.)
-
 \item[TRANSLATABLE]
-	This flag causes the umc to be synchronised with Wescamp. It's advisable
+	This flag causes the UMC to be synchronized with Wescamp. It's advisable
 	to only set the flags when the strings are somewhat stable. This flag
-	can only be set if the language is American English.
+	can only be set if American English is available.
 \end{description}
 
-The [dependencies] lists the dependencies of the UMC. This allows the client
+
+\item[[dependencies]]
+Lists the dependencies of the UMC. This allows the client
 to download all UMC required to use this UMC. The fields mean:
 \begin{description}
 \item[ID]
@@ -226,29 +240,87 @@
 
 \end{description}
 
+\item [[state]] These fields are auto-generated by the server. It's the current state of the UMC.
 
+\begin{description}
+\item[UPLOADER\_IP\_ADDRESS]
+  The ip address of the last uploader of the umc.
+
+\item[TIMESTAMP]
+  The timestamp of the last upload. 
+
+\item[DOWNLOADS]
+  The number of times the UMC is downloaded.
+
+\item[UPLOADS]
+  The number of time a new version of the UMC is uploaded.
+
+\end{description}
+\end{description}
+
+
 \subsection{umc-\emph{lang}.cfg}
 \label{section:communication_protocol:server:umc-lang.cfg}.
 
-The configuration file for the translation of the umc. The
+The configuration file for the translation of the UMC. The
 \emph{lang} is replace with the locale of the translation.
 
 \begin{lstlisting}
 	[language]
-		id = LANGUAGE
-		timestamp = TIMESTAMP
-		translated = TRANSLATED
-		fuzzy = FUZZY
-		untranslated = UNTRANSLATED
-		[translated_umc_strings]
-			name = NAME
-			description = DESCRIPTION
-		[/translated_umc_strings]
+    id = LANGUAGE
+    [translated_umc_strings]
+      name = NAME
+      description = DESCRIPTION
+    [/translated_umc_strings]
+    [po_file_details]
+      size = SIZE
+      timestamp = TIMESTAMP
+      translated = TRANSLATED
+      fuzzy = FUZZY
+      untranslated = UNTRANSLATED
+    [/po_file_details]
 	[/language]
 \end{lstlisting}
 
+\begin{description}
+\item[ID]
+  The id of the language the translation for.
 
+\item[[translated\_umc\_strings]]
 
+  The translation of the name and description, in the language specified by ``ID''.
+
+\begin{description}
+
+\item[NAME]
+  See \cref{section:communication_protocol:server:umc.cfg}
+
+\item[DESCRIPTION]
+  See \cref{section:communication_protocol:server:umc.cfg}
+
+\end{description}
+
+\item [[po\_file\_details]]
+\begin{description}
+\item[SIZE]
+  The size of the po-file.
+
+\item[TIMESTAMP]
+  The timestamp the po-file was last updated.
+
+\item[TRANSLATED]
+  The number of translated strings. Must be \textgreater 0.
+
+\item[FUZZY]
+  The number of strings that are fuzzy.
+  
+\item[UNTRANSLATED]
+  The number of strings that are not translated.
+
+\end{description}
+\end{description}
+
+
 \section{UMC configuration}
 \label{section:communication_protocol:umc}
 
@@ -257,262 +329,548 @@
 contains the following data:
 
 \begin{lstlisting}
-[umc_configuraton]
-	id = ID
-	name = NAME
-	icon = ICON
-	type = TYPE
-	description = DESCRIPTION
-	version = VERSION
-	authors = AUTHORS
-	email = EMAIL
-	password? = PASSWORD
-	language? = LANGUAGE
-	translatable = TRANSLATABLE
-	[dependencies]?
-		[dependency]+
-			id = ID
-			version? = VERSION_MASK
-		[/dependency]
-	[/dependencies]
-[/umc_configration]
+[umc_configuration]
+  [info]
+    id = ID
+    name = NAME
+    type = TYPE
+    description = DESCRIPTION
+    version = VERSION
+    authors = AUTHORS
+    email = EMAIL
+    password = PASSWORD
+  [/info]
+  [language]
+    native_language = NATIVE_LANGUAGE
+    translatable = TRANSLATABLE
+  [/language]
+  [dependencies]?
+    [dependency]+
+      id = ID
+      version? = VERSION_MASK
+    [/dependency]
+  [/dependencies]
+  [image]
+    icon_name = ICON_NAME
+  [/image]
+[/umc_configuration]
 \end{lstlisting}
 
 The keys have the following meaning:
 \begin{description}
-\item[ID]
+\item[[info]]
 	See \cref{section:communication_protocol:server:umc.cfg}.
 
-\item[NAME]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\item[[language]]
+  See \cref{section:communication_protocol:server:umc.cfg}.
 
-\item[ICON]
+\item[[dependencies]]
 	See \cref{section:communication_protocol:server:umc.cfg}.
 
-\item[TYPE]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\item[[image]]
+\begin{description}
+ \item ICON\_NAME The name of the icon that will be displayed in the umc list.
+\end{description}
 
-\item[DESCRIPTION]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\end{description}
 
-\item[VERSION]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\section{Wire}
+\label{section:communication_protocol:wire}
 
-\item[AUTHORS]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\subsection{Design rational}
 
-\item[EMAIL]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\begin{itemize}
+ \item The ID is a technical ID and not the couple campaign name + version which is unique too. So we can change the campaign name without breaking dependencies.
 
-\item[PASSWORD]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\end{itemize}
 
-	It may be omitted, during the initial upload. In that case the first
-	upload results in sending back the password. It's stored in the pbl-file
-	and the author doesn't need to remember it.
 
-\item[LANGUAGE]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\subsection{Special packets}
+\label{wire:specialpackets}
 
-\item[TRANSLATABLE]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+Special packets are sent in reply and can appears instead an expected tag or in addition of this tag.
 
+\subsubsection{Error packet}
+\label{wire:specialpackets:errorpacket}
+
+ The server could not understand the request, or a value in a field of the request is wrong.
+In this case an error packet will be sent and it will always take the following form:
+\begin{lstlisting}
+[error_packet]
+  msg = MSG
+[/error_packet]
+\end{lstlisting}
+
+\begin{description}
+ \item MSG Contains a message describing the error.
 \end{description}
 
-\section{Wire}
-\label{section:communication_protocol:wire}
+The common values of MSG are:
 
-\section{Request campaign list}
+\begin{enumerate}
+ \item The value $<$value$>$ of the field $<$field\_name$>$ is wrong \{because $<$reason$>$\}.
+ \item The field $<$field\_name$>$ is unknown.
+\end{enumerate}
+
+\subsubsection{Warning packet}
+\label{wire:specialpackets:warningpacket}
+
+The server correctly understand the request but the request is not exactly correct for the reasons describe into \textit{msg}.
+\begin{lstlisting}
+[warning_packet]
+  msg = MSG
+[/warning_packet]
+\end{lstlisting}
+
+\begin{description}
+ \item MSG Contains a message describing the warning.
+\end{description}
+
+\subsection{Request campaign list}
 \label{wire:request_campaign_list}
 
-Request:
+\subsubsection{Request}
 \begin{lstlisting}
 	[request_umc_list]
-	[/requst_umc_list]
+    favlang = LANGUAGE
+	[/request_umc_list]
 \end{lstlisting}
 
-Replay:
+The field \textit{favlang} is the favorite language in which the add-ons (title and description for example) must be send. 
+If the content is not fully (or not at all) translated,  the UMC description is downloaded in its native language, 
+and the rest is left to the engine \textit{gettext}.
+\newline
+\subsubsection{Reply}
+
+An error packet can be sent instead of the umc list packet. No special value appears in this packet. See \cref{wire:specialpackets:errorpacket}.
+If the list is empty, no error packet is sent, the list will just appears with no [umc] tag.
+
 \begin{lstlisting}
 	[umc_list]
 		[umc]*
-			id = ID
-			name = NAME
-			type = TYPE
-			description = DESCRIPTION
-			version = VERSION
-			size = SIZE
-			authors = AUTHORS
-			timestamp = TIMESTAMP
-			downloads = DOWNLOADS
-			uploads = UPLOADS
-			language = LANGUAGE
-			[dependencies]?
-				[dependency]+
-					id = ID
-					version? = VERSION_MASK
-				[/dependency]
-			[/dependencies]
-			[languages]?
-				[language]+
-					id = LANGUAGE
-					timestamp = TIMESTAMP
-					translated = TRANSLATED
-					fuzzy = FUZZY
-					untranslated = UNTRANSLATED
-					[translated_umc_strings]
-						name = NAME
-						description = DESCRIPTION
-					[/translated_umc_strings]
-				[/language]
-			[/languages]
+      [info]
+        id = ID
+        type = TYPE
+        version = VERSION
+        size = SIZE
+        authors = AUTHORS
+      [/info]
+      [icon]
+        size = SIZE
+        extension = EXTENSION
+      [/icon]
+      [state]
+        timestamp = TIMESTAMP
+        downloads = DOWNLOADS
+        uploads = UPLOADS
+      [/state]
+      [dependencies]?
+        [dependency]+
+          id = ID
+          version? = VERSION_MASK
+        [/dependency]
+      [/dependencies]
+      [languages]
+        [language] +
+          id = LANGUAGE
+          [translated_umc_strings]
+            name = NAME
+            description = DESCRIPTION
+          [/translated_umc_strings]
+          [po_file_details]
+            size = SIZE
+            timestamp = TIMESTAMP
+            translated = TRANSLATED
+            fuzzy = FUZZY
+            untranslated = UNTRANSLATED
+          [/po_file_details]
+        [/language]
+      [/languages]
 		[/umc]
 	[/umc_list]
 \end{lstlisting}
 
 The fields in [umc] have the following meaning:
 \begin{description}
-\item[ID]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\item[[info]]
+  See \cref{section:communication_protocol:server:umc.cfg}
 
-\item[NAME]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\begin{description}
+ \item SIZE The size of the UMC without translation files (.po).
+\end{description}
 
-	The version in [language] is the translated name of the UMC.
+\item[[icon]]
 
-\item[TYPE]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\begin{description}
+ \item SIZE The size of the icon.
+ \item EXTENSION The extension of the file, or in other word, the file format.
+\end{description}
 
-\item[DESCRIPTION]
-	See \cref{section:communication_protocol:server:umc.cfg}.
 
-\item[VERSION]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\item[[state]]
+  See \cref{section:communication_protocol:server:umc.cfg}.
 
-\item[SIZE]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+\item[[dependencies]] 
+  Lists the dependencies of the UMC, See \cref{section:communication_protocol:server:umc.cfg}.
 
-\item[TIMESTAMP]
-	The timestamp of the last upload. For the [umcs] it is the upload
-	of the umc, for the [language] it is the last upload of the
-	po-file. (NOTE MERGE WITH MASTER LIST.)
+\item[[languages]]
+  Contains the description of the add-on in the favorite language requested.
 
-\item[DOWNLOADS]
-	See \cref{section:communication_protocol:server:umc.cfg}.
+If the translation into the favorite language is not available or incomplete, American English is sent.
+If American English is not available or complete, the language depends on the native language of this UMC. 
+We let the engine \textit{gettext} merge the different file considering this order of preference: $favorite >
+American English > native$. So, maximum 3 languages are sent.
 
-\item[UPLOADS]
-	See \cref{section:communication_protocol:server:umc.cfg}.
-
-\item[LANGUAGE]
-	The id of a language locale. The one in [umc] is the language of
-	the UMC. If this language is empty American English is assumed. The UMC
-	is only translatable if this is set to American English (this should be
-	mentioned in the PBL section).
-\end{description}
-
-
-The [dependencies] lists the dependencies of the UMC, See
-\cref{section:communication_protocol:server:umc.cfg}.
-
-The [languages] contains the list of languages the addon is (partly)
-translated to. The fields mean:
 \begin{description}
-\item[ID]
-	The id of the language the translation for.
-
-\item[TIMESTAMP]
-	The timestamp the po-file was last updated. NOTE UNIX stamp, should be
-	at other stamp as well.
-
-\item[TRANSLATED]
-	The number of translated strings, if this entry is $0$, then the entire
-	section is not printed.
-
-\item[FUZZY]
-	The number of strings that are fuzzy.
-	
-\item[UNTRANSLATED]
-	The number of strings that are not translated.
-
-NOTE MAYBE ALSO ADD UP AND DOWNLOAD COUNTER and obviously the SIZE
+\item [[language]] See \cref{section:communication_protocol:server:umc-lang.cfg}.
 \end{description}
+\end{description}
+The icons are sent in the order of appearance in the [umc\_list] packet, the size of the icon is specified in the [icon] tag.
 
-The section [translated\_umc\_strings] duplicates some strings from the
-general [umc] section. This version contains the translated string from
-the po file. If not translated or fuzzy it contains the original, just like
-normal with gettext. The keys in this section corrospondent with the ones in
-[campaign].
-
-\section{Request umc download}
+\subsection{Request umc download}
 \label{wire:request_umc_download}
 
-This requests to download an umc.
+This requests to download an UMC.
 
-Request:
+\subsubsection{Request}
 \begin{lstlisting}
 	[request_umc_download]
 		id = ID
-		[languages]?
-			[language]*
-				ID = LANGUAGE
-			[/language]
-		[/languages]
-	[/requst_umc_download]
+		language = LANGUAGE
+	[/request_umc_download]
 \end{lstlisting}
 
-The fields are:
 \begin{description}
 \item[ID]
-	The id of the umc to download.
+	The id of the UMC to download.
 
 \item[LANGUAGE]
 	The id of the requested language to download.
 
 \end{description}
 
-Replay:
+\subsubsection{Reply}
+
+An error packet can be sent instead for the common reasons. See \cref{wire:specialpackets:errorpacket}.
+
 \begin{lstlisting}
+  [warning_packet]?
+    msg = MSG
+  [/warning_packet]
 	[umc_download]
 		id = ID
-		status = STATUS
-		[languages]?
+    size = SIZE
+		[languages]
 			[language]+
 				id = LANGUAGE
-				status = STATUS
+        size = SIZE
 			[/language]
 		[/languages]
 	[/umc_download]
 \end{lstlisting}
 
-This is a mirror of the request, only all items have a status field. The
-status can be OK it the file exists and can be downloaded. Or ERROR if not
-possible.
+\begin{description}
+ \item [[warning\_packet]]
+    The warning packet can be sent with the following possible values:
+    \begin{enumerate}
+      \item The language requested is incomplete.
+      \item The language requested is not available.
+    \end{enumerate}
+    See also \cref{wire:specialpackets:warningpacket}.
+  \item[[umc\_download]]
+  \begin{description}
+    \item [ID] The id of the UMC.
+    \item [SIZE] The size of the UMC without translation files (.po).
+    \item [[language]]
+    \begin{description}
+      \item ID The id of the language.
+      \item SIZE The size of the translation file (.po).
+    \end{description}
+  \end{description}
+\end{description}
 
-The files send are in the order of appearance in the request and reply. The
-files are named:
+
+The files send are in the order of appearance in the reply, so first the ID.gz and then
+the ID-LANGUAGE.gz.
 \begin{description}
 \item[ID.gz]
 	The gzipped campaign files. The file is packed in a single config file
 	to be extracted to the local file-system.
 
 \item[ID-LANGUAGE.gz]
-	A gzipped mo-file for a language. If gzip's compression ratio for mo
-	files is too small the mo-file will be send directly.
+	A gzipped mo-file for a language.
 
 \end{description}
 
 
-\section{Request umc change password}
+\subsection{Request UMC change password}
 \label{wire:request_umc_change_password}
 
 This request changes the password.
 
+\subsubsection{Request}
+\begin{lstlisting}
+  [request_change_password]
+    id = ID
+    current_password = CURRENT_PASSWORD
+    new_password = NEW_PASSWORD
+  [/request_change_password]
+\end{lstlisting}
 
-\section{Request umc upload}
+\begin{description}
+\item[ID]
+  The id of the UMC to change the password.
+
+\item[CURRENT\_PASSWORD]
+  The current password of the UMC.
+
+\item[NEW\_PASSWORD]
+  The new password of the UMC.
+\end{description}
+
+\subsubsection{Reply}
+\begin{lstlisting}
+  [umc_change_password]
+    id = ID
+    [error_packet] ?
+      msg = MSG
+    [/error_packet]
+    [warning_packet] ?
+      msg = MSG
+    [/warning_packet]
+  [/umc_change_password]
+\end{lstlisting}
+
+\begin{description}
+\item[id]
+  The id of the UMC to change the password.
+
+\item[[error\_packet]]
+  If this packet appears, then the password could not been changed for the reasons described into this packet.
+  The possible special reasons are:
+  \begin{enumerate}
+    \item The current password is wrong.
+    \item The time between two requests is not respected.
+    \item The new password is too weak.
+  \end{enumerate}
+  See also \cref{wire:specialpackets:errorpacket} for a description.
+
+\item[[warning\_packet]]
+  If this packet appears, the password has been changed but a warning is sent to the user. The warning can take these values:
+  \begin{enumerate}
+    \item The password is weak, you should use a stronger password.
+  \end{enumerate}
+  See also \cref{wire:specialpackets:warningpacket}.
+\end{description}
+If only the ID appears in the packet, the password has been successfully changed.
+
+\subsection{Request a new password}
+\label{wire:request_new_password}
+
+\subsubsection{Request}
+Request a new password because the user forgot it. A new auto-generated password is sent by email.
+\begin{lstlisting}
+  [umc_forgot_password]
+    id = ID
+  [/umc_forgot_password]
+\end{lstlisting}
+\begin{description}
+ \item [ID] The ID of the UMC that the password has been forgotten.
+\end{description}
+
+\subsubsection{Reply}
+
+The reply can be an error packet for the common reasons. See \cref{wire:specialpackets:errorpacket}.
+
+\begin{lstlisting}
+  [umc_forgot_password]
+    id = ID
+    mail = MAIL
+  [/umc_forgot_password]
+\end{lstlisting}
+\begin{description}
+  \item [ID] The ID of the UMC that the password has been forgotten.
+  \item [MAIL] The address mail where the password has been sent.
+\end{description}
+
+\subsection{Request umc upload}
 \label{wire:request_umc_upload}
 
+Request an upload of a new or an updated version of a UMC.
+A new version have no ID in the .pbl file while an updated version have an ID.
 
-\section{Request umc delete}
+\subsubsection{Request}
+\begin{lstlisting}
+[request_umc_upload] 
+  size = SIZE
+  format = FORMAT
+[/request_umc_upload]
+\end{lstlisting}
+\begin{description}
+  \item [SIZE] The size the complete UMC that is sent next.
+  \item [FORMAT] The format of the UMC, this field can take these values: GZ, TAR, ZIP, ...
+All the files must be grouped, if the compression ratio is bad, then the .tar extension is, at least, required (namely a tarball).
+\end{description}
+
+The server will decompressed or unpack this file and will look recursively into the repository to check
+if all the required files are present in respect of the pattern described in their respective section.
+
+The pack must contains, at least:
+
+\begin{enumerate}
+  \item A .pbl file.
+\end{enumerate}
+
+But can also contains:
+
+\begin{enumerate}
+ \item An icon file, the name of the icon file is specified in the .pbl file, so the server will look recursively into the archive.
+\end{enumerate}
+
+
+\subsubsection{Reply}
+
+An error packet can be sent for the common reasons, see \cref{wire:specialpackets:errorpacket}.
+But also for specific reasons:
+
+\begin{enumerate}
+  \item The translatable flag in the .pbl has been set, but no American English translation can be found.
+  \item The file $<$file\_type$>$ is malformed: $<$reason$>$.
+  \item A conflict has been detected: $<$reason$>$.
+  \item Wrong password.
+\end{enumerate}
+
+If no error packet appears, in case of a new version, the ID field in the .pbl is add and
+the following response is sent:
+
+\begin{lstlisting}
+[request_umc_upload]
+  [umc]
+    [info]
+      id = ID
+      type = TYPE
+      version = VERSION
+      size = SIZE
+      authors = AUTHORS
+    [/info]
+    [icon]
+      size = SIZE
+      extension = EXTENSION
+    [/icon]
+    [state]
+      timestamp = TIMESTAMP
+      downloads = DOWNLOADS
+      uploads = UPLOADS
+    [/state]
+    [dependencies]?
+      [dependency]+
+        id = ID
+        version? = VERSION_MASK
+      [/dependency]
+    [/dependencies]
+    [languages]
+      [language] +
+        id = LANGUAGE
+        [translated_umc_strings]
+          name = NAME
+          description = DESCRIPTION
+        [/translated_umc_strings]
+        [po_file_details]
+          size = SIZE
+          timestamp = TIMESTAMP
+          translated = TRANSLATED
+          fuzzy = FUZZY
+          untranslated = UNTRANSLATED
+        [/po_file_details]
+      [/language]
+    [/languages]
+  [/umc]
+[/request_umc_upload]
+\end{lstlisting}
+
+\begin{description}
+  \item [[umc]] In case of a new version, the .pbl file is updated with the ID. See \cref{wire:request_campaign_list}.
+\end{description}
+
+\subsection{Request umc delete}
 \label{wire:request_umc_delete}
 
-\section{Request license}
+\subsubsection{Request}
+\begin{lstlisting}
+[request_umc_delete]
+  id = ID
+  password = PASSWORD
+[/request_umc_delete]
+\end{lstlisting}
+\begin{description}
+  \item [ID] The ID of the UMC we want to delete.
+  \item [PASSWORD] The password of the UMC.
+\end{description}
+
+\subsubsection{Reply}
+
+An error packet can be sent for the common reasons (see \cref{wire:specialpackets:errorpacket}) but also because:
+\begin{enumerate}
+ \item The password is wrong.
+\end{enumerate}
+
+Otherwise, a packet with no field is sent.
+\begin{lstlisting}
+[request_umc_delete]
+[/request_umc_delete]
+\end{lstlisting}
+
+\subsection{Request license}
 \label{wire:request_license}
+
+\subsubsection{Request}
+\begin{lstlisting}
+[request_license]
+  language = LANGUAGE
+[/request_license]
+\end{lstlisting}
+
+\begin{description}
+ \item [LANGUAGE] The language we want the license. 
+\end{description}
+
+\subsubsection{Reply}
+
+The license is sent in the language asked or, if not available, in American English.
+
+\begin{lstlisting}
+[request_license]
+  [warning_packet] ?
+    msg = MSG
+  [/warning_packet]
+  text = TEXT
+[/request_license]
+\end{lstlisting}
+
+\begin{description}
+ \item [[warning\_packet]] Can be sent if the language of the license is not the language expected.
+ \item [TEXT] The text of the license.
+\end{description}
+
+\section{Text encoding}
+
+The text encoding is important because the server can open the file to verify their validity or to read
+information in the .pbl file.
+
+The strings could be in something else than American English and for this reasons, the encoding must be UTF-8.
+
+\section{Security}
+\label{section:security}
+
+\subsection{Password storage}
+\label{section:security:passwordstorage}
+
+The passwords will be stored with a strong hash function such as SHA-512, 
+a salt only knowable by the server is append to this hash. The library OpenSSL (http://www.openssl.org/docs/crypto/sha.html)
+provides the algorithm, and a encapsulation in a C++ class will be required.
+
+\subsection{Password transmission}
+\label{section:security:passwordtransmission}
+
+The password will be transmit via Transport Layer Security (TLS) protocol. The library OpenSSL (http://www.openssl.org/docs/ssl/ssl.html)
+provides the secure socket. We will extend \textit{Boost.Asio} with them.
\ No newline at end of file
