← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcpp-plugin-sdk-cpp/LoLPlugin] Rev 23: init

 

------------------------------------------------------------
revno: 23
committer: poy <poy@xxxxxxxxxx>
branch nick: LoLPlugin
timestamp: Thu 2013-05-16 19:47:44 +0200
message:
  init
added:
  src/AdcCommand.cpp
  src/AdcCommand.h
  src/GUI.cpp
  src/GUI.h
modified:
  src/Plugin.cpp
  src/Plugin.h
  src/resource.rc
  src/stdafx.h
  src/version.h


--
lp:~dcplusplus-team/dcpp-plugin-sdk-cpp/LoLPlugin
https://code.launchpad.net/~dcplusplus-team/dcpp-plugin-sdk-cpp/LoLPlugin

Your team Dcplusplus-team is subscribed to branch lp:~dcplusplus-team/dcpp-plugin-sdk-cpp/LoLPlugin.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcpp-plugin-sdk-cpp/LoLPlugin/+edit-subscription
=== added file 'src/AdcCommand.cpp'
--- src/AdcCommand.cpp	1970-01-01 00:00:00 +0000
+++ src/AdcCommand.cpp	2013-05-16 17:47:44 +0000
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2001-2013 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "AdcCommand.h"
+
+namespace dcpp {
+
+AdcCommand::AdcCommand(uint32_t aCmd, char aType /* = TYPE_CLIENT */) : cmdInt(aCmd), from(0), type(aType) { }
+AdcCommand::AdcCommand(uint32_t aCmd, const uint32_t aTarget, char aType) : cmdInt(aCmd), from(0), to(aTarget), type(aType) { }
+
+AdcCommand::AdcCommand(const string& aLine, bool nmdc /* = false */) : cmdInt(0), type(TYPE_CLIENT) {
+	parse(aLine, nmdc);
+}
+
+void AdcCommand::parse(const string& aLine, bool nmdc /* = false */) {
+	string::size_type i = 5;
+
+	if(nmdc) {
+		// "$ADCxxx ..."
+		if(aLine.length() < 7)
+			return;
+		type = TYPE_CLIENT;
+		cmd[0] = aLine[4];
+		cmd[1] = aLine[5];
+		cmd[2] = aLine[6];
+		i += 3;
+	} else {
+		// "yxxx ..."
+		if(aLine.length() < 4)
+			return;
+		type = aLine[0];
+		cmd[0] = aLine[1];
+		cmd[1] = aLine[2];
+		cmd[2] = aLine[3];
+	}
+
+	if(type != TYPE_BROADCAST && type != TYPE_CLIENT && type != TYPE_DIRECT && type != TYPE_ECHO && type != TYPE_FEATURE && type != TYPE_INFO && type != TYPE_HUB && type != TYPE_UDP) {
+		return;
+	}
+
+	if(type == TYPE_INFO) {
+		from = HUB_SID;
+	}
+
+	string::size_type len = aLine.length();
+	const char* buf = aLine.c_str();
+	string cur;
+	cur.reserve(128);
+
+	bool toSet = false;
+	bool featureSet = false;
+	bool fromSet = nmdc; // $ADCxxx never have a from CID...
+
+	while(i < len) {
+		switch(buf[i]) {
+		case '\\':
+			++i;
+			if(i == len)
+				return;
+			if(buf[i] == 's')
+				cur += ' ';
+			else if(buf[i] == 'n')
+				cur += '\n';
+			else if(buf[i] == '\\')
+				cur += '\\';
+			else if(buf[i] == ' ' && nmdc)	// $ADCGET escaping, leftover from old specs
+				cur += ' ';
+			else
+				return;
+			break;
+		case ' ':
+			// New parameter...
+			{
+				if((type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) && !fromSet) {
+					if(cur.length() != 4) {
+						return;
+					}
+					from = toSID(cur);
+					fromSet = true;
+				} else if((type == TYPE_DIRECT || type == TYPE_ECHO) && !toSet) {
+					if(cur.length() != 4) {
+						return;
+					}
+					to = toSID(cur);
+					toSet = true;
+				} else if(type == TYPE_FEATURE && !featureSet) {
+					if(cur.length() % 5 != 0) {
+						return;
+					}
+					// Skip...
+					featureSet = true;
+				} else {
+					parameters.push_back(cur);
+				}
+				cur.clear();
+			}
+			break;
+		default:
+			cur += buf[i];
+		}
+		++i;
+	}
+	if(!cur.empty()) {
+		if((type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) && !fromSet) {
+			if(cur.length() != 4) {
+				return;
+			}
+			from = toSID(cur);
+			fromSet = true;
+		} else if((type == TYPE_DIRECT || type == TYPE_ECHO) && !toSet) {
+			if(cur.length() != 4) {
+				return;
+			}
+			to = toSID(cur);
+			toSet = true;
+		} else if(type == TYPE_FEATURE && !featureSet) {
+			if(cur.length() % 5 != 0) {
+				return;
+			}
+            // Skip...
+			featureSet = true;
+		} else {
+			parameters.push_back(cur);
+		}
+	}
+
+	if((type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) && !fromSet) {
+		return;
+	}
+
+	if(type == TYPE_FEATURE && !featureSet) {
+		return;
+	}
+
+	if((type == TYPE_DIRECT || type == TYPE_ECHO) && !toSet) {
+		return;
+	}
+}
+
+string AdcCommand::toString(uint32_t sid /* = 0 */, bool nmdc /* = false */) const {
+	return getHeaderString(sid, nmdc) + getParamString(nmdc);
+}
+
+string AdcCommand::escape(const string& str, bool old) {
+	string tmp = str;
+	string::size_type i = 0;
+	while( (i = tmp.find_first_of(" \n\\", i)) != string::npos) {
+		if(old) {
+			tmp.insert(i, "\\");
+		} else {
+			switch(tmp[i]) {
+				case ' ': tmp.replace(i, 1, "\\s"); break;
+				case '\n': tmp.replace(i, 1, "\\n"); break;
+				case '\\': tmp.replace(i, 1, "\\\\"); break;
+			}
+		}
+		i+=2;
+	}
+	return tmp;
+}
+
+string AdcCommand::getHeaderString(uint32_t sid, bool nmdc) const {
+	string tmp;
+	if(nmdc) {
+		tmp += "$ADC";
+	} else {
+		tmp += getType();
+	}
+
+	tmp += cmdChar;
+
+	if(type == TYPE_BROADCAST || type == TYPE_DIRECT || type == TYPE_ECHO || type == TYPE_FEATURE) {
+		tmp += ' ';
+		tmp += fromSID(sid);
+	}
+
+	if(type == TYPE_DIRECT || type == TYPE_ECHO) {
+		tmp += ' ';
+		tmp += fromSID(to);
+	}
+
+	if(type == TYPE_FEATURE) {
+		tmp += ' ';
+		tmp += features;
+	}
+	return tmp;
+}
+
+string AdcCommand::getParamString(bool nmdc) const {
+	string tmp;
+	for(auto& i: getParameters()) {
+		tmp += ' ';
+		tmp += escape(i, nmdc);
+	}
+	if(nmdc) {
+		tmp += '|';
+	} else {
+		tmp += '\n';
+	}
+	return tmp;
+}
+
+const string& AdcCommand::getParam(size_t n) const {
+	return getParameters().size() > n ? getParameters()[n] : emptyString;
+}
+
+bool AdcCommand::getParam(const char* name, size_t start, string& ret) const {
+	for(auto i = start; i < getParameters().size(); ++i) {
+		if(toCode(name) == toCode(getParameters()[i].c_str())) {
+			ret = getParameters()[i].substr(2);
+			return true;
+		}
+	}
+	return false;
+}
+
+bool AdcCommand::hasFlag(const char* name, size_t start) const {
+	for(auto i = start; i < getParameters().size(); ++i) {
+		if(toCode(name) == toCode(getParameters()[i].c_str()) &&
+			getParameters()[i].size() == 3 &&
+			getParameters()[i][2] == '1')
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+} // namespace dcpp

=== added file 'src/AdcCommand.h'
--- src/AdcCommand.h	1970-01-01 00:00:00 +0000
+++ src/AdcCommand.h	2013-05-16 17:47:44 +0000
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2001-2013 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DCPLUSPLUS_DCPP_ADC_COMMAND_H
+#define DCPLUSPLUS_DCPP_ADC_COMMAND_H
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace dcpp {
+
+using std::string;
+typedef std::vector<string> StringList;
+
+class AdcCommand {
+public:
+	template<uint32_t T>
+	struct Type {
+		enum { CMD = T };
+	};
+
+	enum Error {
+		SUCCESS = 0,
+		ERROR_GENERIC = 0,
+		ERROR_HUB_GENERIC = 10,
+		ERROR_HUB_FULL = 11,
+		ERROR_HUB_DISABLED = 12,
+		ERROR_LOGIN_GENERIC = 20,
+		ERROR_NICK_INVALID = 21,
+		ERROR_NICK_TAKEN = 22,
+		ERROR_BAD_PASSWORD = 23,
+		ERROR_CID_TAKEN = 24,
+		ERROR_COMMAND_ACCESS = 25,
+		ERROR_REGGED_ONLY = 26,
+		ERROR_INVALID_PID = 27,
+		ERROR_BANNED_GENERIC = 30,
+		ERROR_PERM_BANNED = 31,
+		ERROR_TEMP_BANNED = 32,
+		ERROR_PROTOCOL_GENERIC = 40,
+		ERROR_PROTOCOL_UNSUPPORTED = 41,
+		ERROR_CONNECT_FAILED = 42,
+		ERROR_INF_MISSING = 43,
+		ERROR_BAD_STATE = 44,
+		ERROR_FEATURE_MISSING = 45,
+		ERROR_BAD_IP = 46,
+		ERROR_NO_HUB_HASH = 47,
+		ERROR_TRANSFER_GENERIC = 50,
+		ERROR_FILE_NOT_AVAILABLE = 51,
+		ERROR_FILE_PART_NOT_AVAILABLE = 52,
+		ERROR_SLOTS_FULL = 53,
+		ERROR_NO_CLIENT_HASH = 54
+	};
+
+	enum Severity {
+		SEV_SUCCESS = 0,
+		SEV_RECOVERABLE = 1,
+		SEV_FATAL = 2
+	};
+
+	static const char TYPE_BROADCAST = 'B';
+	static const char TYPE_CLIENT = 'C';
+	static const char TYPE_DIRECT = 'D';
+	static const char TYPE_ECHO = 'E';
+	static const char TYPE_FEATURE = 'F';
+	static const char TYPE_INFO = 'I';
+	static const char TYPE_HUB = 'H';
+	static const char TYPE_UDP = 'U';
+
+#if defined(_WIN32) || defined(__i386__) || defined(__x86_64__) || defined(__alpha)
+#define C(n, a, b, c) static const uint32_t CMD_##n = (((uint32_t)a) | (((uint32_t)b)<<8) | (((uint32_t)c)<<16)); typedef Type<CMD_##n> n
+#else
+#define C(n, a, b, c) static const uint32_t CMD_##n = ((((uint32_t)a)<<24) | (((uint32_t)b)<<16) | (((uint32_t)c)<<8)); typedef Type<CMD_##n> n
+#endif
+	// Base commands
+	C(SUP, 'S','U','P');
+	C(STA, 'S','T','A');
+	C(INF, 'I','N','F');
+	C(MSG, 'M','S','G');
+	C(SCH, 'S','C','H');
+	C(RES, 'R','E','S');
+	C(CTM, 'C','T','M');
+	C(RCM, 'R','C','M');
+	C(GPA, 'G','P','A');
+	C(PAS, 'P','A','S');
+	C(QUI, 'Q','U','I');
+	C(GET, 'G','E','T');
+	C(GFI, 'G','F','I');
+	C(SND, 'S','N','D');
+	C(SID, 'S','I','D');
+	// Extensions
+	C(CMD, 'C','M','D');
+	C(NAT, 'N','A','T');
+	C(RNT, 'R','N','T');
+	C(ZON, 'Z','O','N');
+	C(ZOF, 'Z','O','F');
+	C(LOL, 'L','O','L');
+#undef C
+
+	static const uint32_t HUB_SID = 0xffffffff;		// No client will have this sid
+
+	static uint32_t toFourCC(const char* x) { return *reinterpret_cast<const uint32_t*>(x); }
+	static std::string fromFourCC(uint32_t x) { return std::string(reinterpret_cast<const char*>(&x), sizeof(x)); }
+
+	explicit AdcCommand(uint32_t aCmd, char aType = TYPE_CLIENT);
+	explicit AdcCommand(uint32_t aCmd, const uint32_t aTarget, char aType);
+	explicit AdcCommand(const string& aLine, bool nmdc = false);
+	void parse(const string& aLine, bool nmdc = false);
+
+	uint32_t getCommand() const { return cmdInt; }
+	char getType() const { return type; }
+	void setType(char t) { type = t; }
+	string getFourCC() const { string tmp(4, 0); tmp[0] = type; tmp[1] = cmd[0]; tmp[2] = cmd[1]; tmp[3] = cmd[2]; return tmp; }
+
+	const string& getFeatures() const { return features; }
+	AdcCommand& setFeatures(const string& feat) { features = feat; return *this; }
+
+	StringList& getParameters() { return parameters; }
+	const StringList& getParameters() const { return parameters; }
+
+	string toString(uint32_t sid = 0, bool nmdc = false) const;
+
+	AdcCommand& addParam(const string& name, const string& value) {
+		parameters.push_back(name);
+		parameters.back() += value;
+		return *this;
+	}
+	AdcCommand& addParam(const string& str) {
+		parameters.push_back(str);
+		return *this;
+	}
+	const string& getParam(size_t n) const;
+	/** Return a named parameter where the name is a two-letter code */
+	bool getParam(const char* name, size_t start, string& ret) const;
+	bool hasFlag(const char* name, size_t start) const;
+	static uint16_t toCode(const char* x) { return *((uint16_t*)x); }
+
+	bool operator==(uint32_t aCmd) { return cmdInt == aCmd; }
+
+	static string escape(const string& str, bool old);
+	uint32_t getTo() const { return to; }
+	AdcCommand& setTo(const uint32_t sid) { to = sid; return *this; }
+	uint32_t getFrom() const { return from; }
+
+	static uint32_t toSID(const string& aSID) { return *reinterpret_cast<const uint32_t*>(aSID.data()); }
+	static string fromSID(const uint32_t aSID) { return string(reinterpret_cast<const char*>(&aSID), sizeof(aSID)); }
+private:
+	string getHeaderString(uint32_t sid, bool nmdc) const;
+	string getParamString(bool nmdc) const;
+	StringList parameters;
+	string features;
+	union {
+		char cmdChar[4];
+		uint8_t cmd[4];
+		uint32_t cmdInt;
+	};
+	uint32_t from;
+	uint32_t to;
+	char type;
+	string emptyString;
+};
+
+} // namespace dcpp
+
+#endif // !defined(ADC_COMMAND_H)

=== added file 'src/GUI.cpp'
--- src/GUI.cpp	1970-01-01 00:00:00 +0000
+++ src/GUI.cpp	2013-05-16 17:47:44 +0000
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012-2013 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "stdafx.h"
+#include "GUI.h"
+#include "Plugin.h"
+
+#include <pluginsdk/Config.h>
+#include <pluginsdk/Util.h>
+
+#include <dwt/Application.h>
+#include <dwt/DWTException.h>
+#include <dwt/Events.h>
+#include <dwt/widgets/Button.h>
+#include <dwt/widgets/ComboBox.h>
+#include <dwt/widgets/Grid.h>
+#include <dwt/widgets/GroupBox.h>
+#include <dwt/widgets/Label.h>
+#include <dwt/widgets/TextBox.h>
+#include <dwt/widgets/Window.h>
+
+// dwt defines another tstring...
+typedef tstring _tstring;
+#define tstring _tstring
+
+using dcapi::Config;
+using dcapi::Util;
+
+using namespace dwt;
+
+WindowPtr window;
+ComboBoxPtr server;
+TextBoxPtr summoner;
+TextBoxPtr link;
+
+GUI::GUI()
+{
+}
+
+GUI::~GUI() {
+	if(window) {
+		::DestroyWindow(window->handle());
+		window = nullptr;
+		Application::uninit();
+	}
+}
+
+void GUI::create() {
+	if(window) {
+		return;
+	}
+
+	Application::init();
+
+	{
+		Window::Seed seed(_T(PLUGIN_NAME));
+		seed.location.size.x = 600;
+		seed.location.size.y = 300;
+
+		window = new Window();
+		window->create(seed);
+
+		auto iconPath = Util::toT(Config::getInstallPath() + "LoLPlugin.ico");
+		try {
+			window->setSmallIcon(new dwt::Icon(iconPath, dwt::Point(16, 16)));
+			window->setLargeIcon(new dwt::Icon(iconPath, dwt::Point(32, 32)));
+		} catch(const dwt::DWTException&) { }
+
+		window->onClosing([]() -> bool {
+			window = nullptr;
+			Application::uninit();
+			return true;
+		});
+	}
+
+	auto grid = window->addChild(Grid::Seed(3, 1));
+	grid->column(0).mode = GridInfo::FILL;
+	grid->setSpacing(6);
+
+	{
+		auto cur = grid->addChild(GroupBox::Seed(_T("Your LoL information")))->addChild(Grid::Seed(2, 1));
+		cur->column(0).mode = GridInfo::FILL;
+		cur->setSpacing(grid->getSpacing());
+
+		ComboBox::Seed cs;
+		cs.style |= CBS_DROPDOWNLIST;
+		server = cur->addChild(GroupBox::Seed(_T("The server you play on")))->addChild(cs);
+		const auto servConf = Config::getConfig("Server");
+		size_t counter = 0, sel = 0;
+		for(auto& serv: Plugin::servers) {
+			server->addValue(Util::toT(serv));
+			if(serv == servConf) { sel = counter; }
+			++counter;
+		}
+		server->setSelected(sel);
+
+		TextBox::Seed ts(Util::toT(Config::getConfig("Summoner")));
+		ts.style |= ES_AUTOHSCROLL;
+		summoner = cur->addChild(GroupBox::Seed(_T("Your summoner name")))->addChild(ts);
+	}
+
+	{
+		auto cur = grid->addChild(GroupBox::Seed(_T("Web link to display LoL information")))->addChild(Grid::Seed(3, 1));
+		cur->column(0).mode = GridInfo::FILL;
+		cur->setSpacing(grid->getSpacing());
+
+		auto row = cur->addChild(Grid::Seed(1, 2));
+		row->column(0).mode = GridInfo::FILL;
+		row->setSpacing(cur->getSpacing());
+
+		auto confLink = Config::getConfig("Link");
+		if(confLink.empty()) { confLink = Plugin::defLink; }
+		TextBox::Seed seed(Util::toT(confLink));
+		seed.style |= ES_AUTOHSCROLL;
+		link = row->addChild(seed);
+
+		row->addChild(Button::Seed(_T("Default link")))->onClicked([] { link->setText(Util::toT(Plugin::defLink)); });
+
+		cur->addChild(Label::Seed(_T("<server> will be replaced by the user's LoL server.")));
+		cur->addChild(Label::Seed(_T("<summoner> will be replaced by the user's LoL summoner name.")));
+	}
+
+	{
+		auto cur = grid->addChild(Grid::Seed(1, 2));
+		cur->column(0).mode = GridInfo::FILL;
+		cur->column(0).align = GridInfo::BOTTOM_RIGHT;
+		cur->setSpacing(grid->getSpacing());
+
+		Button::Seed bs(_T("OK"));
+		bs.style |= BS_DEFPUSHBUTTON;
+		bs.padding.x = 20;
+		cur->addChild(bs)->onClicked([this] { ok(); });
+
+		bs.caption = _T("Cancel");
+		bs.style &= ~BS_DEFPUSHBUTTON;
+		bs.padding.x = 10;
+		cur->addChild(bs)->onClicked([] { window->close(true); });
+	}
+
+	grid->resize(window->getClientSize());
+	window->onSized([grid](const SizedEvent& e) { grid->resize(e.size); });
+}
+
+void GUI::ok() {
+	Config::setConfig("Server", Util::fromT(server->getText()));
+	Config::setConfig("Summoner", Util::fromT(summoner->getText()));
+	Config::setConfig("Link", Util::fromT(link->getText()));
+	if(Config::getConfig("Link").empty()) { Config::setConfig("Link", Plugin::defLink); }
+
+	window->close(true);
+}

=== added file 'src/GUI.h'
--- src/GUI.h	1970-01-01 00:00:00 +0000
+++ src/GUI.h	2013-05-16 17:47:44 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012-2013 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PLUGIN_GUI_H
+#define PLUGIN_GUI_H
+
+class GUI
+{
+public:
+	GUI();
+	~GUI();
+
+	void create();
+
+private:
+	void ok();
+};
+
+#endif

=== modified file 'src/Plugin.cpp'
--- src/Plugin.cpp	2013-01-18 21:37:14 +0000
+++ src/Plugin.cpp	2013-05-16 17:47:44 +0000
@@ -19,21 +19,40 @@
 #include "stdafx.h"
 #include "Plugin.h"
 
+#include <boost/algorithm/string/replace.hpp>
+
 /* Include plugin SDK helpers. There are more interfaces available that can be included in the same
 fashion (check the pluginsdk directory). */
 #include <pluginsdk/Config.h>
 #include <pluginsdk/Core.h>
 #include <pluginsdk/Hooks.h>
+#include <pluginsdk/Hubs.h>
 #include <pluginsdk/Logger.h>
+#include <pluginsdk/UI.h>
 #include <pluginsdk/Util.h>
 
+#include "AdcCommand.h"
+
+#include <shellapi.h>
+
 /* Plugin SDK helpers are in the "dcapi" namespace; ease their calling. */
 using dcapi::Config;
 using dcapi::Core;
 using dcapi::Hooks;
+using dcapi::Hubs;
 using dcapi::Logger;
+using dcapi::UI;
 using dcapi::Util;
 
+using dcpp::AdcCommand;
+
+const string feat = "LOLI";
+
+const string Plugin::defLink = "http://quickfind.kassad.in/profile/<server>/<summoner>/";
+const string Plugin::servers[7] = { "br", "eune", "euw", "kr", "na", "ru", "tr" };
+
+const size_t MAX_CACHE = 10;
+
 Plugin::Plugin() {
 }
 
@@ -60,6 +79,12 @@
 			return True;
 		}
 
+	case ON_CONFIGURE:
+		{
+			instance->onConfigure();
+			return True;
+		}
+
 	default:
 		{
 			return False;
@@ -71,15 +96,110 @@
 	/* Initialization phase. Initiate additional interfaces that you may have included from the
 	plugin SDK. */
 	Core::init(core);
-	if(!Config::init(PLUGIN_GUID) || !Hooks::init() || !Logger::init() || !Util::init()) {
+	if(!Config::init(PLUGIN_GUID) || !Hooks::init() || !Hubs::init() || !Logger::init() || !UI::init(PLUGIN_GUID) || !Util::init()) {
 		return false;
 	}
 
+	if(Config::getConfig("Link").empty()) { Config::setConfig("Link", defLink); }
+
 	if(install) {
 		// This only executes when the plugin has been installed for the first time.
+		Logger::log("The LoL plugin has been installed; check the plugins menu to configure it.");
+
+		onConfigure();
+	}
+
+	if(Config::getConfig("Server").empty() || Config::getConfig("Summoner").empty()) {
+		Logger::log("LoL plugin: You have not defined your LoL settings; use the plugins menu to configure them.");
 	}
 
 	// Start the plugin logic here; add hooks with functions from the Hooks interface.
+	Hooks::Network::onHubDataIn([this](HubDataPtr hub, char* message, bool&) { return onHubDataIn(hub, message); });
+	Hooks::Network::onHubDataOut([this](HubDataPtr hub, char* message, bool&) { return onHubDataOut(hub, message); });
 
 	return true;
 }
+
+void Plugin::onConfigure() {
+	gui.create();
+}
+
+namespace {
+#ifdef _WIN32
+void openLink(const string& link) {
+	ShellExecute(nullptr, nullptr, Util::toT(link).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
+}
+#else
+void openLink(const string& link) {
+	system(string("xdg-open " + link).c_str());
+}
+#endif
+} // unnamed namespace
+
+bool Plugin::onHubDataIn(HubDataPtr hub, char* message) {
+	if(hub->protocol == PROTOCOL_ADC) {
+		auto cmd = AdcCommand(message);
+
+		if(cmd.getCommand() == AdcCommand::CMD_SID && cmd.getType() == AdcCommand::TYPE_INFO) {
+			// add the user command.
+			Hubs::handle()->emulate_protocol_cmd(hub,
+				AdcCommand(AdcCommand::CMD_CMD, AdcCommand::TYPE_INFO)
+				.addParam("Open LoL profile")
+				.addParam("CT", "14" /* 2 + 4 + 8 */)
+				.addParam("TT", "DLOL %[mySID] %[userSID]\n")
+				.addParam("CO", "1")
+				.toString().c_str());
+
+		} else if(cmd.getCommand() == AdcCommand::CMD_LOL && cmd.getType() == AdcCommand::TYPE_DIRECT) {
+			if(cmd.getParameters().empty()) {
+				// answer with our LoL info.
+				Hubs::handle()->send_protocol_cmd(hub,
+					AdcCommand(AdcCommand::CMD_LOL, cmd.getFrom(), AdcCommand::TYPE_DIRECT)
+					.addParam("SE", Config::getConfig("Server"))
+					.addParam("SU", Config::getConfig("Summoner"))
+					.toString(cmd.getTo()).c_str());
+
+			} else {
+				if(std::find(cache.begin(), cache.end(), cmd.getFrom()) != cache.end()) {
+					string server, summoner;
+					if(cmd.getParam("SE", 0, server) && cmd.getParam("SU", 0, summoner)) {
+						auto link = Config::getConfig("Link");
+						boost::ireplace_first(link, "<server>", server);
+						boost::ireplace_first(link, "<summoner>", summoner);
+						openLink(link);
+					}
+				}
+			}
+		}
+
+	} else if(hub->protocol == PROTOCOL_NMDC) {
+		// TODO fuck NMDC?
+	}
+	return false;
+}
+
+bool Plugin::onHubDataOut(HubDataPtr hub, char* message) {
+	if(hub->protocol == PROTOCOL_ADC) {
+		auto cmd = AdcCommand(message);
+
+		if(cmd.getCommand() == AdcCommand::CMD_INF) {
+			// add the feature to INF SU.
+			auto& params = cmd.getParameters();
+			for(auto& param: params) {
+				if(AdcCommand::toCode(param.c_str()) == AdcCommand::toCode("SU") && param.find(feat) == string::npos) {
+					param += ',' + feat;
+				}
+			}
+
+		} else if(cmd.getCommand() == AdcCommand::CMD_LOL) {
+			if(cache.size() > MAX_CACHE) {
+				cache.erase(cache.begin(), cache.begin() + MAX_CACHE / 2);
+			}
+			cache.push_back(cmd.getTo());
+		}
+
+	} else if(hub->protocol == PROTOCOL_NMDC) {
+		// TODO fuck NMDC?
+	}
+	return false;
+}

=== modified file 'src/Plugin.h'
--- src/Plugin.h	2013-01-18 21:37:14 +0000
+++ src/Plugin.h	2013-05-16 17:47:44 +0000
@@ -19,18 +19,31 @@
 #ifndef PLUGIN_PLUGIN_H
 #define PLUGIN_PLUGIN_H
 
-using std::string;
+#include <vector>
+
+#include "GUI.h"
 
 class Plugin
 {
 public:
 	static Bool DCAPI main(PluginState state, DCCorePtr core, dcptr_t);
 
+	static const string defLink;
+	static const string servers[7];
+
 private:
 	Plugin();
 	~Plugin();
 
 	bool onLoad(DCCorePtr core, bool install);
+	void onConfigure();
+	bool onHubDataIn(HubDataPtr hub, char* message);
+	bool onHubDataOut(HubDataPtr hub, char* message);
+
+	// dumb cache to make sure people don't spam us with random LOLs...
+	std::vector<uint32_t> cache;
+
+	GUI gui;
 };
 
 #endif

=== modified file 'src/resource.rc'
--- src/resource.rc	2012-11-15 18:17:16 +0000
+++ src/resource.rc	2013-05-16 17:47:44 +0000
@@ -67,13 +67,13 @@
     BEGIN
         BLOCK "080004b0"
         BEGIN
-            VALUE "Comments", "..."
-            VALUE "FileDescription", "..."
+            VALUE "Comments", "http://dcplusplus.sourceforge.net";
+            VALUE "FileDescription", "LoL plugin for DC++"
             VALUE "FileVersion", "1, 0, 0, 0"
-            VALUE "InternalName", "..."
-            VALUE "LegalCopyright", "..."
-            VALUE "OriginalFilename", "..."
-            VALUE "ProductName", "..."
+            VALUE "InternalName", "LoLPlugin"
+            VALUE "LegalCopyright", "Copyright (C) 2012-2013 Jacek Sieka"
+            VALUE "OriginalFilename", "LoLPlugin.dll"
+            VALUE "ProductName", "LoL plugin for DC++"
             VALUE "ProductVersion", "1, 0, 0, 0"
         END
     END

=== modified file 'src/stdafx.h'
--- src/stdafx.h	2013-01-18 21:37:14 +0000
+++ src/stdafx.h	2013-05-16 17:47:44 +0000
@@ -33,6 +33,7 @@
 #include <cstdio>
 #include <cstdint>
 #include <string>
+#include <utility>
 
 #include <pluginsdk/PluginDefs.h>
 
@@ -44,4 +45,7 @@
 typedef std::string tstring;
 #endif
 
+using std::move;
+using std::string;
+
 #endif

=== modified file 'src/version.h'
--- src/version.h	2013-01-18 21:37:14 +0000
+++ src/version.h	2013-05-16 17:47:44 +0000
@@ -18,27 +18,25 @@
 
 /* Information about the plugin - fill this out! Don't forget to edit the resource file as well. */
 
-#error Version information not set! Remove this error once you have filled version.h and the resource file.
-
 #ifndef PLUGIN_VERSION_H
 #define PLUGIN_VERSION_H
 
 /* UUID/GUID for this plugin project */
-#define PLUGIN_GUID "..."
+#define PLUGIN_GUID "{32c71f4f-ea2f-40ea-a5c9-52e46e721bbc}"
 
 /* Name of the plugin */
-#define PLUGIN_NAME "..."
+#define PLUGIN_NAME "LoL plugin"
 
 /* Author of the plugin */
-#define PLUGIN_AUTHOR "..."
+#define PLUGIN_AUTHOR "DC++"
 
 /* Short description of the plugin */
-#define PLUGIN_DESC "..."
+#define PLUGIN_DESC "Exchange League of Legends profile information with other users."
 
 /* Version of the plugin (note: not API version) */
 #define PLUGIN_VERSION 1.0
 
 /* Plugin website, set to "N/A" if none */
-#define PLUGIN_WEB "N/A"
+#define PLUGIN_WEB "http://dcplusplus.sourceforge.net/";
 
 #endif