diff --git a/src/Ghosts.Client/Ghosts.Client.csproj b/src/Ghosts.Client/Ghosts.Client.csproj index 38d21d88..6a4ea108 100755 --- a/src/Ghosts.Client/Ghosts.Client.csproj +++ b/src/Ghosts.Client/Ghosts.Client.csproj @@ -95,6 +95,9 @@ ..\packages\FileHelpers.3.4.1\lib\net45\FileHelpers.dll + + ..\packages\HtmlAgilityPack.1.11.45\lib\Net45\HtmlAgilityPack.dll + lib\Interop.ProfMan.dll True diff --git a/src/Ghosts.Client/Handlers/Outlook.cs b/src/Ghosts.Client/Handlers/Outlook.cs index 63903cf0..08003862 100755 --- a/src/Ghosts.Client/Handlers/Outlook.cs +++ b/src/Ghosts.Client/Handlers/Outlook.cs @@ -11,6 +11,8 @@ using System.Linq; using System.Reflection; using System.Threading; +using Ghosts.Domain.Code.Helpers; +using NetOffice.ExcelApi.Enums; using Exception = System.Exception; using MAPIFolder = Microsoft.Office.Interop.Outlook.MAPIFolder; @@ -132,6 +134,19 @@ public void ExecuteEvents(TimelineHandler handler) Log.Error(e); } break; + case "CLICKRANDOMLINK": + try + { + if (ClickRandomLink(timelineEvent)) + { + Report(handler.HandlerType.ToString(), timelineEvent.Command, string.Join(",", timelineEvent.CommandArgs)); + } + } + catch (Exception e) + { + Log.Error(e); + } + break; } if (timelineEvent.DelayAfter > 0) @@ -147,6 +162,36 @@ public void ExecuteEvents(TimelineHandler handler) } } + private bool ClickRandomLink(TimelineEvent timelineEvent) + { + try + { + var folderItemsRaw = _folderInbox.Items; + var folderItems = new List(); + foreach (MailItem folderItem in folderItemsRaw) + { + folderItems.Add(folderItem); + } + + var filteredEmails = folderItems.Where(x => x.BodyFormat == OlBodyFormat.olFormatHTML && x.HTMLBody.Contains("'", - "Random+Parent - format is reply then original message", - "Parent - format of original message", - "" - ], - "DelayAfter": 900000, - "DelayBefore": 0 - } + { + "Command": "reply", + "CommandArgs": [ + "CurrentUser", + "All - reply to all", + "All", + "All", + "Parent - format is 'RE: '", + "Random+Parent - format is reply then original message", + "Parent - format of original message", + "" + ], + "DelayAfter": 900000, + "DelayBefore": 0 + }, + { + "Command": "clickrandomlink", + "CommandArgs": [], + "DelayAfter": 900000, + "DelayBefore": 0 + } ] }, { @@ -61,21 +67,27 @@ "DelayAfter": 900000, "DelayBefore": 0 }, - { - "Command": "reply", - "CommandArgs": [ - "CurrentUser", - "All", - "All", - "All", - "Parent", - "Parent+Random", - "Parent", - "" - ], - "DelayAfter": 900000, - "DelayBefore": 0 - } + { + "Command": "reply", + "CommandArgs": [ + "CurrentUser", + "All", + "All", + "All", + "Parent", + "Parent+Random", + "Parent", + "" + ], + "DelayAfter": 900000, + "DelayBefore": 0 + }, + { + "Command": "clickrandomlink", + "CommandArgs": [], + "DelayAfter": 900000, + "DelayBefore": 0 + } ] } ] diff --git a/src/Ghosts.Client/packages.config b/src/Ghosts.Client/packages.config index e7dc2544..ec8d0bbe 100644 --- a/src/Ghosts.Client/packages.config +++ b/src/Ghosts.Client/packages.config @@ -6,6 +6,7 @@ + diff --git a/src/Ghosts.Domain/Code/ApplicationDetails.cs b/src/Ghosts.Domain/Code/ApplicationDetails.cs index ca0cc04d..9348d484 100755 --- a/src/Ghosts.Domain/Code/ApplicationDetails.cs +++ b/src/Ghosts.Domain/Code/ApplicationDetails.cs @@ -99,6 +99,8 @@ public static class ConfigurationFiles public static string Health => Clean(Path + "health.json"); public static string Timeline => Clean(Path + "timeline.json"); + public static string DenyList => Clean(Path + "denylist.txt"); + public static string EmailContent(string raw) => Determine(raw, "email-content.csv"); public static string EmailReply(string raw) => Determine(raw, "email-reply.csv"); public static string EmailDomain(string raw) => Determine(raw, "emails-domain.json"); diff --git a/src/Ghosts.Domain/Code/DenyListManager.cs b/src/Ghosts.Domain/Code/DenyListManager.cs new file mode 100644 index 00000000..f6d09ecf --- /dev/null +++ b/src/Ghosts.Domain/Code/DenyListManager.cs @@ -0,0 +1,49 @@ +// Copyright 2017 Carnegie Mellon University. All Rights Reserved. See LICENSE.md file for terms. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Ghosts.Domain.Code.Helpers; +using NLog; + +namespace Ghosts.Domain.Code +{ + public static class DenyListManager + { + private static readonly Logger _log = LogManager.GetCurrentClassLogger(); + + public static IEnumerable Load() + { + try + { + return File.ReadAllLines(ApplicationDetails.ConfigurationFiles.DenyList); + } + catch (Exception e) + { + _log.Trace(e); + return new List(); + } + } + + public static bool IsInList(string item) + { + var list = Load(); + return list.Any(x => x.StartsWith(item.GetUriHost(), StringComparison.InvariantCultureIgnoreCase)); + } + + public static IEnumerable ScrubList(IEnumerable list) + { + var denyList = Load(); + var filteredList = new List(); + foreach (var item in list) + { + if (!denyList.Any(x => x.StartsWith(item.GetUriHost(), StringComparison.InvariantCultureIgnoreCase))) + { + filteredList.Add(item); + } + } + return filteredList; + } + } +} diff --git a/src/Ghosts.Domain/Code/Helpers/UriExtensions.cs b/src/Ghosts.Domain/Code/Helpers/UriExtensions.cs index 61302a96..c7c50773 100644 --- a/src/Ghosts.Domain/Code/Helpers/UriExtensions.cs +++ b/src/Ghosts.Domain/Code/Helpers/UriExtensions.cs @@ -1,6 +1,10 @@ // Copyright 2017 Carnegie Mellon University. All Rights Reserved. See LICENSE.md file for terms. using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using HtmlAgilityPack; namespace Ghosts.Domain.Code.Helpers { @@ -11,5 +15,44 @@ public static string GetDomain(this Uri uri) var a = uri.Host.Split('.'); return a.GetUpperBound(0) < 2 ? uri.Host : $"{a[a.GetUpperBound(0) - 1]}.{a[a.GetUpperBound(0)]}"; } + + public static string GetUriHost(this string uriString) + { + try + { + if (!uriString.Contains(Uri.SchemeDelimiter)) + { + uriString = string.Concat(Uri.UriSchemeHttp, Uri.SchemeDelimiter, uriString); + } + return new Uri(uriString).Host; + } + catch (Exception e) + { + Console.WriteLine(e); + return uriString; + } + } + + public static IEnumerable GetHrefUrls(this string input) + { + var doc = new HtmlDocument(); + doc.LoadHtml(input); + + return doc.DocumentNode.SelectNodes("//a[@href]")//this xpath selects all anchor tags + .Select(p => p.Attributes["href"].Value); + } + + //TODO:clean this up + public static void OpenUrl(this string url) + { + try + { + Process.Start(url); + } + catch + { + //ignore + } + } } } diff --git a/src/Ghosts.Domain/config/denylist.txt b/src/Ghosts.Domain/config/denylist.txt new file mode 100644 index 00000000..90512e5c --- /dev/null +++ b/src/Ghosts.Domain/config/denylist.txt @@ -0,0 +1,3 @@ +herein_lies_the_format_of_the_deny_list.org +we_can_deny_entire_domains.com +or_some_subnet.of_some_domain.net diff --git a/src/Ghosts.Domain/ghosts.domain.csproj b/src/Ghosts.Domain/ghosts.domain.csproj index c878f917..7d079df2 100755 --- a/src/Ghosts.Domain/ghosts.domain.csproj +++ b/src/Ghosts.Domain/ghosts.domain.csproj @@ -15,17 +15,17 @@ + - + - - - - + + PreserveNewest + PreserveNewest