Browse Source

Fixed tracking not recording correct IP.

tags/2.0.3
Teknikode 4 years ago
parent
commit
090cf9f5b7

+ 3
- 3
Teknik/Areas/API/Controllers/APIv1Controller.cs View File

@@ -31,7 +31,7 @@ namespace Teknik.Areas.API.Controllers
{
try
{
Tracking.TrackPageView(Request, "Upload", Subdomain);
Tracking.TrackPageView(Request, "Upload");
if (file != null)
{
if (file.ContentLength <= Config.UploadConfig.MaxUploadSize)
@@ -131,7 +131,7 @@ namespace Teknik.Areas.API.Controllers
{
try
{
Tracking.TrackPageView(Request, "Paste", Subdomain);
Tracking.TrackPageView(Request, "Paste");
Paste.Models.Paste paste = PasteHelper.CreatePaste(code, title, syntax, expireUnit, expireLength, password, hide);

db.Pastes.Add(paste);
@@ -160,7 +160,7 @@ namespace Teknik.Areas.API.Controllers
{
try
{
Tracking.TrackPageView(Request, "Shorten", Subdomain);
Tracking.TrackPageView(Request, "Shorten");
if (url.IsValidUrl())
{
ShortenedUrl newUrl = Shortener.Shortener.ShortenUrl(url, Config.ShortenerConfig.UrlLength);

+ 1
- 1
Teknik/Areas/Upload/Controllers/UploadController.cs View File

@@ -147,7 +147,7 @@ namespace Teknik.Areas.Upload.Controllers
Response.AppendHeader("Content-Disposition", cd.ToString());

// Handle Piwik Tracking if enabled
Tracking.TrackAction(Request.UserAgent, Request.Url.ToString());
Tracking.TrackAction(Request, Request.Url.ToString());

return File(data, upload.ContentType);
}

+ 3
- 0
Teknik/Configuration/PiwikConfig.cs View File

@@ -14,11 +14,14 @@ namespace Teknik.Configuration

public int SiteId { get; set; }

public string TokenAuth { get; set; }

public PiwikConfig()
{
Enabled = false;
Url = string.Empty;
SiteId = 1;
TokenAuth = string.Empty;
}
}
}

+ 6
- 22
Teknik/Filters/TrackingFilterAttribute.cs View File

@@ -20,30 +20,14 @@ namespace Teknik.Filters

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Config config = Config.Load();
if (config.PiwikConfig.Enabled)
{
try
{
string sub = filterContext.HttpContext.Request.RequestContext.RouteData.Values["sub"].ToString();
if (string.IsNullOrEmpty(sub))
{
sub = filterContext.HttpContext.Request.Url.AbsoluteUri.GetSubdomain();
}
string title = config.Title;
Page page = filterContext.HttpContext.Handler as Page;

if (page != null)
{
title = page.Title;
}
Tracking.TrackPageView(filterContext.HttpContext.Request, title, sub);
}
catch (Exception ex)
{
string title = string.Empty;
Page page = filterContext.HttpContext.Handler as Page;

}
if (page != null)
{
title = page.Title;
}
Tracking.TrackPageView(filterContext.HttpContext.Request, title);

base.OnActionExecuted(filterContext);
}

+ 10
- 28
Teknik/Global.asax.cs View File

@@ -46,40 +46,22 @@ namespace Teknik
var stopwatch = new Stopwatch();
HttpContext.Current.Items["Stopwatch"] = stopwatch;
stopwatch.Start();

// Handle Piwik Tracking if enabled
Config config = Config.Load();
if (config.PiwikConfig.Enabled)
{
try
{
HttpRequest request = base.Request;

string sub = request.RequestContext.RouteData.Values["sub"].ToString();
if (string.IsNullOrEmpty(sub))
{
sub = request.Url.AbsoluteUri.GetSubdomain();
}
string title = config.Title;
Page page = HttpContext.Current.Handler as Page;

if (page != null)
{
title = page.Title;
}
Tracking.TrackPageView(new HttpRequestWrapper(request), title, sub);
}
catch (Exception ex)
{

}
}
}

protected void Application_EndRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;

// Handle Piwik
string title = string.Empty;
Page page = HttpContext.Current.Handler as Page;

if (page != null)
{
title = page.Title;
}
Tracking.TrackPageView(new HttpRequestWrapper(context.Request), title);

Stopwatch stopwatch = (Stopwatch)context.Items["Stopwatch"];
stopwatch.Stop();


+ 23
- 0
Teknik/Helpers/Crypto.cs View File

@@ -15,6 +15,29 @@ using System;

namespace Teknik.Helpers
{
public class MD5
{
public static string Hash(string value)
{
byte[] valBytes = Encoding.ASCII.GetBytes(value);
System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] hashBytes = md5.ComputeHash(valBytes);

StringBuilder sBuilder = new StringBuilder();

// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < hashBytes.Length; i++)
{
sBuilder.Append(hashBytes[i].ToString("x2"));
}

// Return the hexadecimal string.
return sBuilder.ToString();

}
}

public class SHA384
{
public static string Hash(string key, string value)

+ 231
- 0
Teknik/Helpers/RequestHelper.cs View File

@@ -0,0 +1,231 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Teknik.Helpers
{
public static class RequestHelper
{
/// <summary>
/// method to get Client ip address
/// </summary>
/// <param name="GetLan"> set to true if want to get local(LAN) Connected ip address</param>
/// <returns></returns>
public static string GetVisitorIPAddress(bool GetLan = false)
{
string visitorIPAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

if (String.IsNullOrEmpty(visitorIPAddress))
visitorIPAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

if (string.IsNullOrEmpty(visitorIPAddress))
visitorIPAddress = HttpContext.Current.Request.UserHostAddress;

if (string.IsNullOrEmpty(visitorIPAddress) || visitorIPAddress.Trim() == "::1")
{
GetLan = true;
visitorIPAddress = string.Empty;
}

if (GetLan)
{
if (string.IsNullOrEmpty(visitorIPAddress))
{
//This is for Local(LAN) Connected ID Address
string stringHostName = Dns.GetHostName();
//Get Ip Host Entry
IPHostEntry ipHostEntries = Dns.GetHostEntry(stringHostName);
//Get Ip Address From The Ip Host Entry Address List
IPAddress[] arrIpAddress = ipHostEntries.AddressList;

try
{
visitorIPAddress = arrIpAddress[arrIpAddress.Length - 2].ToString();
}
catch
{
try
{
visitorIPAddress = arrIpAddress[0].ToString();
}
catch
{
try
{
arrIpAddress = Dns.GetHostAddresses(stringHostName);
visitorIPAddress = arrIpAddress[0].ToString();
}
catch
{
visitorIPAddress = "127.0.0.1";
}
}
}
}
}
return visitorIPAddress;
}

// based on http://www.grantburton.com/2008/11/30/fix-for-incorrect-ip-addresses-in-wordpress-comments/
public static string ClientIPFromRequest(this HttpRequestBase request, bool skipPrivate)
{
foreach (var item in s_HeaderItems)
{
var ipString = request.Headers[item.Key];

if (String.IsNullOrEmpty(ipString))
continue;

if (item.Split)
{
foreach (var ip in ipString.Split(','))
if (ValidIP(ip, skipPrivate))
return ip;
}
else
{
if (ValidIP(ipString, skipPrivate))
return ipString;
}
}

return request.UserHostAddress;
}

public static string DumpHeaders(this HttpRequestBase request)
{
var headers = string.Empty;
foreach (var key in request.Headers.AllKeys)
headers += key + "=" + request.Headers[key] + Environment.NewLine;
return headers;
}

public static string DumpServerVariables(this HttpRequestBase request)
{
var variables = string.Empty;
foreach (var key in request.ServerVariables.AllKeys)
variables += key + "=" + request.ServerVariables[key] + Environment.NewLine;
return variables;
}

private static bool ValidIP(string ip, bool skipPrivate)
{
IPAddress ipAddr;

ip = ip == null ? String.Empty : ip.Trim();

if (0 == ip.Length
|| false == IPAddress.TryParse(ip, out ipAddr)
|| (ipAddr.AddressFamily != AddressFamily.InterNetwork
&& ipAddr.AddressFamily != AddressFamily.InterNetworkV6))
return false;

if (skipPrivate && ipAddr.AddressFamily == AddressFamily.InterNetwork)
{
var addr = IpRange.AddrToUInt64(ipAddr);
foreach (var range in s_PrivateRanges)
{
if (range.Encompasses(addr))
return false;
}
}

return true;
}

/// <summary>
/// Provides a simple class that understands how to parse and
/// compare IP addresses (IPV4) ranges.
/// </summary>
private sealed class IpRange
{
private readonly UInt64 _start;
private readonly UInt64 _end;

public IpRange(string startStr, string endStr)
{
_start = ParseToUInt64(startStr);
_end = ParseToUInt64(endStr);
}

public static UInt64 AddrToUInt64(IPAddress ip)
{
var ipBytes = ip.GetAddressBytes();
UInt64 value = 0;

foreach (var abyte in ipBytes)
{
value <<= 8; // shift
value += abyte;
}

return value;
}

public static UInt64 ParseToUInt64(string ipStr)
{
var ip = IPAddress.Parse(ipStr);
return AddrToUInt64(ip);
}

public bool Encompasses(UInt64 addrValue)
{
return _start <= addrValue && addrValue <= _end;
}

public bool Encompasses(IPAddress addr)
{
var value = AddrToUInt64(addr);
return Encompasses(value);
}
};

private static readonly IpRange[] s_PrivateRanges =
new IpRange[] {
new IpRange("0.0.0.0","2.255.255.255"),
new IpRange("10.0.0.0","10.255.255.255"),
new IpRange("127.0.0.0","127.255.255.255"),
new IpRange("169.254.0.0","169.254.255.255"),
new IpRange("172.16.0.0","172.31.255.255"),
new IpRange("192.0.2.0","192.0.2.255"),
new IpRange("192.168.0.0","192.168.255.255"),
new IpRange("255.255.255.0","255.255.255.255")
};


/// <summary>
/// Describes a header item (key) and if it is expected to be
/// a comma-delimited string
/// </summary>
private sealed class HeaderItem
{
public readonly string Key;
public readonly bool Split;

public HeaderItem(string key, bool split)
{
Key = key;
Split = split;
}
}

// order is in trust/use order top to bottom
private static readonly HeaderItem[] s_HeaderItems =
new HeaderItem[] {
new HeaderItem("HTTP_CLIENT_IP",false),
new HeaderItem("HTTP_X_FORWARDED_FOR",true),
new HeaderItem("HTTP_X_FORWARDED",false),
new HeaderItem("HTTP_X_CLUSTER_CLIENT_IP",false),
new HeaderItem("HTTP_FORWARDED_FOR",false),
new HeaderItem("HTTP_FORWARDED",false),
new HeaderItem("HTTP_VIA",false),
new HeaderItem("REMOTE_ADDR",false)
};

}
}

+ 25
- 7
Teknik/Helpers/Tracking.cs View File

@@ -11,7 +11,7 @@ namespace Teknik.Helpers
{
public static class Tracking
{
public static void TrackPageView(HttpRequestBase request, string title, string sub)
public static void TrackPageView(HttpRequestBase request, string title)
{
Config config = Config.Load();
// Handle Piwik Tracking if enabled
@@ -19,22 +19,35 @@ namespace Teknik.Helpers
{
try
{
string sub = request.RequestContext.RouteData.Values["sub"].ToString();
if (string.IsNullOrEmpty(sub))
{
sub = request.Url.AbsoluteUri.GetSubdomain();
}

if (string.IsNullOrEmpty(title))
{
title = config.Title;
}

PiwikTracker.URL = config.PiwikConfig.Url;
PiwikTracker tracker = new PiwikTracker(config.PiwikConfig.SiteId);

tracker.setForceVisitDateTime(DateTime.Now);
tracker.setUserAgent(request.UserAgent);

tracker.setResolution(request.Browser.ScreenPixelsWidth, request.Browser.ScreenPixelsHeight);
tracker.setBrowserHasCookies(request.Browser.Cookies);

string ipAddress = request.UserHostAddress;
string ipAddress = request.ClientIPFromRequest(true);

tracker.setIp(ipAddress);
tracker.setTokenAuth(config.PiwikConfig.TokenAuth);

tracker.setUrl(request.Url.ToString());
tracker.setUrlReferrer(request.UrlReferrer.ToString());
if (request.UrlReferrer != null)
tracker.setUrlReferrer(request.UrlReferrer.ToString());

tracker.setRequestTimeout(5);
tracker.doTrackPageView(string.Format("{0} / {1}", sub, title));
}
catch (Exception ex)
@@ -44,7 +57,7 @@ namespace Teknik.Helpers
}
}

public static void TrackAction(string userAgent, string url)
public static void TrackAction(HttpRequestBase request, string url)
{
Config config = Config.Load();
// Handle Piwik Tracking if enabled
@@ -55,7 +68,12 @@ namespace Teknik.Helpers
PiwikTracker.URL = config.PiwikConfig.Url;
PiwikTracker tracker = new PiwikTracker(config.PiwikConfig.SiteId);

tracker.setUserAgent(userAgent);
tracker.setUserAgent(request.UserAgent);

string ipAddress = request.ClientIPFromRequest(true);

tracker.setIp(ipAddress);
tracker.setTokenAuth(config.PiwikConfig.TokenAuth);

tracker.doTrackAction(url, PiwikTracker.ActionType.download);
}

+ 0
- 2
Teknik/Modules/PerformanceMonitorModule.cs View File

@@ -30,8 +30,6 @@ namespace Teknik.Modules

if (requestContext.Response.ContentType == "text/html" && requestContext.Response.StatusCode == 200)
{

Uri requestUrl = requestContext.Request.Url;
double ms = (double)timer.ElapsedMilliseconds;
string result = string.Format("{0:F0}", ms);


+ 1
- 0
Teknik/Teknik.csproj View File

@@ -266,6 +266,7 @@
<Compile Include="Helpers\HttpRequestExtensions.cs" />
<Compile Include="Helpers\MysqlDatabase.cs" />
<Compile Include="Helpers\MarkdownHelper.cs" />
<Compile Include="Helpers\RequestHelper.cs" />
<Compile Include="Helpers\RSSFeedResult.cs" />
<Compile Include="Helpers\Tracking.cs" />
<Compile Include="Helpers\UrlExtensions.cs" />

+ 27
- 0
Teknik/Views/Shared/_Layout.cshtml View File

@@ -30,6 +30,12 @@
</div>
<!-- NoScript Alert -->
<noscript>
@if (Model.Config.PiwikConfig.Enabled)
{
<!-- Piwik Image Tracker-->
<img src="https://stats.teknik.io/piwik.php?idsite=1&rec=1" style="border:0" alt="" />
<!-- End Piwik -->
}
<div class="container">
<div class="row">
<div class="col-xs-12 text-center">
@@ -45,6 +51,27 @@
@RenderBody()
</div>
@Html.Partial("_Footer")
@if (Model.Config.PiwikConfig.Enabled)
{
<!-- Piwik -->
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setCookieDomain", "*.teknik.io"]);
_paq.push(["setDomains", ["*.teknik.io"]]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//stats.teknik.io/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', 1]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Piwik Code -->
}

<script type="text/javascript">
$(document).ready(function () {pageloadDoTimer();});

Loading…
Cancel
Save