summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authormaz-12015-10-08 04:40:15 +0800
committermaz-12015-10-08 04:40:15 +0800
commitb14389e644ca7f4fe58e61c82315c0fc0aaff772 (patch)
tree800ada4bea5d8478dd238283b26f30a0e44f803e
downloadaur-b14389e644ca7f4fe58e61c82315c0fc0aaff772.tar.gz
initial
-rw-r--r--.SRCINFO30
-rw-r--r--PKGBUILD67
-rw-r--r--amule-dlp.patch1458
-rw-r--r--amule.install29
-rw-r--r--amuled.systemd11
-rw-r--r--amuleweb.systemd13
6 files changed, 1608 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..4dbc41e3a37c
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,30 @@
+pkgbase = amule-dlp
+ pkgdesc = An eMule-like client for ed2k p2p network
+ pkgver = 10871
+ pkgrel = 1
+ url = http://www.amule.org
+ install = amule.install
+ arch = i686
+ arch = x86_64
+ license = GPL
+ depends = wxgtk
+ depends = wxgtk2.8
+ depends = gd
+ depends = geoip
+ depends = libupnp
+ depends = crypto++
+ depends = libsm
+ optdepends = antileech
+ provides = amule
+ conflicts = amule
+ source = http://amule.sourceforge.net/tarballs/aMule-SVN-r10871.tar.bz2
+ source = amuled.systemd
+ source = amuleweb.systemd
+ source = amule-dlp.patch
+ md5sums = f3c666b6fa518a3e6e2c21670c243292
+ md5sums = 59772c41860e238f1c822feb8ca8d47f
+ md5sums = 05975c5d94bfc41fddb894d98b1115d5
+ md5sums = 8f3bc2d105b6acf2d25b19b01bdfbe30
+
+pkgname = amule-dlp
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..b818250f9084
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,67 @@
+# $Id: PKGBUILD 240850 2015-06-15 06:19:33Z giovanni $
+# Maintainer: Giovanni Scafora <giovanni@archlinux.org>
+# Contributor: Henrik Ronellenfitsch <searinox@web.de>
+# Contributor: Alessio Sergi <sergi.alessio {at} gmail.com>
+# Contributor: Dario 'Dax' Vilardi <dax [at] deelab [dot] org>
+# Contributor: Anatol Pomozov <anatol.pomozov@gmail.com>
+
+pkgname=amule-dlp
+pkgver=10871
+pkgrel=1
+pkgdesc="An eMule-like client for ed2k p2p network"
+arch=('i686' 'x86_64')
+url="http://www.amule.org"
+license=('GPL')
+depends=('wxgtk' 'wxgtk2.8' 'gd' 'geoip' 'libupnp' 'crypto++' 'libsm')
+optdepends=('antileech')
+provides=(amule)
+conflicts=(amule)
+install=amule.install
+source=("http://amule.sourceforge.net/tarballs/aMule-SVN-r${pkgver}.tar.bz2"
+ 'amuled.systemd'
+ 'amuleweb.systemd'
+ 'amule-dlp.patch'
+ )
+md5sums=('f3c666b6fa518a3e6e2c21670c243292'
+ '59772c41860e238f1c822feb8ca8d47f'
+ '05975c5d94bfc41fddb894d98b1115d5'
+ '8f3bc2d105b6acf2d25b19b01bdfbe30')
+prepare() {
+ cd "${srcdir}/aMule-SVN-r${pkgver}"
+ patch -p1 < ../amule-dlp.patch
+
+}
+
+
+build() {
+ cd "${srcdir}/aMule-SVN-r${pkgver}"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-cas \
+ --enable-wxcas \
+ --enable-amule-daemon \
+ --enable-amulecmd \
+ --enable-amule-gui \
+ --enable-alc \
+ --enable-alcc \
+ --enable-webserver \
+ --disable-debug \
+ --enable-optimize \
+ --enable-ccache \
+ --enable-geoip \
+ --enable-upnp \
+ --enable-dlp \
+ --with-wxversion=2.8
+
+ make
+}
+
+package() {
+ cd "${srcdir}/aMule-SVN-r${pkgver}"
+
+ make DESTDIR=${pkgdir} install
+
+ install -D -m644 "${srcdir}/amuled.systemd" "${pkgdir}/usr/lib/systemd/system/amuled.service"
+ install -D -m644 "${srcdir}/amuleweb.systemd" "${pkgdir}/usr/lib/systemd/system/amuleweb.service"
+}
diff --git a/amule-dlp.patch b/amule-dlp.patch
new file mode 100644
index 000000000000..34a66351d4d7
--- /dev/null
+++ b/amule-dlp.patch
@@ -0,0 +1,1458 @@
+diff -Naur amule/configure.in amule-dlp/configure.in
+--- amule/configure.in 2015-06-19 14:46:14.860175576 +0800
++++ amule-dlp/configure.in 2015-06-19 13:34:36.331051364 +0800
+@@ -89,6 +89,14 @@
+ KDE_CONFIG_OPTIONS
+ QT_CONFIG_OPTIONS
+
++#Dynamic Leecher Protection - Bill Lee
++AC_ARG_ENABLE(
++ [dlp],
++ [AS_HELP_STRING(
++ [--disable-dlp],
++ [Do not compile DLP.])],
++ [ENABLE_DLP=$enableval], [ENABLE_DLP=yes])
++
+ # Default is yes, because they're most likely compatible.
+ # However, this is only used when cross-compiling.
+ AC_ARG_WITH(
+@@ -457,6 +465,8 @@
+ AM_CONDITIONAL(GENERATE_FLEX_HEADER, test x$HAVE_FLEX_EXTENDED = xyes)
+ AM_CONDITIONAL(INSTALL_SKINS, test MULE_IS_ENABLED_ANY([monolithic, amule-gui]))
+ AM_CONDITIONAL(PLASMAMULE, test MULE_IS_ENABLED([plasmamule]))
++#Dynamic Leech Protection - Bill Lee
++AM_CONDITIONAL(ENABLE_DLP, test x$ENABLE_DLP = xyes)
+
+ AM_CONDITIONAL([COMPILE_LIB_COMMON], [test MULE_IS_ENABLED_ANY([monolithic, amule-daemon, amulecmd, webserver, amule-gui, fileview])])
+ AM_CONDITIONAL([COMPILE_LIB_EC], [test MULE_IS_ENABLED_ANY([monolithic, amule-daemon, amulecmd, webserver, amule-gui])])
+diff -Naur amule/po/zh_CN.po amule-dlp/po/zh_CN.po
+--- amule/po/zh_CN.po 2015-06-19 14:46:14.936172416 +0800
++++ amule-dlp/po/zh_CN.po 2015-06-19 13:35:59.000000000 +0800
+@@ -5,6 +5,7 @@
+ # xiaoqiao <29551030@qq.com>, 2007, 2008.
+ # JimHu <jimhuyiwei@gmail.com>, 2009.
+ # Xiaoqiao <wo@xiaoqiao.me>, 2010.
++# Bill Lee <bill.lee.y@gmail.com>, 2010, 2011.
+ # Yi Qi <u4781098@anu.edu.au>,2011.
+ #
+ msgid ""
+@@ -467,6 +468,13 @@
+ msgid "http://kademlia.scs.cs.nyu.edu\n"
+ msgstr "http://kademlia.scs.cs.nyu.edu\n"
+
++msgid "\nDynamic Leech Protection\n"
++msgstr "\n动态吸血保护\n"
++
++msgid " Homepage: http://amule-dlp.googlecode.com \n"
++msgstr " 主页:http://amule-dlp.googlecode.com \n"
++
++
+ #: src/amuleDlg.cpp:513 src/KadDlg.cpp:193 src/PartFile.cpp:920
+ #: src/PartFile.cpp:928 src/PrefsUnifiedDlg.cpp:629
+ #: src/PrefsUnifiedDlg.cpp:734 src/PrefsUnifiedDlg.cpp:847
+@@ -3856,6 +3864,9 @@
+ msgid "Click on this button to update the nodes list from URL ..."
+ msgstr "按此更新节点列表自网址..."
+
++msgid "DLP Info"
++msgstr "动态反吸血信息"
++
+ #: src/muuli_wdr.cpp:2649
+ msgid "Nodes (0)"
+ msgstr "节点(0)"
+@@ -7672,6 +7683,48 @@
+ #~ "\n"
+ #~ "此外,浏览器设定已经被重设为系统默认值。如有必要,请重新配置浏览器选项。\n"
+
++msgid "Dynamic Leecher Protection Options"
++msgstr "动态反吸血保护选项"
++
++msgid "Reload antiLeech"
++msgstr "重新装载 antiLeech"
++
++msgid "Check bad modstring"
++msgstr "根据 Mod 名字检测吸血驴"
++
++msgid "Check bad username"
++msgstr "根据用户名字检测吸血驴"
++
++msgid "Check bad userhash"
++msgstr "检测错误的用户哈希值"
++
++msgid "Check bad hello tag"
++msgstr "根据握手标签(HelloTag)检测吸血驴"
++
++msgid "Check bad info tag"
++msgstr "根据 InfoTag 检测吸血驴"
++
++msgid "Check ghost mod"
++msgstr "检测幽灵客户端(Ghost Mod)"
++
++#~ msgid "Ban VeryCD easyMule2"
++#~ msgstr "屏蔽 VeryCD easyMule2"
++
++msgid "Ban eMule VeryCD mod(Please consider carefully whether to use)"
++msgstr "屏蔽 VeryCD eMule(请慎重考虑是否使用)"
++
++#~ msgid "Ban VeryCD miniMule"
++#~ msgstr "屏蔽 VeryCD miniMule"
++
++msgid "Trying to load antiLeech..."
++msgstr "尝试加载 antiLeech..."
++
++msgid "No antiLeech available!"
++msgstr "未找到 antiLeech!"
++
++msgid "Succeed loading antiLeech! Version: %d"
++msgstr "成功加载 antiLeech! 版本: %d"
++
+ #~ msgid "Fetching status..."
+ #~ msgstr "正在获取状态..."
+
+diff -Naur amule/src/amule.cpp amule-dlp/src/amule.cpp
+--- amule/src/amule.cpp 2015-06-19 14:46:14.972170919 +0800
++++ amule-dlp/src/amule.cpp 2015-06-19 13:34:36.331051364 +0800
+@@ -23,7 +23,6 @@
+ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ //
+
+-
+ #include "amule.h" // Interface declarations.
+
+ #include <csignal>
+@@ -89,6 +88,11 @@
+ #include <wx/sysopt.h> // Do_not_auto_remove
+ #endif
+
++//Dynamic Leecher Protection - Bill Lee
++#ifdef AMULE_DLP
++#include "DLP.h"
++#endif
++
+ #ifndef AMULE_DAEMON
+ #ifdef __WXMAC__
+ #include <CoreFoundation/CFBundle.h> // Do_not_auto_remove
+@@ -517,6 +521,11 @@
+ uploadqueue = new CUploadQueue();
+ ipfilter = new CIPFilter();
+
++ //DLP initialization - Bill Lee
++ #ifdef AMULE_DLP
++ theDLP = new DLP();
++ #endif
++
+ // Creates all needed listening sockets
+ wxString msg;
+ if (!ReinitializeNetwork(&msg)) {
+@@ -2049,3 +2058,8 @@
+ DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
+ DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
+ // File_checked_for_headers
++
++//Dynamic Leech Protect - Bill Lee
++#ifdef AMULE_DLP
++DLP* theDLP;
++#endif
+diff -Naur amule/src/amuled.cpp amule-dlp/src/amuled.cpp
+--- amule/src/amuled.cpp 2015-06-19 14:46:14.972170919 +0800
++++ amule-dlp/src/amuled.cpp 2015-06-19 13:34:36.331051364 +0800
+@@ -746,4 +746,8 @@
+ return 0; // That's neither yes nor no, ok, cancel
+ }
+
++void CamuleDaemonApp::AddDLPMessageLine(const wxString &msg)
++{
++}
++
+ // File_checked_for_headers
+diff -Naur amule/src/amuleDlg.cpp amule-dlp/src/amuleDlg.cpp
+--- amule/src/amuleDlg.cpp 2015-06-19 14:46:14.972170919 +0800
++++ amule-dlp/src/amuleDlg.cpp 2015-06-19 13:37:42.000000000 +0800
+@@ -314,7 +314,7 @@
+ wxNotebook* logs_notebook = CastChild( ID_SRVLOG_NOTEBOOK, wxNotebook);
+ wxNotebook* networks_notebook = CastChild( ID_NETNOTEBOOK, wxNotebook);
+
+- wxASSERT(logs_notebook->GetPageCount() == 4);
++ wxASSERT(logs_notebook->GetPageCount() == 5);
+ wxASSERT(networks_notebook->GetPageCount() == 2);
+
+ for (uint32 i = 0; i < logs_notebook->GetPageCount(); ++i) {
+@@ -506,7 +506,12 @@
+ _("Part of aMule is based on \n") <<
+ _("Kademlia: Peer-to-peer routing based on the XOR metric.\n") <<
+ _(" Copyright (c) 2002-2011 Petar Maymounkov ( petar@post.harvard.edu )\n") <<
+- _("http://kademlia.scs.cs.nyu.edu\n");
++ _("http://kademlia.scs.cs.nyu.edu\n") <<
++ _("\nDynamic Leech Protection\n") <<
++ _(" Homepage: http://amule-dlp.googlecode.com \n") <<
++ _(" Copyright (C) 2002-2007 Xtreme-Mod \n") <<
++ _(" Copyright (C) 2009 greensea \n") <<
++ _(" Copyright (C) 2009-2011 Bill Lee \n");
+
+ if (m_is_safe_state) {
+ wxMessageBox(msg, _("Message"), wxOK | wxICON_INFORMATION, this);
+@@ -660,6 +665,20 @@
+ }
+ }
+
++#ifdef AMULE_DLP
++void CamuleDlg::AddDLPMessageLine(const wxString& msg) /* modified by Bill Lee */
++{
++ wxTextCtrl* cv = CastByID( ID_DLPINFO, m_serverwnd, wxTextCtrl );
++ if(cv) {
++ if (msg.Length() > 500) {
++ cv->AppendText(msg.Left(500) + wxT("\n"));
++ } else {
++ cv->AppendText(msg + wxT("\n"));
++ }
++ cv->ShowPosition(cv->GetLastPosition()-1);
++ }
++}
++#endif
+
+ void CamuleDlg::ShowConnectionState(bool skinChanged)
+ {
+@@ -1455,7 +1474,9 @@
+ if (thePrefs::GetNetworkKademlia()) {
+ logs_notebook->AddPage(m_logpages[3].page, m_logpages[3].name);
+ }
+-
++
++ logs_notebook->AddPage(m_logpages[4].page, m_logpages[4].name);
++
+ // Set the main window.
+ // If we have both networks active, activate a notebook to select between them.
+ // If only one is active, show the window directly without a surrounding one tab notebook.
+diff -Naur amule/src/amuleDlg.h amule-dlp/src/amuleDlg.h
+--- amule/src/amuleDlg.h 2015-06-19 14:46:14.972170919 +0800
++++ amule-dlp/src/amuleDlg.h 2015-06-19 13:34:36.339051031 +0800
+@@ -114,6 +114,9 @@
+
+ void AddLogLine(const wxString& line);
+ void AddServerMessageLine(wxString& message);
++ #ifdef AMULE_DLP
++ void AddDLPMessageLine(const wxString& msg); /* Modified by Bill Lee */
++ #endif
+ void ResetLog(int id);
+
+ void ShowUserCount(const wxString& info = wxEmptyString);
+@@ -231,7 +234,7 @@
+ WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
+ ZipCatalog cat;
+
+- PageType m_logpages[4];
++ PageType m_logpages[5];
+ PageType m_networkpages[2];
+
+ bool LoadGUIPrefs(bool override_pos, bool override_size);
+diff -Naur amule/src/amule-gui.cpp amule-dlp/src/amule-gui.cpp
+--- amule/src/amule-gui.cpp 2015-06-19 14:46:14.964171252 +0800
++++ amule-dlp/src/amule-gui.cpp 2015-06-19 13:34:36.343050864 +0800
+@@ -332,6 +332,21 @@
+ return CamuleApp::GetLog(reset);
+ }
+
++#ifdef AMULE_DLP
++void CamuleGuiApp::AddDLPMessageLine(const wxString &msg)
++{
++ wxString message;
++ time_t rawtime;
++ struct tm *timeinfo;
++ char tbuf[101];
++ time(&rawtime);
++ timeinfo = localtime(&rawtime);
++ strftime(tbuf, 100, "%Y-%m-%d %X: ", timeinfo);
++
++ message = wxString(tbuf, wxConvUTF8) + msg;
++ amuledlg->AddDLPMessageLine(message);
++}
++#endif
+
+ wxString CamuleGuiApp::GetServerLog(bool reset)
+ {
+diff -Naur amule/src/amule.h amule-dlp/src/amule.h
+--- amule/src/amule.h 2015-06-19 14:46:14.972170919 +0800
++++ amule-dlp/src/amule.h 2015-06-19 13:34:36.343050864 +0800
+@@ -395,6 +395,7 @@
+ wxString GetLog(bool reset = false);
+ wxString GetServerLog(bool reset = false);
+ void AddServerMessageLine(wxString &msg);
++ void AddDLPMessageLine(const wxString &msg);
+ DECLARE_EVENT_TABLE()
+ };
+
+@@ -558,6 +559,8 @@
+
+ virtual int ShowAlert(wxString msg, wxString title, int flags);
+
++ void AddDLPMessageLine(const wxString &msg);
++
+ DECLARE_EVENT_TABLE()
+ };
+
+@@ -568,3 +571,8 @@
+
+ #endif // AMULE_H
+ // File_checked_for_headers
++
++#ifdef AMULE_DLP
++class DLP; //forward declaretion
++extern DLP* theDLP;
++#endif
+diff -Naur amule/src/antiLeech.h amule-dlp/src/antiLeech.h
+--- amule/src/antiLeech.h 1970-01-01 08:00:00.000000000 +0800
++++ amule-dlp/src/antiLeech.h 2015-06-19 13:34:36.347050698 +0800
+@@ -0,0 +1,48 @@
++#ifndef ANTILEECH_H
++#define ANTILEECH_H
++
++
++#pragma once
++
++#include "antiLeech_wx.h"
++#include "CString_wx.h"
++
++class IantiLeech
++{
++public:
++ virtual ~IantiLeech(){}; /* Bill Lee: Not be used currently */
++ //BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD,LPVOID);
++ virtual DWORD GetDLPVersion() = 0;
++ //old versions to keep compatible
++ /* //drop old version support
++ virtual LPCTSTR DLPCheckModstring(LPCTSTR modversion, LPCTSTR clientversion);
++ virtual LPCTSTR DLPCheckUsername(LPCTSTR username);
++ virtual LPCTSTR DLPCheckNameAndHash(CString username, CString& userhash);
++ */
++ //new versions
++ virtual LPCTSTR DLPCheckModstring_Hard(LPCTSTR modversion, LPCTSTR clientversion) = 0;
++ virtual LPCTSTR DLPCheckModstring_Soft(LPCTSTR modversion, LPCTSTR clientversion) = 0;
++ virtual LPCTSTR DLPCheckUsername_Hard(LPCTSTR username) = 0;
++ virtual LPCTSTR DLPCheckUsername_Soft(LPCTSTR username) = 0;
++ virtual LPCTSTR DLPCheckNameAndHashAndMod(const CString& username, const CString& userhash, const CString& modversion) = 0;
++ virtual LPCTSTR DLPCheckMessageSpam(LPCTSTR messagetext) = 0;
++
++
++ virtual LPCTSTR DLPCheckUserhash(const PBYTE userhash) = 0;
++
++
++ virtual LPCTSTR DLPCheckHelloTag(UINT tagnumber) = 0;
++ virtual LPCTSTR DLPCheckInfoTag(UINT tagnumber) = 0;
++
++ //void TestFunc();
++
++//Bill Lee: no need in interface abstract class
++//private:
++// static bool IsTypicalHex (const CString& addon);
++};
++
++//Bill Lee: never call delete on IantiLeech, use destoryAntiLeechInstat instead.
++extern "C" IantiLeech* createAntiLeechInstant();
++extern "C" int destoryAntiLeechInstant(IantiLeech*);
++
++#endif
+diff -Naur amule/src/antiLeech_wx.h amule-dlp/src/antiLeech_wx.h
+--- amule/src/antiLeech_wx.h 1970-01-01 08:00:00.000000000 +0800
++++ amule-dlp/src/antiLeech_wx.h 2015-06-19 13:34:36.347050698 +0800
+@@ -0,0 +1,49 @@
++#ifndef ANTILEECH_WX_H
++#define ANTILEECH_WX_H
++
++#include <wx/defs.h>
++#include <string.h>
++
++#define LPCTSTR const wxChar*
++#define BOOL bool
++//#define _T(var) wxT(var) //defined in wxWidgets
++#define DWORD wxUint32
++#define UINT wxUint16
++#define WINAPI
++#define HINSTANCE
++#define LPVOID void*
++#define PBYTE unsigned char*
++#define TCHAR wxChar
++#define _TINT wxInt32
++
++#define StrCmpI _tcsicmp
++
++#define _istdigit(var) iswdigit(var)
++#define _istcntrl(var) iswcntrl(var)
++#define _istpunct(var) iswpunct(var)
++#define _istspace(var) iswspace(var)
++#define _istxdigit(var) iswxdigit(var)
++inline float _tstof(const wchar_t* str){
++ wchar_t** ptail = NULL;
++ return wcstof(str, ptail);
++}
++//This function is not used. by Orzogc Lee
++//But I think there is no need to removing, linker will remove it.
++/*
++inline void tolowers(wxChar* str){
++ int i = 0;
++ do{
++ str[i] = towlower(str[i]);
++ }while(str[++i]);
++}
++*/
++#define _tcsstr(haystack, needle) wcsstr(haystack, needle)
++#define _tcslen(var) wcslen(var)
++#define StrStr(a, b) wcsstr(a, b)
++
++LPCTSTR StrStrI(LPCTSTR haystack, LPCTSTR needle);
++//Bill Lee: I think inlining this function make no senses, because it is a very large operation.
++
++#define _tcsicmp(a, b) wcscasecmp(a, b)
++
++#endif
+diff -Naur amule/src/BaseClient.cpp amule-dlp/src/BaseClient.cpp
+--- amule/src/BaseClient.cpp 2015-06-19 14:46:14.940172250 +0800
++++ amule-dlp/src/BaseClient.cpp 2015-06-19 14:49:51.000000000 +0800
+@@ -1,4 +1,3 @@
+-//
+ // This file is part of the aMule Project.
+ //
+ // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
+@@ -23,6 +22,11 @@
+ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ //
+
++//Dynamic Leech Protect - Bill Lee
++#ifdef AMULE_DLP
++#include "DLP.h"
++#endif
++
+ #include <wx/wx.h>
+ #include <wx/mstream.h>
+ #include <wx/tokenzr.h>
+@@ -83,10 +87,8 @@
+ #include "kademlia/kademlia/UDPFirewallTester.h"
+ #include "kademlia/routing/RoutingZone.h"
+
+-
+ //#define __PACKET_DEBUG__
+
+-
+ // some client testing variables
+ static wxString crash_name = wxT("[Invalid User Name]");
+ static wxString empty_name = wxT("[Empty User Name]");
+@@ -290,6 +292,10 @@
+ m_cMessagesReceived = 0;
+ m_cMessagesSent = 0;
+
++ #ifdef AMULE_DLP
++ dlp_nonofficialopcodes = false; //Dynamic Leecher Protect
++ #endif
++
+ }
+
+
+@@ -635,6 +641,15 @@
+ m_fSharedDirectories = 1;
+ dwEmuleTags |= 4;
+ break;
++ //Bill Lee start
++ //Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ default: //if tag isn't those above, it may be used by leecher.
++ theDLP->CheckHelloTag(this, temptag.GetNameID());
++ dlp_nonofficialopcodes = true; //to detect Ghost Mod
++ break;
++ //Bill Lee end
++ #endif
+ }
+ }
+
+@@ -717,6 +732,11 @@
+ Kademlia::CKademlia::Bootstrap(wxUINT32_SWAP_ALWAYS(GetIP()), GetKadPort());
+ }
+
++ //Dynamic Leecher Protection - Bill Lee
++ #ifdef AMULE_DLP
++ theDLP->DLPCheck(this);
++ #endif
++
+ return bIsMule;
+ }
+
+@@ -972,6 +992,14 @@
+ % GetClientFullInfo()
+ );
+
++ //Bill Lee start
++ //Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ theDLP->CheckInfoTag(this, temptag.GetNameID());
++ dlp_nonofficialopcodes = true;
++ #endif
++ //Bill Lee end
++
+ break;
+ }
+ }
+@@ -1009,6 +1037,11 @@
+ m_byInfopacketsReceived |= IP_EMULEPROTPACK;
+ }
+
++ //Dynamic Leecher Protection - Added by Bill Lee
++ #ifdef AMULE_DLP
++ theDLP->DLPCheck(this);
++ #endif
++
+ return (protocol_version == 0xFF); // This was a OS_Info?
+ }
+
+@@ -2300,7 +2333,7 @@
+ }
+
+
+-#ifdef __DEBUG__
++//#ifdef __DEBUG__
+ wxString CUpDownClient::GetClientFullInfo()
+ {
+ if (m_clientVerString.IsEmpty()) {
+@@ -2315,7 +2348,7 @@
+ % m_clientVerString
+ % m_strModVersion;
+ }
+-#endif
++//#endif
+
+ wxString CUpDownClient::GetClientShortInfo()
+ {
+diff -Naur amule/src/CString_wx.h amule-dlp/src/CString_wx.h
+--- amule/src/CString_wx.h 1970-01-01 08:00:00.000000000 +0800
++++ amule-dlp/src/CString_wx.h 2015-06-19 13:34:36.355050365 +0800
+@@ -0,0 +1,59 @@
++/**
++ * Author: Bill Lee<bill.lee.y@gmail.com>
++ * License: GNU GPL
++ */
++//---------------------
++#ifndef CSTRING_WX_H
++#define CSTRING_WX_H
++
++//#include <wx/wx.h>
++#include <wx/string.h>
++
++class CString : public wxString{
++ public:
++ CString(){}
++ CString(wxChar c, size_t n=1): wxString(c, n){}
++ CString(const wxChar* str): wxString(str){}
++ CString(const wxString& str): wxString(str){}
++ CString(const CString& str): wxString(str){}
++ //---------------------
++ CString& operator=(const wxChar* str){
++ wxString::operator=(str);
++ return *this;
++ }
++ //operator*() from wxString;
++ size_t GetLength()const{ return Length(); }
++ wxChar GetAt(size_t nIndex)const{ return GetChar(nIndex); }
++ //IsEmpty() from wxString;
++ CString& TrimLeft(wxChar c){
++ size_t pos = find_first_not_of(c);
++ if(pos == 0)
++ return *this;
++ erase(0, pos);
++ return *this;
++ }
++ CString& TrimRight(wxChar c){
++ size_t pos = find_last_not_of(c) + 1;
++ if(pos == Length())
++ return *this;
++ erase(pos, Length() - pos);
++ return *this;
++ }
++ CString Trim(){
++ CString ret(*this);
++ ret.wxString::Trim(false); /* wxString::Trim(bool fromright = true) */
++ ret.wxString::Trim(true);
++ return ret;
++ }
++ //Find(wxChar) and Find(wxChar*) from wxString;
++ int Find(const CString& str)const{ return wxString::Find(str.c_str()); }
++ int ReverseFind(const wxChar c)const{ return wxString::Find(c, true); }
++ int ReverseFind(const wxChar* str)const{ return rfind(str); }
++ int ReverseFind(const CString& str)const{ return rfind(str); }
++ CString Right(size_t len)const{ return wxString::Right(len); }
++ CString Left(size_t len)const{ return wxString::Left(len); }
++ CString Mid(size_t first, size_t count = wxSTRING_MAXLEN)const{
++ return wxString::Mid(first, count);
++ }
++};
++#endif
+diff -Naur amule/src/DLP.cpp amule-dlp/src/DLP.cpp
+--- amule/src/DLP.cpp 1970-01-01 08:00:00.000000000 +0800
++++ amule-dlp/src/DLP.cpp 2015-06-19 14:25:16.000000000 +0800
+@@ -0,0 +1,190 @@
++// Copyright (C) 2011 Bill Lee <bill.lee.y@gmail.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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++//
++#include "Logger.h"
++
++#include "DLP.h"
++#include "antiLeech.h"
++#include <wx/dynlib.h> /* Needed for wxDynamicLibrary */
++
++#include "DLPPref.h"
++#include "Preferences.h" // Needed for CPreferences
++#include "amule.h" // Needed for theApp
++
++#include <wx/stdpaths.h> /* Needed for wxStandardPaths */
++
++#define PRE_CHECK(tag) if( (!c->IsBanned()) && antiLeech && (thePrefs::GetDLPCheckMask() & tagn) )
++
++void DLP::CheckHelloTag(CUpDownClient* c, UINT tagn){
++ PRE_CHECK(PF_HELLOTAG){
++ const wxChar* dlp_result = antiLeech->DLPCheckHelloTag(tagn);
++ if(dlp_result != NULL) {
++ wxString ret;
++ ret.Printf(_("[HelloTag %s] %s"), dlp_result, c->GetClientFullInfo().c_str());
++ //ret.Printf(_("[HelloTag %s] %s"), dlp_result, c->GetClientShortInfo().c_str());
++ c->Ban();
++ theApp->AddDLPMessageLine(ret);
++ }
++ }
++}
++
++void DLP::CheckInfoTag(CUpDownClient* c, UINT tagn){
++ PRE_CHECK(PF_INFOTAG){
++ const wxChar* dlp_result = antiLeech->DLPCheckInfoTag(tagn);
++ if(dlp_result != NULL) {
++ wxString ret;
++ ret.Printf(_("[InfoTag %s] %s"), dlp_result, c->GetClientFullInfo().c_str());
++ //ret.Printf(_("[InfoTag %s] %s"), dlp_result, c->GetClientShortInfo().c_str());
++ c->Ban();
++ theApp->AddDLPMessageLine(ret);
++ }
++ }
++}
++
++bool DLP::DLPCheck(CUpDownClient* c){
++ const wxChar* tmp = NULL;
++ wxString ret;
++
++ unsigned int prefs = thePrefs::GetDLPCheckMask();
++
++ CString modver(c->GetClientModString());
++ CString clientver(c->GetClientVerString());
++ CString uname(c->GetUserName());
++ CString uhash(wxString(c->GetUserHash().EncodeSTL().c_str(), wxConvUTF8));
++
++ //CheckGhostMod
++ if(prefs & PF_GHOSTMOD) {
++ if(c->HasNonOfficialOpCodes() && (modver.IsEmpty())) {
++ ret = _("GhostMod");
++ tmp = ret.c_str(); //char pointer
++ }
++ }
++
++ // Check bad modstring
++ if ((prefs & PF_MODSTRING) && (tmp == NULL)) {
++ if((tmp = antiLeech->DLPCheckModstring_Soft(modver.c_str(), clientver.c_str())) == NULL)
++ tmp = antiLeech->DLPCheckModstring_Hard(modver.c_str(), clientver.c_str());
++ }
++ /*
++ if ((prefs & PF_USERHASH) && (tmp == NULL)) {
++ // not finished
++ }
++ */
++ // Check bad username
++ if ((prefs & PF_USERNAME) && (tmp == NULL)) {
++ if ((tmp = antiLeech->DLPCheckNameAndHashAndMod(uname, uhash, modver)) == NULL){
++ if( (tmp = antiLeech->DLPCheckUsername_Hard(uname.c_str())) == NULL )
++ tmp = antiLeech->DLPCheckUsername_Soft(uname.c_str());
++ }
++ }
++
++
++ // Check VeryCD eMule
++ if ((prefs & PF_VERYCDEMULE) && (tmp == NULL)) {
++ if(modver.Find(wxT("VeryCD")) != wxNOT_FOUND){
++ ret = _("VeryCD Mod");
++ tmp = ret.c_str();
++ }
++ }
++
++ if (tmp != NULL) {
++ ret = tmp;
++ wxString wxInfo;
++ wxInfo.Printf(wxT("[%s] %s"), ret.c_str(), c->GetClientFullInfo().c_str());
++ //wxInfo.Printf(wxT("[%s] %s"), ret.c_str(), c->GetClientShortInfo().c_str());
++ c->Ban();
++ theApp->AddDLPMessageLine(wxInfo);
++ return true;
++ }
++
++ return false;
++
++}
++
++int DLP::ReloadAntiLeech(){
++ //Unloading
++ AddLogLineN( _("Checking if there is a antiLeech working..."));
++ if(antiLeechLib.IsLoaded()){
++ Destoryer fn = (Destoryer)(antiLeechLib.GetSymbol( wxT("destoryAntiLeechInstant")));
++ wxASSERT(fn);
++ AddLogLineN( _("Unload previous antiLeech..."));
++ fn(antiLeech);
++ antiLeech = NULL;
++ antiLeechLib.Unload();
++ }
++ else
++ AddLogLineN( _("No working antiLeech exists."));
++ //Get lib's location
++ wxStandardPathsBase &spb(wxStandardPaths::Get());
++#ifdef __WXMSW__
++ wxString dataDir(spb.GetPluginsDir());
++#elif defined(__WXMAC__)
++ wxString dataDir(spb.GetDataDir());
++#else
++ wxString dataDir(spb.GetDataDir().BeforeLast(wxT('/')) + wxT("/amule"));
++#endif
++ wxString localName = wxDynamicLibrary::CanonicalizeName(wxT("antiLeech"));
++ wxString systemwideFile(JoinPaths(dataDir, localName));
++ //wxString userFile(theApp->ConfigDir + localName);
++ wxString userFile(thePrefs::GetConfigDir() + localName);
++ wxString fallbackFile(wxT("antiLeech"));
++ //Try to load lib;
++ AddLogLineN( _("Trying to load antiLeech..."));
++ if( !LoadFrom(userFile) ){
++ if( !LoadFrom(systemwideFile) ){
++ if( !LoadFrom(fallbackFile) ){
++ AddLogLineC( _("No antiLeech available!"));
++ return 1; //Not found
++ }
++ }
++ }
++ //Searching symbol "createAntiLeechInstant"
++ Creator fn = (Creator)(antiLeechLib.GetSymbol( wxT("createAntiLeechInstant") ));
++ if(!fn){
++ antiLeechLib.Unload();
++ AddLogLineC( _("antiLeech found, but it seems not to be a valid antiLeech!"));
++ return 2; //Found, but isn't antiLeech
++ }
++ //Try to create antiLeech
++ antiLeech = fn();
++ if(antiLeech){
++ wxString logline;
++ logline.Printf(_("Succeed loading antiLeech! Version: %d"), antiLeech->GetDLPVersion());
++ AddLogLineC( logline);
++ return 0;
++ }
++ //else
++ antiLeechLib.Unload();
++ AddLogLineC( _("FAIL! An error occur when setting up antiLeech."));
++ return 3; //Fail to create antiLeech instant
++
++}
++
++DLP::~DLP(){
++ if(antiLeechLib.IsLoaded()){
++ Destoryer fn = (Destoryer)(antiLeechLib.GetSymbol( wxT("destoryAntiLeechInstant")));
++ wxASSERT(fn);
++ AddLogLineN( _("Unload previous antiLeech..."));
++ fn(antiLeech);
++ //antiLeech = NULL;
++ //antiLeechLib.Unload();
++ }
++}
++
++bool DLP::LoadFrom(wxString& file){
++ antiLeechLib.Load(file);
++ return antiLeechLib.IsLoaded();
++}
+diff -Naur amule/src/DLP.h amule-dlp/src/DLP.h
+--- amule/src/DLP.h 1970-01-01 08:00:00.000000000 +0800
++++ amule-dlp/src/DLP.h 2015-06-19 13:34:36.355050365 +0800
+@@ -0,0 +1,45 @@
++// Copyright (C) 2011 Bill Lee <bill.lee.y@gmail.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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++//
++
++class IantiLeech; //forward declaretion
++
++#include "updownclient.h" // Needed for CUpDownClient
++#include "antiLeech_wx.h"
++
++#include <wx/dynlib.h>
++
++class DLP
++{
++public:
++ DLP() : antiLeech(NULL) { ReloadAntiLeech(); }
++ ~DLP();
++
++ void CheckHelloTag(CUpDownClient*, UINT tagnumber);
++ void CheckInfoTag(CUpDownClient*, UINT tagnumber);
++ bool DLPCheck(CUpDownClient*);
++
++ int ReloadAntiLeech();
++
++private:
++ typedef IantiLeech* (*Creator)();
++ typedef int (*Destoryer)(IantiLeech*);
++
++ wxDynamicLibrary antiLeechLib;
++ IantiLeech* antiLeech;
++
++ bool LoadFrom(wxString& file);
++};
+diff -Naur amule/src/DLPPref.h amule-dlp/src/DLPPref.h
+--- amule/src/DLPPref.h 1970-01-01 08:00:00.000000000 +0800
++++ amule-dlp/src/DLPPref.h 2015-06-19 13:34:36.355050365 +0800
+@@ -0,0 +1,15 @@
++#ifndef ANTILEECH_AMULE_H
++#define ANTILEECH_AMULE_H
++
++/* Define DLPCheck prefs arg */
++#define PF_MODSTRING 0x1
++#define PF_USERHASH 0x2
++#define PF_USERNAME 0x4
++#define PF_HELLOTAG 0x8
++#define PF_INFOTAG 0x10
++#define PF_VERYCDEMULE 0x20
++//#define PF_EASYMULE 0x40
++//#define PF_MINIMULE 0x80
++#define PF_GHOSTMOD 0x100
++
++#endif
+diff -Naur amule/src/DownloadQueue.cpp amule-dlp/src/DownloadQueue.cpp
+--- amule/src/DownloadQueue.cpp 2015-06-19 14:46:14.944172083 +0800
++++ amule-dlp/src/DownloadQueue.cpp 2015-06-19 13:34:36.355050365 +0800
+@@ -623,6 +623,15 @@
+ return;
+ }
+
++ //Dynamic Leecher Protect - Bill Lee
++ #ifdef AMULE_DLP
++ if ( source->IsBanned() ){
++ source->Safe_Delete();
++ return;
++ }
++ #endif
++ //Bill Lee end
++
+ // Filter sources which are known to be dead/useless
+ if ( theApp->clientlist->IsDeadSource( source ) || sender->IsDeadSource(source) ) {
+ source->Safe_Delete();
+diff -Naur amule/src/ExternalConn.cpp amule-dlp/src/ExternalConn.cpp
+--- amule/src/ExternalConn.cpp 2015-06-19 14:46:14.944172083 +0800
++++ amule-dlp/src/ExternalConn.cpp 2015-06-19 13:34:36.359050198 +0800
+@@ -57,6 +57,9 @@
+ #include "kademlia/kademlia/UDPFirewallTester.h"
+ #include "Statistics.h"
+
++#ifdef AMULE_DLP
++#include "DLP.h"
++#endif
+
+ //-------------------- File_Encoder --------------------
+
+@@ -1378,6 +1381,15 @@
+ }
+ }
+ break;
++ //Dynamic Leech Protect - Bill Lee
++ #ifdef AMULE_DLP
++ case EC_OP_ANTILEECH_RELOAD:
++ if( theDLP->ReloadAntiLeech() )
++ response = new CECPacket(EC_OP_FAILED);
++ else
++ response = new CECPacket(EC_OP_NOOP);
++ break;
++ #endif
+ //
+ // Status requests
+ //
+diff -Naur amule/src/libs/ec/abstracts/ECCodes.abstract amule-dlp/src/libs/ec/abstracts/ECCodes.abstract
+--- amule/src/libs/ec/abstracts/ECCodes.abstract 2015-06-19 14:46:14.976170753 +0800
++++ amule-dlp/src/libs/ec/abstracts/ECCodes.abstract 2015-06-19 13:34:36.359050198 +0800
+@@ -148,6 +148,8 @@
+
+ EC_OP_FRIEND 0x57
+
++EC_OP_ANTILEECH_RELOAD 0x80
++
+ [/Section]
+
+ [Section Content]
+diff -Naur amule/src/libs/ec/cpp/ECCodes.h amule-dlp/src/libs/ec/cpp/ECCodes.h
+--- amule/src/libs/ec/cpp/ECCodes.h 2015-06-19 14:46:14.980170586 +0800
++++ amule-dlp/src/libs/ec/cpp/ECCodes.h 2015-06-19 13:34:36.363050032 +0800
+@@ -121,7 +121,8 @@
+ EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE = 0x54,
+ EC_OP_SHARED_FILE_SET_COMMENT = 0x55,
+ EC_OP_SERVER_SET_STATIC_PRIO = 0x56,
+- EC_OP_FRIEND = 0x57
++ EC_OP_FRIEND = 0x57,
++ EC_OP_ANTILEECH_RELOAD = 0x80
+ };
+
+ enum ECTagNames {
+@@ -554,6 +555,7 @@
+ case 0x55: return wxT("EC_OP_SHARED_FILE_SET_COMMENT");
+ case 0x56: return wxT("EC_OP_SERVER_SET_STATIC_PRIO");
+ case 0x57: return wxT("EC_OP_FRIEND");
++ case 0x80 : return wxT("EC_OP_ANTILEECH_RELOAD");
+ default: return CFormat(wxT("unknown %d 0x%x")) % arg % arg;
+ }
+ }
+diff -Naur amule/src/libs/ec/java/ECCodes.java amule-dlp/src/libs/ec/java/ECCodes.java
+--- amule/src/libs/ec/java/ECCodes.java 2015-06-19 14:46:14.980170586 +0800
++++ amule-dlp/src/libs/ec/java/ECCodes.java 2015-06-19 13:34:36.363050032 +0800
+@@ -112,6 +112,7 @@
+ public final static byte EC_OP_SHARED_FILE_SET_COMMENT = 0x55;
+ public final static byte EC_OP_SERVER_SET_STATIC_PRIO = 0x56;
+ public final static byte EC_OP_FRIEND = 0x57;
++public final static byte EC_OP_ANTILEECH_RELOAD = 0x80 ;
+
+ public final static short EC_TAG_STRING = 0x0000;
+ public final static short EC_TAG_PASSWD_HASH = 0x0001;
+diff -Naur amule/src/Makefile.am amule-dlp/src/Makefile.am
+--- amule/src/Makefile.am 2015-06-19 14:46:14.952171751 +0800
++++ amule-dlp/src/Makefile.am 2015-06-19 13:34:36.367049865 +0800
+@@ -178,6 +178,13 @@
+ kademlia/routing/RoutingZone.cpp
+
+
++#Dynamic Leecher Protection - Bill Lee
++if ENABLE_DLP
++core_sources += \
++ DLP.cpp
++AM_CPPFLAGS += -DAMULE_DLP
++endif
++
+ gui_sources = \
+ amule-gui.cpp \
+ amuleDlg.cpp \
+diff -Naur amule/src/muuli_wdr.cpp amule-dlp/src/muuli_wdr.cpp
+--- amule/src/muuli_wdr.cpp 2015-06-19 14:46:14.984170420 +0800
++++ amule-dlp/src/muuli_wdr.cpp 2015-06-19 13:35:05.817823798 +0800
+@@ -1769,6 +1769,51 @@
+ return item0;
+ }
+
++#ifdef AMULE_DLP
++wxSizer *PreferencesDLPTab( wxWindow *parent, bool call_fit, bool set_sizer )
++{
++ wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
++
++ wxButton* btnReload = new wxButton( parent, IDC_RELOADANTILEECH, _("Reload antiLeech"), wxDefaultPosition, wxDefaultSize, 0 ); //Bill Lee
++
++ wxStaticBox *item2 = new wxStaticBox( parent, -1, _("Dynamic Leecher Protection Options") );
++ wxStaticBoxSizer *item1 = new wxStaticBoxSizer( item2, wxVERTICAL );
++
++ wxCheckBox *item4 = new wxCheckBox( parent, IDC_CHECKMODSTRING, _("Check bad modstring"), wxDefaultPosition, wxDefaultSize, 0 );
++ item1->Add( item4, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxCheckBox *item5 = new wxCheckBox( parent, IDC_CHECKUSERNAME, _("Check bad username"), wxDefaultPosition, wxDefaultSize, 0 );
++ item1->Add( item5, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxCheckBox *item6 = new wxCheckBox( parent, IDC_CHECKUSERHASH, _("Check bad userhash"), wxDefaultPosition, wxDefaultSize, 0 );
++ item1->Add( item6, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxCheckBox *item7 = new wxCheckBox( parent, IDC_CHECKHELLOTAG, _("Check bad hello tag"), wxDefaultPosition, wxDefaultSize, 0 );
++ item1->Add( item7, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxCheckBox *item8 = new wxCheckBox( parent, IDC_CHECKINFOTAG, _("Check bad info tag"), wxDefaultPosition, wxDefaultSize, 0 );
++ item1->Add( item8, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxCheckBox *item9 = new wxCheckBox( parent, IDC_CHECKGHOSTMOD, _("Check ghost mod"), wxDefaultPosition, wxDefaultSize, 0);
++ item1->Add( item9, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxCheckBox *item10 = new wxCheckBox( parent, IDC_CHECKVERYCDMOD, _("Ban eMule VeryCD mod(Please consider carefully whether to use)"), wxDefaultPosition, wxDefaultSize, 0 ); //Modified by Bill Lee
++ item1->Add( item10, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ item0->Add( btnReload, 0, wxGROW|wxALL, 5); //Bill Lee
++ item0->Add( item1, 0, wxGROW|wxALL, 5 );
++
++ if (set_sizer)
++ {
++ parent->SetSizer( item0 );
++ if (call_fit)
++ item0->SetSizeHints( parent );
++ }
++
++ return item0;
++}
++#endif
++
+ wxSizer *PreferencesFilesTab( wxWindow *parent, bool call_fit, bool set_sizer )
+ {
+ wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
+@@ -2587,6 +2632,42 @@
+ return item0;
+ }
+
++wxSizer *DLPInfoLog( wxWindow *parent, bool call_fit, bool set_sizer )
++{
++ wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
++
++ wxBoxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
++
++ wxStaticBitmap *item2 = new wxStaticBitmap( parent, -1, amuleDlgImages( 3 ), wxDefaultPosition, wxDefaultSize );
++ item2->SetToolTip( _("Display DLP log") );
++ item1->Add( item2, 0, wxALIGN_CENTER|wxALL, 5 );
++
++ wxStaticText *item3 = new wxStaticText( parent, -1, _("DLP Info"), wxDefaultPosition, wxDefaultSize, 0 );
++ item1->Add( item3, 0, wxALIGN_CENTER|wxALL, 5 );
++
++ item0->Add( item1, 0, wxALIGN_CENTER_VERTICAL, 5 );
++
++ wxBoxSizer *item4 = new wxBoxSizer( wxHORIZONTAL );
++
++ CMuleTextCtrl *item5 = new CMuleTextCtrl( parent, ID_DLPINFO, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxVSCROLL );
++ item4->Add( item5, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL, 5 );
++
++ wxButton *item6 = new wxButton( parent, ID_BTN_RESET_DLP, _("Reset"), wxDefaultPosition, wxDefaultSize, 0 );
++ item6->SetToolTip( _("Click this button to reset the log.") );
++ item4->Add( item6, 0, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
++
++ item0->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
++
++ if (set_sizer)
++ {
++ parent->SetSizer( item0 );
++ if (call_fit)
++ item0->SetSizeHints( parent );
++ }
++
++ return item0;
++}
++
+ wxSizer *serverListDlgDown( wxWindow *parent, bool call_fit, bool set_sizer )
+ {
+ wxStaticBox *item1 = new wxStaticBox( parent, -1, wxT("") );
+@@ -2602,7 +2683,7 @@
+ wxPanel *item4 = new wxPanel( item3, -1 );
+ aMuleLog( item4, FALSE );
+ item3->AddPage( item4, _("aMule Log") );
+-
++
+ wxPanel *item5 = new wxPanel( item3, -1 );
+ ServerInfoLog( item5, FALSE );
+ item3->AddPage( item5, _("Server Info") );
+@@ -2614,6 +2695,10 @@
+ wxPanel *item7 = new wxPanel( item3, -1 );
+ Kad_Info( item7, FALSE );
+ item3->AddPage( item7, _("Kad Info") );
++
++ wxPanel *item8 = new wxPanel( item3, -1);
++ DLPInfoLog( item8, FALSE);
++ item3->AddPage(item8, _("DLP Info"));
+
+ item0->Add( item2, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
+
+diff -Naur amule/src/muuli_wdr.h amule-dlp/src/muuli_wdr.h
+--- amule/src/muuli_wdr.h 2015-06-19 14:46:14.984170420 +0800
++++ amule-dlp/src/muuli_wdr.h 2015-06-19 13:35:05.817823798 +0800
+@@ -335,6 +335,10 @@
+ #define ID_BTN_RESET_SERVER 10240
+ wxSizer *ServerInfoLog( wxWindow *parent, bool call_fit = TRUE, bool set_sizer = TRUE );
+
++#define ID_DLPINFO 22001
++#define ID_BTN_RESET_DLP 22002
++wxSizer *DLPInfoLog( wxWindow *parent, bool call_fit = TRUE, bool set_sizer = TRUE );
++
+ #define ID_LOGVIEW 10241
+ #define ID_BTN_RESET 10242
+ wxSizer *aMuleLog( wxWindow *parent, bool call_fit = TRUE, bool set_sizer = TRUE );
+@@ -424,6 +428,21 @@
+ #define ID_DEBUGCATS 10307
+ wxSizer *PreferencesDebug( wxWindow *parent, bool call_fit = TRUE, bool set_sizer = TRUE );
+
++/* Dynamic Leecher Protection */
++#define IDC_CHECKMODSTRING 11001
++#define IDC_CHECKUSERNAME 11002
++#define IDC_CHECKUSERHASH 11003
++#define IDC_CHECKHELLOTAG 11004
++#define IDC_CHECKINFOTAG 11005
++#define IDC_CHECKEASYMULE 11006
++#define IDC_CHECKVERYCDMOD 11007
++#define IDC_CHECKMINIMULE 11008
++#define IDC_CHECKGHOSTMOD 11009
++#ifdef AMULE_DLP
++#define IDC_RELOADANTILEECH 11010 //Bill Lee
++wxSizer *PreferencesDLPTab( wxWindow *parent, bool call_fit = TRUE, bool set_sizer = TRUE );
++#endif
++
+ extern wxSizer *IDC_CURJOB;
+ #define IDC_CONV_PB_LABEL 10308
+ #define IDC_CONV_PROZENT 10309
+diff -Naur amule/src/Preferences.cpp amule-dlp/src/Preferences.cpp
+--- amule/src/Preferences.cpp 2015-06-19 14:46:14.956171584 +0800
++++ amule-dlp/src/Preferences.cpp 2015-06-19 13:35:05.817823798 +0800
+@@ -51,6 +51,11 @@
+
+ #include "UserEvents.h"
+
++#ifdef AMULE_DLP
++#include "DLPPref.h"
++#include "antiLeech.h"
++#endif
++
+ #ifndef AMULE_DAEMON
+ #include <wx/valgen.h>
+ #include "muuli_wdr.h"
+@@ -343,6 +348,19 @@
+ wxWindow* m_widget;
+ };
+
++/* Dynamic Leecher Protection */
++#ifdef AMULE_DLP
++bool CPreferences::s_DLPCheckModString;
++bool CPreferences::s_DLPCheckUsername;
++bool CPreferences::s_DLPCheckUserHash;
++bool CPreferences::s_DLPCheckHelloTag;
++bool CPreferences::s_DLPCheckInfoTag;
++//bool CPreferences::s_DLPCheckEasyMule;
++bool CPreferences::s_DLPCheckVeryCDMod;
++//bool CPreferences::s_DLPCheckminiMule; //Added by Bill Lee
++bool CPreferences::s_DLPCheckGhostMod;
++unsigned int CPreferences::s_DLPCheckMask;
++#endif
+
+ /** Cfg class for wxStrings. */
+ class Cfg_Str : public Cfg_Tmpl<wxString>
+@@ -952,6 +970,11 @@
+ s_userhash[5] = 14;
+ s_userhash[14] = 111;
+
++ // Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ CalcDLPCheckMask();
++ #endif
++
+ #ifndef CLIENT_GUI
+ LoadPreferences();
+ ReloadSharedFolders();
+@@ -1061,6 +1084,20 @@
+ NewCfgItem( IDC_NETWORKKAD, (new Cfg_Bool( wxT("/eMule/ConnectToKad"), s_ConnectToKad, true )) );
+ NewCfgItem( IDC_NETWORKED2K, ( new Cfg_Bool( wxT("/eMule/ConnectToED2K"), s_ConnectToED2K, true ) ));
+
++ /**
++ * Dynamic Leecher Protection
++ **/
++ #ifdef AMULE_DLP
++ NewCfgItem(IDC_CHECKMODSTRING, (new Cfg_Bool( wxT("/DLP/CheckModString"), s_DLPCheckModString, true )));
++ NewCfgItem(IDC_CHECKUSERNAME, (new Cfg_Bool( wxT("/DLP/CheckUsername"), s_DLPCheckUsername, true )));
++ NewCfgItem(IDC_CHECKUSERHASH, (new Cfg_Bool( wxT("/DLP/CheckUserHash"), s_DLPCheckUserHash, true )));
++ NewCfgItem(IDC_CHECKHELLOTAG, (new Cfg_Bool( wxT("/DLP/CheckHelloTag"), s_DLPCheckHelloTag, true )));
++ NewCfgItem(IDC_CHECKINFOTAG, (new Cfg_Bool( wxT("/DLP/CheckInfoTag"), s_DLPCheckInfoTag, true )));
++ //NewCfgItem(IDC_CHECKEASYMULE, (new Cfg_Bool( wxT("/DLP/CheckEasyMule"), s_DLPCheckEasyMule, true ))); //Modified by Bill Lee
++ NewCfgItem(IDC_CHECKVERYCDMOD, (new Cfg_Bool( wxT("/DLP/CheckVeryCDMod"), s_DLPCheckVeryCDMod, false )));
++ //NewCfgItem(IDC_CHECKMINIMULE, (new Cfg_Bool( wxT("/DLP/CheckminiMule"), s_DLPCheckminiMule, true))); //Added by Bill Lee
++ NewCfgItem(IDC_CHECKGHOSTMOD, (new Cfg_Bool( wxT("/DLP/CheckGhostMod"), s_DLPCheckGhostMod, true ))); //Added by Bill Lee.
++ #endif
+
+ /**
+ * Files
+@@ -1469,6 +1506,11 @@
+ }
+
+ SavePreferences();
++
++ // Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ CalcDLPCheckMask();
++ #endif
+
+ #ifndef CLIENT_GUI
+ CTextFile sdirfile;
+@@ -1481,6 +1523,21 @@
+ #endif
+ }
+
++#ifdef AMULE_DLP
++void CPreferences::CalcDLPCheckMask()
++{
++ s_DLPCheckMask = 0;
++ if (s_DLPCheckModString) s_DLPCheckMask |= PF_MODSTRING;
++ if (s_DLPCheckUsername) s_DLPCheckMask |= PF_USERNAME;
++ if (s_DLPCheckUserHash) s_DLPCheckMask |= PF_USERHASH;
++ if (s_DLPCheckHelloTag) s_DLPCheckMask |= PF_HELLOTAG;
++ if (s_DLPCheckInfoTag) s_DLPCheckMask |= PF_INFOTAG;
++ if (s_DLPCheckGhostMod) s_DLPCheckMask |= PF_GHOSTMOD;
++ //if (s_DLPCheckEasyMule) s_DLPCheckMask |= PF_EASYMULE;
++ if (s_DLPCheckVeryCDMod) s_DLPCheckMask |= PF_VERYCDEMULE;
++ //if (s_DLPCheckminiMule) s_DLPCheckMask |= PF_MINIMULE; //Added by Bill Lee
++}
++#endif
+
+ CPreferences::~CPreferences()
+ {
+diff -Naur amule/src/Preferences.h amule-dlp/src/Preferences.h
+--- amule/src/Preferences.h 2015-06-19 14:46:14.956171584 +0800
++++ amule-dlp/src/Preferences.h 2015-06-19 13:35:05.821823631 +0800
+@@ -574,6 +574,11 @@
+ // Sleep
+ static bool GetPreventSleepWhileDownloading() { return s_preventSleepWhileDownloading; }
+ static void SetPreventSleepWhileDownloading(bool status) { s_preventSleepWhileDownloading = status; }
++
++ // Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ static unsigned int GetDLPCheckMask() {return s_DLPCheckMask;}
++ #endif
+ protected:
+ static int32 GetRecommendedMaxConnections();
+
+@@ -594,6 +599,11 @@
+ private:
+ void LoadPreferences();
+ void SavePreferences();
++
++ // Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ void CalcDLPCheckMask();
++ #endif
+
+ protected:
+ static wxString s_configDir;
+@@ -807,6 +817,20 @@
+ // Stats server
+ static wxString s_StatsServerName;
+ static wxString s_StatsServerURL;
++
++ // Dynamic Leecher Protection
++ #ifdef AMULE_DLP
++ static bool s_DLPCheckModString;
++ static bool s_DLPCheckUsername;
++ static bool s_DLPCheckUserHash;
++ static bool s_DLPCheckHelloTag;
++ static bool s_DLPCheckInfoTag;
++ //static bool s_DLPCheckEasyMule;
++ static bool s_DLPCheckVeryCDMod;
++ //static bool s_DLPCheckminiMule; //Added by Bill Lee
++ static bool s_DLPCheckGhostMod; //Added by Bill Lee
++ static unsigned int s_DLPCheckMask;
++ #endif
+ };
+
+
+diff -Naur amule/src/PrefsUnifiedDlg.cpp amule-dlp/src/PrefsUnifiedDlg.cpp
+--- amule/src/PrefsUnifiedDlg.cpp 2015-06-19 14:46:14.956171584 +0800
++++ amule-dlp/src/PrefsUnifiedDlg.cpp 2015-06-19 13:35:05.821823631 +0800
+@@ -53,6 +53,11 @@
+ #include "UserEvents.h"
+ #include "PlatformSpecific.h" // Needed for PLATFORMSPECIFIC_CAN_PREVENT_SLEEP_MODE
+
++//Dynamic Leech Protect - Bill Lee
++#ifdef AMULE_DLP
++#include "DLP.h"
++#endif
++
+ BEGIN_EVENT_TABLE(PrefsUnifiedDlg,wxDialog)
+ // Events
+ #define USEREVENTS_EVENT(ID, NAME, VARS) \
+@@ -114,6 +119,11 @@
+ EVT_CHOICE(IDC_COLORSELECTOR, PrefsUnifiedDlg::OnColorCategorySelected)
+ EVT_LIST_ITEM_SELECTED(ID_PREFSLISTCTRL,PrefsUnifiedDlg::OnPrefsPageChange)
+
++ //Dynamic Leech Protect - Bill Lee
++ #ifdef AMULE_DLP
++ EVT_BUTTON(IDC_RELOADANTILEECH, PrefsUnifiedDlg::OnButtonReloadAntiLeech)
++ #endif
++
+ EVT_INIT_DIALOG(PrefsUnifiedDlg::OnInitDialog)
+
+ EVT_COMMAND_SCROLL(IDC_SLIDER, PrefsUnifiedDlg::OnScrollBarChange)
+@@ -187,6 +197,9 @@
+ { wxTRANSLATE("Online Signature"), PreferencesOnlineSigTab, 21 },
+ { wxTRANSLATE("Advanced"), PreferencesaMuleTweaksTab, 12 },
+ { wxTRANSLATE("Events"), PreferencesEventsTab, 5 }
++#ifdef AMULE_DLP
++ ,{ wxTRANSLATE("DLP"), PreferencesDLPTab, 5}
++#endif
+ #ifdef __DEBUG__
+ ,{ wxTRANSLATE("Debugging"), PreferencesDebug, 25 }
+ #endif
+@@ -1076,6 +1089,21 @@
+ theApp->ipfilter->Update( CastChild( IDC_IPFILTERURL, wxTextCtrl )->GetValue() );
+ }
+
++//Bill Lee
++#ifdef AMULE_DLP
++void PrefsUnifiedDlg::OnButtonReloadAntiLeech(wxCommandEvent& WXUNUSED(event)){
++ #ifndef CLIENT_GUI
++ if( theDLP->ReloadAntiLeech() )
++ wxMessageBox(_("Cannot load antiLeech!"), _("Message"), wxOK | wxICON_EXCLAMATION, this);
++ else
++ wxMessageBox(_("Succeed loading antiLeech!"), _("Message"), wxOK | wxICON_INFORMATION, this);
++ #else
++ AddLogLineN(_("Reload antiLeech from remote GUI has not been implemented."));
++ wxMessageBox(_("Sorry, it has not been implemented yet!"));
++ #endif
++}
++#endif
++
+
+ void PrefsUnifiedDlg::OnPrefsPageChange(wxListEvent& event)
+ {
+diff -Naur amule/src/PrefsUnifiedDlg.h amule-dlp/src/PrefsUnifiedDlg.h
+--- amule/src/PrefsUnifiedDlg.h 2015-06-19 14:46:14.956171584 +0800
++++ amule-dlp/src/PrefsUnifiedDlg.h 2015-06-19 13:35:05.821823631 +0800
+@@ -124,6 +124,9 @@
+ void OnUserEventSelected(wxListEvent& event);
+ void OnLanguageChoice(wxCommandEvent &event);
+ void CreateEventPanels(const int idx, const wxString& vars, wxWindow* parent);
++ #ifdef AMULE_DLP
++ void OnButtonReloadAntiLeech(wxCommandEvent &event); /* Dynamic Leech Protect - Bill Lee */
++ #endif
+
+ void OnInitDialog( wxInitDialogEvent& evt );
+
+diff -Naur amule/src/ServerWnd.cpp amule-dlp/src/ServerWnd.cpp
+--- amule/src/ServerWnd.cpp 2015-06-19 14:46:14.964171252 +0800
++++ amule-dlp/src/ServerWnd.cpp 2015-06-19 13:35:05.825823465 +0800
+@@ -45,6 +45,7 @@
+ EVT_BUTTON(ID_BTN_RESET, CServerWnd::OnBnClickedResetLog)
+ EVT_BUTTON(ID_BTN_RESET_SERVER, CServerWnd::OnBnClickedResetServerLog)
+ EVT_SPLITTER_SASH_POS_CHANGED(ID_SRV_SPLITTER,CServerWnd::OnSashPositionChanged)
++ EVT_BUTTON(ID_BTN_RESET_DLP, CServerWnd::OnBnClickedResetDLPLog)
+ END_EVENT_TABLE()
+
+
+@@ -151,6 +152,11 @@
+ theApp->GetServerLog(true); // Reset it
+ }
+
++void CServerWnd::OnBnClickedResetDLPLog(wxCommandEvent& WXUNUSED(evt))
++{
++ wxTextCtrl* cv= CastByID( ID_DLPINFO, this, wxTextCtrl );
++ cv->Clear();
++}
+
+ void CServerWnd::UpdateED2KInfo()
+ {
+diff -Naur amule/src/ServerWnd.h amule-dlp/src/ServerWnd.h
+--- amule/src/ServerWnd.h 2015-06-19 14:46:14.964171252 +0800
++++ amule-dlp/src/ServerWnd.h 2015-06-19 13:35:05.825823465 +0800
+@@ -50,6 +50,7 @@
+ void OnBnClickedUpdateservermetfromurl(wxCommandEvent& evt);
+ void OnBnClickedResetLog(wxCommandEvent& evt);
+ void OnBnClickedResetServerLog(wxCommandEvent& evt);
++ void OnBnClickedResetDLPLog(wxCommandEvent& evt);
+
+ DECLARE_EVENT_TABLE()
+ };
+diff -Naur amule/src/TextClient.cpp amule-dlp/src/TextClient.cpp
+--- amule/src/TextClient.cpp 2015-06-19 14:46:14.964171252 +0800
++++ amule-dlp/src/TextClient.cpp 2015-06-19 13:35:05.829823298 +0800
+@@ -76,6 +76,7 @@
+ CMD_ID_RELOAD_SHARED,
+ CMD_ID_RELOAD_IPFILTER_LOCAL,
+ CMD_ID_RELOAD_IPFILTER_NET,
++ CMD_ID_RELOAD_ANTILEECH, /* Only used internally - Dynamic Leech Protect - Bill Lee */
+ CMD_ID_SET_IPFILTER_ON,
+ CMD_ID_SET_IPFILTER_OFF,
+ CMD_ID_SET_IPFILTER_CLIENTS_ON,
+@@ -109,7 +110,6 @@
+ CMD_ID_DOWNLOAD,
+ // IDs for deprecated commands
+ CMD_ID_SET_IPFILTER
+-
+ };
+
+ // method to create a SearchFile
+@@ -243,6 +243,12 @@
+ case CMD_ID_DISCONNECT_KAD:
+ request_list.push_back(new CECPacket(EC_OP_KAD_STOP));
+ break;
++ //Dynamic Leech Protect - Bill Lee
++ #ifdef AMULE_DLP
++ case CMD_ID_RELOAD_ANTILEECH:
++ request_list.push_back(new CECPacket(EC_OP_ANTILEECH_RELOAD));
++ break;
++ #endif
+
+ case CMD_ID_RELOAD_SHARED:
+ request_list.push_back(new CECPacket(EC_OP_SHAREDFILES_RELOAD));
+@@ -906,6 +912,9 @@
+ tmp2->AddCommand(wxT("Net"), CMD_ID_RELOAD_IPFILTER_NET, wxTRANSLATE("Update IP filtering table from URL."),
+ wxTRANSLATE("If URL is omitted the URL from the preferences is used."), CMD_PARAM_OPTIONAL);
+
++ #ifdef AMULE_DLP
++ tmp->AddCommand(wxT("AntiLeech"), CMD_ID_RELOAD_ANTILEECH, wxTRANSLATE("Reloads antiLeech."), wxEmptyString, CMD_PARAM_NEVER); //Bill Lee
++ #endif
+ tmp = m_commands.AddCommand(wxT("Connect"), CMD_ID_CONNECT, wxTRANSLATE("Connect to the network."),
+ wxTRANSLATE("This will connect to all networks that are enabled in Preferences.\nYou may also optionally specify a server address in IP:Port form, to connect to\nthat server only. The IP must be a dotted decimal IPv4 address,\nor a resolvable DNS name."), CMD_PARAM_OPTIONAL);
+ tmp->AddCommand(wxT("ED2K"), CMD_ID_CONNECT_ED2K, wxTRANSLATE("Connect to eD2k only."), wxEmptyString, CMD_PARAM_NEVER);
+diff -Naur amule/src/updownclient.h amule-dlp/src/updownclient.h
+--- amule/src/updownclient.h 2015-06-19 14:46:15.000169755 +0800
++++ amule-dlp/src/updownclient.h 2015-06-19 14:30:45.000000000 +0800
+@@ -408,7 +408,8 @@
+ bool GetSentCancelTransfer() const { return m_fSentCancelTransfer; }
+ void SetSentCancelTransfer(bool bVal) { m_fSentCancelTransfer = bVal; }
+
+- DEBUG_ONLY( wxString GetClientFullInfo(); )
++ //DEBUG_ONLY( wxString GetClientFullInfo(); )
++ wxString GetClientFullInfo();
+ wxString GetClientShortInfo();
+
+ const wxString& GetClientOSInfo() const { return m_sClientOSInfo; }
+@@ -581,7 +582,10 @@
+ bool ShouldReceiveCryptUDPPackets() const;
+
+ bool HasDisabledSharedFiles() const { return m_fNoViewSharedFiles; }
+-
++ #ifdef AMULE_DLP
++ bool HasNonOfficialOpCodes() const { return dlp_nonofficialopcodes; } //Dynamic Leecher Protection - Bill Lee
++ #endif
++
+ private:
+
+ CClientCredits *credits;
+@@ -842,6 +846,10 @@
+ #ifdef __DEBUG__
+ wxString connection_reason;
+ #endif
++
++ #ifdef AMULE_DLP
++ bool dlp_nonofficialopcodes; //Dynamic Leecher Protect - Bill Lee
++ #endif
+ };
+
+
+diff -Naur amule/src/UploadQueue.cpp amule-dlp/src/UploadQueue.cpp
+--- amule/src/UploadQueue.cpp 2015-06-19 14:46:14.964171252 +0800
++++ amule-dlp/src/UploadQueue.cpp 2015-06-19 13:35:05.833823132 +0800
+@@ -390,6 +390,11 @@
+ return;
+ }
+
++ //Dynamic Leecher Protect - Bill Lee
++ #if defined AMULE_DLP && defined __DEBUG__
++ AddLogLineN(client->GetClientFullInfo());
++ #endif
++
+ client->AddAskedCount();
+ client->SetLastUpRequest();
+
diff --git a/amule.install b/amule.install
new file mode 100644
index 000000000000..62dab1173f33
--- /dev/null
+++ b/amule.install
@@ -0,0 +1,29 @@
+post_install() {
+ post_upgrade
+ passwd -l amule &>/dev/null
+}
+
+_config_instructions() {
+ echo "If you plan to use external client (e.g. amuleGUI or amuleweb) then you need to"
+ echo "provide [ExternalConnect] configuration."
+ echo "You also need to specify amuleweb password."
+ echo "Please follow https://wiki.archlinux.org/index.php/AMule for more information."
+ echo "amuleweb can be started as 'systemctl start amuleweb'."
+}
+
+post_upgrade() {
+ # create user/group that the daemon will run as by default, do not delete this on uninstall, as it will own files
+ getent group amule >/dev/null || groupadd amule
+ getent passwd amule >/dev/null || useradd -c 'aMule Client' -g amule -d '/var/lib/amule' -m -s /bin/false amule
+
+ if [ ! -e /var/lib/amule/.aMule/amule.conf ]; then
+ _config_instructions
+ fi
+}
+
+post_remove() {
+ # TOTHINK: delete homedir and user account/group?
+ #getent passwd amule >/dev/null && userdel amule
+ #getent group amule >/dev/null && groupdel amule
+ true
+}
diff --git a/amuled.systemd b/amuled.systemd
new file mode 100644
index 000000000000..e1878dfd9759
--- /dev/null
+++ b/amuled.systemd
@@ -0,0 +1,11 @@
+[Unit]
+Description=aMule Daemon
+After=network.target
+
+# This assumes that a user 'amule' exists, with a writeable home directory
+[Service]
+User=amule
+ExecStart=/usr/bin/amuled
+
+[Install]
+WantedBy=multi-user.target
diff --git a/amuleweb.systemd b/amuleweb.systemd
new file mode 100644
index 000000000000..1799f4ae88c0
--- /dev/null
+++ b/amuleweb.systemd
@@ -0,0 +1,13 @@
+[Unit]
+Description=aMule Webserver
+Requires=amuled.service
+
+[Service]
+User=amule
+ExecStart=/usr/bin/amuleweb --quiet
+# If amuled still starting then amuleweb exits, restart until amuleweb is up
+Restart=on-success
+RestartSec=3s
+
+[Install]
+WantedBy=multi-user.target