using System;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kayak;
using Kayak.Http;
using System.Net;
namespace IW4MAdmin_Web
{
class WebFront
{
public enum Page
{
main,
stats,
bans,
player
}
public WebFront()
{
}
public void Init()
{
webSchedule = KayakScheduler.Factory.Create(new SchedulerDelegate());
webServer = KayakServer.Factory.CreateHttp(new RequestDelegate(), webSchedule);
using (webServer.Listen(new IPEndPoint(IPAddress.Any, 1624)))
{
// runs scheduler on calling thread. this method will block until
// someone calls Stop() on the scheduler.
webSchedule.Start();
}
}
private IScheduler webSchedule;
private IServer webServer;
}
static class Macro
{
static public String parsePagination(int server, int totalItems, int itemsPerPage, int currentPage, String Page)
{
StringBuilder output = new StringBuilder();
output.Append("
");
if ( currentPage > 0)
output.AppendFormat("
PREV", server, currentPage - 1, Page);
double totalPages = Math.Ceiling(((float)totalItems / itemsPerPage));
output.Append("");
if ((currentPage + 1) < totalPages)
output.AppendFormat("
NEXT", server, currentPage + 1, Page);
output.Append("
");
return output.ToString();
}
static public String parseMacros(String input, WebFront.Page Page, int Pagination, int server)
{
StringBuilder buffer = new StringBuilder();
switch (input)
{
case "SERVERS":
var Servers = IW4MAdmin.Program.Servers;
int cycleFix = 0;
for (int i = 0; i < Servers.Count; i++)
{
StringBuilder players = new StringBuilder();
if (Servers[i].getClientNum() < 1)
players.Append("");
return buffer.ToString();
case "STATS":
int totalStats = IW4MAdmin.Program.Servers[server].statDB.totalStats();
buffer.Append("
Starting at #{{TOP}}
");
buffer.Append("
");
start = Pagination*30;
if (totalStats <= 30)
range = totalStats - 1;
else if ((totalStats - start) < 30 )
range = (totalStats - start);
else
range = 30;
List Stats = IW4MAdmin.Program.Servers[server].statDB.getMultipleStats(start, range).OrderByDescending(x => x.Skill).ToList();
buffer.Append("Name | Kills | Deaths | KDR | Rating |
");
cycleFix = 0;
for (int i = 0; i < totalStats; i++)
{
if (i >= Stats.Count -1 || Stats[i] == null )
continue;
IW4MAdmin.Player P = IW4MAdmin.Program.Servers[server].clientDB.getPlayer(Stats[i].statIndex);
if (P == null)
continue;
P.stats = Stats[i];
if (P.stats != null)
{
String Prefix;
if (cycleFix % 2 == 0)
Prefix = "class=row-grey";
else
Prefix = "class=row-white";
String Link = "/" + server + "/" + P.getDBID() + "/?player";
buffer.AppendFormat("{0} | {1} | {2} | {3} | {4} |
", P.getName(), P.stats.Kills, P.stats.Deaths, P.stats.KDR, P.stats.Skill, Prefix, Link);
cycleFix++;
}
}
buffer.Append("
");
buffer.Append(parsePagination(server, totalStats, 30, Pagination, "stats"));
return buffer.ToString().Replace("{{TOP}}", (start + 1).ToString());
case "PLAYER":
buffer.Append("
Name | Aliases | IP | Rating | Level | Connections | Last Seen | Profile | ");
IW4MAdmin.Player Player = IW4MAdmin.Program.Servers[server].clientDB.getPlayer(Pagination);
if (Player == null)
buffer.Append("
---|
");
else
{
buffer.Append("
");
StringBuilder str = new StringBuilder();
List aliases = new List();
IW4MAdmin.Program.Servers[server].getAliases(aliases, Player);
foreach (IW4MAdmin.Player a in aliases)
str.AppendFormat("{0}
", a.getName());
Player.stats = IW4MAdmin.Program.Servers[server].statDB.getStats(Player.getDBID());
String Rating = String.Empty;
if (Player.stats == null)
Rating = "Not Available";
else
Rating = Player.stats.Skill.ToString();
bool logged = false;
String IP;
if (logged)
IP = Player.getIP();
else
IP = "XXX.XXX.XXX.XXX";
Int64 forumID = Int64.Parse(Player.getID(), NumberStyles.AllowHexSpecifier);
forumID = forumID - 76561197960265728;
buffer.AppendFormat("{0} | {1} | {2} | {3} | {4} | {5} | {6} ago | {8} | ", Player.getName(), str, IP, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName());
buffer.Append("
");
}
return buffer.ToString();
default:
return input;
}
}
static public String findMacros(String input, int pageNumber, int server, WebFront.Page page)
{
String output = input;
switch (page)
{
case WebFront.Page.main:
output = output.Replace("{{SERVERS}}", parseMacros("SERVERS", page, pageNumber, server));
break;
case WebFront.Page.bans:
output = output.Replace("{{BANS}}", parseMacros("BANS", page, pageNumber, server));
break;
case WebFront.Page.stats:
output = output.Replace("{{STATS}}", parseMacros("STATS", page, pageNumber, server));
break;
case WebFront.Page.player:
output = output.Replace("{{PLAYER}}", parseMacros("PLAYER", page, pageNumber, server));
break;
}
//output = output.Replace("{{PAGE}}", parseMacros("PAGE", page, pageNumber, server));
//output = output.Replace("{{SERVERS}}", parseMacros("SERVERS", 0));
//output = output.Replace("{{BANS}}", parseMacros("BANS", page));
output = output.Replace("{{TITLE}}", "IW4M Administration");
output = output.Replace("{{VERSION}}", IW4MAdmin.Program.Version.ToString());
//output = output.Replace("{{PAGE}}", parseMacros("PAGE", page));
//output = output.Replace("{{STATS}}", parseMacros("STATS", page));
return output;
}
}
class SchedulerDelegate : ISchedulerDelegate
{
public void OnException(IScheduler scheduler, Exception e)
{
Console.WriteLine(e.InnerException.Message);
Console.Write(e.InnerException);
e.DebugStackTrace();
}
public void OnStop(IScheduler scheduler)
{
}
}
class RequestDelegate : IHttpRequestDelegate
{
public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response)
{
if (request.Uri.StartsWith("/"))
{
//Console.WriteLine("[WEBFRONT] Processing Request for " + request.Uri);
var body = String.Empty;
if (request.Uri.StartsWith("/"))
{
IW4MAdmin.file Header = new IW4MAdmin.file("webfront\\header.html");
var header = Header.getLines();
Header.Close();
IW4MAdmin.file Footer = new IW4MAdmin.file("webfront\\footer.html");
var footer = Footer.getLines();
Footer.Close();
String[] req = request.Path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
int server = 0;
int page = 0;
if (req.Length > 1)
{
Int32.TryParse(req[0], out server);
Int32.TryParse(req[1], out page);
}
if (request.QueryString == "bans")
{
IW4MAdmin.file Bans = new IW4MAdmin.file("webfront\\bans.html");
var bans = Bans.getLines();
Bans.Close();
body = Macro.findMacros((header + bans + footer), page, server, WebFront.Page.bans);
}
else if (request.QueryString == "stats")
{
IW4MAdmin.file Stats = new IW4MAdmin.file("webfront\\stats.html");
var stats = Stats.getLines();
Stats.Close();
body = Macro.findMacros(header + stats + footer, page, server, WebFront.Page.stats);
}
else if (request.QueryString == "player")
{
IW4MAdmin.file Player = new IW4MAdmin.file("webfront\\player.html");
var player = Player.getLines();
Player.Close();
body = Macro.findMacros(header + player + footer, page, server, WebFront.Page.player);
}
else
{
IW4MAdmin.file Main = new IW4MAdmin.file("webfront\\main.html");
var main = Main.getLines();
Main.Close();
body = Macro.findMacros(header + main + footer, 0, server, WebFront.Page.main);
}
IW4MAdmin.Program.Servers[server].Log.Write("Webfront processed request for " + request.Uri, IW4MAdmin.Log.Level.Debug);
}
var headers = new HttpResponseHead()
{
Status = "200 OK",
Headers = new Dictionary
()
{
{ "Content-Type", "text/html" },
{ "Content-Length", body.Length.ToString() },
}
};
response.OnResponse(headers, new BufferedProducer(body));
}
else
{
var responseBody = "The resource you requested ('" + request.Uri + "') could not be found.";
var headers = new HttpResponseHead()
{
Status = "404 Not Found",
Headers = new Dictionary()
{
{ "Content-Type", "text/text" },
{ "Content-Length", responseBody.Length.ToString() }
}
};
var body = new BufferedProducer(responseBody);
response.OnResponse(headers, body);
}
}
class BufferedProducer : IDataProducer
{
ArraySegment data;
public BufferedProducer(string data) : this(data, Encoding.UTF8) { }
public BufferedProducer(string data, Encoding encoding) : this(encoding.GetBytes(data)) { }
public BufferedProducer(byte[] data) : this(new ArraySegment(data)) { }
public BufferedProducer(ArraySegment data)
{
this.data = data;
}
public IDisposable Connect(IDataConsumer channel)
{
// null continuation, consumer must swallow the data immediately.
channel.OnData(data, null);
channel.OnEnd();
return null;
}
}
class BufferedConsumer : IDataConsumer
{
List> buffer = new List>();
Action resultCallback;
Action errorCallback;
public BufferedConsumer(Action resultCallback, Action errorCallback)
{
this.resultCallback = resultCallback;
this.errorCallback = errorCallback;
}
public bool OnData(ArraySegment data, Action continuation)
{
// since we're just buffering, ignore the continuation.
buffer.Add(data);
return false;
}
public void OnError(Exception error)
{
errorCallback(error);
}
public void OnEnd()
{
// turn the buffer into a string.
var str = buffer
.Select(b => Encoding.UTF8.GetString(b.Array, b.Offset, b.Count))
.Aggregate((result, next) => result + next);
resultCallback(str);
}
}
}
}