using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using InsomniaSoftware.Server;
using InsomniaSoftware.Server.Sources;
namespace SimpleLogin
{
class Login
{
//Allowed users
static LinkedList<User> users = new LinkedList<User>();
//Handle to Form1
static Form1 mainForm;
/// <summary>
/// Clears possibly existing users and loads new ones
/// </summary>
/// <param name="usersFile">XML file which stores the new users</param>
public static void LoadUsers(string usersFile)
{
users.Clear();
XmlTextReader xmlReader = new XmlTextReader(usersFile);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
XmlNode curNode = xmlDoc.FirstChild;
while (curNode != null)
{
if (curNode.Name.ToLower() == "login")
{
XmlNode curSubNode = curNode.FirstChild;
while (curSubNode != null)
{
User newUser = new User();
if (curSubNode.Name.ToLower() == "user")
{
foreach (XmlNode attribute in curSubNode.ChildNodes)
{
if (attribute.Name.ToLower() == "name")
newUser.name = attribute.InnerText;
if (attribute.Name.ToLower() == "pw")
newUser.pw = attribute.InnerText;
}
}
users.AddLast(newUser);
curSubNode = curSubNode.NextSibling;
}
}
curNode = curNode.NextSibling;
}
xmlReader.Close();
}
/// <summary>
/// Adds all needed sources to the server
/// </summary>
/// <param name="server">Server handle</param>
/// <param name="callingForm">Form which contains the list box to be filled with login data</param>
public static void AddSources(InsomniaServer server, Form1 callingForm)
{
mainForm = callingForm;
server.fileSystem.AddSource("index.html", FileSource.GetSource, "../pages/index.html");
server.fileSystem.AddSource("dologin.html", GetDoLogin, null);
server.fileSystem.AddSource("sec/*", GetMembersonlyContent, null);
server.fileSystem.GetNode("sec").SetSecurityValidator(SecurityValidator, null, InternalRedirectSource.GetSource, "/index.html");
}
/// <summary>
/// Gets the "dologin.html" source and redirects the request
/// </summary>
public static ObjectType GetDoLogin(string subPath, HttpRequest request, object userData, out Source source)
{
string passedName = null;
string passedPW = null;
string assignedID = null;
try
{
passedName = request.GetParameter("username").ToString();
passedPW = request.GetParameter("password").ToString();
}
catch { }
bool matchFound = false;
try
{
if (passedName != null && passedPW != null)
{
try
{
foreach (User curUser in users)
{
if (curUser.name == passedName && curUser.pw == passedPW)
{
matchFound = true;
break;
}
}
}
catch { }
}
if (matchFound)
{
//Create a new session, to store user's data
Session sess = request.server.sessionManager.RegisterSession();
sess.SetStringValue("username", passedName);
sess.SetValue("ip", request.remoteEndPoint.Address);
assignedID = sess.id;
//Redirect request to the secured area
source = new MovedPermanentlySource("/sec/index.html?sid=" + sess.id);
return ObjectType.File;
}
else
{
//Login failed - send failed response
source = FileSource.Get("../pages/loginfailed.html");
return ObjectType.File;
}
}
finally
{
if (mainForm != null)
{
//Write login data and result to the form's list box
mainForm.Invoke(new Form1.AddListBoxItemDelegate(mainForm.listBoxLogins.Items.Add),
DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString() + ": " +
(passedName != null ? passedName : "[null]") + " / " + (passedPW != null ? passedPW : "[null]") + " " +
(matchFound ? ("SUCCEEDED (" + assignedID + ")") : "FAILED"));
}
}
}
/// <summary>
/// Gets a source for the secured area
/// </summary>
public static ObjectType GetMembersonlyContent(string subPath, HttpRequest request, object userData, out Source source)
{
source = null;
//Create full local path of the requested source
string fullPath = "../pages/sec/" + subPath;
if (File.Exists(fullPath))
{
if (subPath.EndsWith(".html") || subPath.EndsWith(".htm"))
{
Session sess = null;
try
{
//Load user's session
sess = request.server.sessionManager.GetSession(request.GetParameter("sid").ToString());
}
catch { }
//Replace placeholders in html pages
StreamReader reader = new StreamReader(fullPath, Encoding.ASCII);
string pageContent = reader.ReadToEnd();
reader.Dispose();
if (sess != null)
{
pageContent = pageContent.Replace("<!--#USER#-->", sess.GetStringValue("username"));
pageContent = pageContent.Replace("<!--#SID#-->", sess.id);
pageContent = pageContent.Replace("<!--#IP#-->", sess.GetValue("ip").ToString());
}
source = new BinarySource(Encoding.ASCII.GetBytes(pageContent), ContentType.FromFileName(subPath));
}
else
source = FileSource.Get(fullPath);
return ObjectType.File;
}
else
{
if (Directory.Exists(fullPath))
return ObjectType.Folder;
else
return ObjectType.NotFound;
}
}
/// <summary>
/// Checks whether a request belongs to a logged in user
/// </summary>
public static bool SecurityValidator(object validatorUserData, string subPath, HttpRequest request, object sourceUserData)
{
try
{
Session sess = request.server.sessionManager.GetSession(request.GetParameter("sid").ValueToString());
if (!sess.GetValue("ip").Equals(request.remoteEndPoint.Address))
return false;
return true;
}
catch
{
return false;
}
}
struct User
{
public string name;
public string pw;
}
}
}