Rename to VAR.Focus

This commit is contained in:
2015-06-26 02:23:21 +02:00
parent 58d51ee3b7
commit 175fad80e4
52 changed files with 71 additions and 98 deletions

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace VAR.Focus.Web.Code
{
public class Bundler
{
#region Declarations
private string _path = null;
private List<string> _files = null;
#endregion
#region Properties
private List<string> Files
{
get
{
if (_files != null) { return _files; }
DirectoryInfo dir = new DirectoryInfo(_path);
FileInfo[] files = dir.GetFiles();
_files = files.OrderBy(file => file.FullName).Select(file2 => file2.FullName).ToList();
return _files;
}
}
#endregion
#region Creator
public Bundler(string path)
{
_path = path;
}
#endregion
#region Public methods
public void WriteResponse(Stream outStream)
{
foreach (string fileName in Files)
{
string fileContent = File.ReadAllText(fileName);
byte[] byteArray = Encoding.UTF8.GetBytes(fileContent);
if (byteArray.Length > 0)
{
outStream.Write(byteArray, 0, byteArray.Length);
byteArray = Encoding.UTF8.GetBytes("\n\n");
outStream.Write(byteArray, 0, byteArray.Length);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,284 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using VAR.Focus.Web.Code.Entities;
namespace VAR.Focus.Web.Code.BusinessLogic
{
public class CardBoard
{
#region Declarations
private List<Card> _cards = new List<Card>();
private int _lastIDCard = 0;
private List<ICardEvent> _cardEvents = new List<ICardEvent>();
private int _lastIDCardEvent = 0;
private int _idBoard = 0;
#endregion
#region Life cycle
public CardBoard(int idBoard)
{
_idBoard = idBoard;
LoadData();
}
#endregion
#region Public methods
public List<Card> Cards_Status()
{
List<Card> activeCards=new List<Card>();
foreach (Card card in _cards)
{
if (card.Active)
{
activeCards.Add(card);
}
}
return activeCards;
}
public List<ICardEvent> Cards_GetEventList(int idCardEvent)
{
List<ICardEvent> listEvents = new List<ICardEvent>();
for (int i = 0, n = _cardEvents.Count; i < n; i++)
{
ICardEvent cardEvent = _cardEvents[i];
if (cardEvent.IDCardEvent > idCardEvent)
{
listEvents.Insert(0, cardEvent);
}
else { break; }
}
return listEvents;
}
public int GetLastIDCardEvent()
{
return _lastIDCardEvent;
}
public int GetLastIDCard()
{
return _lastIDCard;
}
public int Card_Create(string title, string body, int x, int y, string currentUserName)
{
DateTime currentDate = DateTime.UtcNow;
Card card;
lock (_cards)
{
// Create card
_lastIDCard++;
card = new Card()
{
IDCard = _lastIDCard,
Title = title,
Body = body,
X = x,
Y = y,
Active = true,
CreatedBy = currentUserName,
CreatedDate = currentDate,
ModifiedBy = currentUserName,
ModifiedDate = currentDate,
};
_cards.Add(card);
// Create event
_lastIDCardEvent++;
CardCreateEvent cardCreateEvent = new CardCreateEvent()
{
IDCardEvent = _lastIDCardEvent,
IDCard = card.IDCard,
UserName = currentUserName,
Date = currentDate,
Title = card.Title,
Body = card.Body,
X = card.X,
Y = card.Y,
};
_cardEvents.Insert(0, cardCreateEvent);
SaveData();
}
return card.IDCard;
}
public bool Card_Move(int idCard, int x, int y, string currentUserName)
{
DateTime currentDate = DateTime.UtcNow;
lock (_cards)
{
// Move card
Card card = GetByID(idCard);
if (card == null) { return false; }
card.X = x;
card.Y = y;
card.ModifiedBy = currentUserName;
card.ModifiedDate = currentDate;
// Create event
_lastIDCardEvent++;
CardMoveEvent cardMoveEvent = new CardMoveEvent()
{
IDCardEvent = _lastIDCardEvent,
IDCard = card.IDCard,
UserName = currentUserName,
Date = currentDate,
X = card.X,
Y = card.Y,
};
_cardEvents.Insert(0, cardMoveEvent);
SaveData();
}
return true;
}
public bool Card_Edit(int idCard, string title, string body, string currentUserName)
{
DateTime currentDate = DateTime.UtcNow;
lock (_cards)
{
// Edit card
Card card = GetByID(idCard);
if (card == null) { return false; }
card.Title = title;
card.Body = body;
card.ModifiedBy = currentUserName;
card.ModifiedDate = currentDate;
// Create event
_lastIDCardEvent++;
CardEditEvent cardEditEvent = new CardEditEvent()
{
IDCardEvent = _lastIDCardEvent,
IDCard = card.IDCard,
UserName = currentUserName,
Date = currentDate,
Title = card.Title,
Body = card.Body,
};
_cardEvents.Insert(0, cardEditEvent);
SaveData();
}
return true;
}
public bool Card_Delete(int idCard, string currentUserName)
{
DateTime currentDate = DateTime.UtcNow;
lock (_cards)
{
// Delete card
Card card = GetByID(idCard);
if (card == null) { return false; }
card.Active = false;
card.ModifiedBy = currentUserName;
// Create event
_lastIDCardEvent++;
CardDeleteEvent cardDeleteEvent = new CardDeleteEvent()
{
IDCardEvent = _lastIDCardEvent,
IDCard = card.IDCard,
UserName = currentUserName,
Date = currentDate,
};
_cardEvents.Insert(0, cardDeleteEvent);
SaveData();
}
return true;
}
public static List<ICardEvent> ConvertCardsToEvents(List<Card> listCards, int lastIDCardEvent)
{
List<ICardEvent> listEvents = new List<ICardEvent>();
foreach (Card card in listCards)
{
var evt = new CardCreateEvent()
{
IDCardEvent = lastIDCardEvent,
IDCard = card.IDCard,
UserName = card.ModifiedBy,
Date = card.ModifiedDate,
Title = card.Title,
Body = card.Body,
X = card.X,
Y = card.Y,
};
listEvents.Add(evt);
}
return listEvents;
}
#endregion
#region Private methods
private Card GetByID(int idCard)
{
foreach (Card card in _cards)
{
if (card.IDCard == idCard)
{
return card;
}
}
return null;
}
#region Persistence
private const string CardsPersistenceFile = "priv/cardBoard.{0}.json";
private const string EventsPersistenceFile = "priv/cardEvents.{0}.json";
private void LoadData()
{
_cards = Persistence.LoadList<Card>(String.Format(CardsPersistenceFile, _idBoard));
_lastIDCard = 0;
foreach (Card card in _cards)
{
if (card.IDCard > _lastIDCard)
{
_lastIDCard = card.IDCard;
}
}
_cardEvents = Persistence.LoadList<ICardEvent>(String.Format(EventsPersistenceFile, _idBoard),
new List<Type> {
typeof(CardCreateEvent),
typeof(CardMoveEvent),
typeof(CardEditEvent),
typeof(CardDeleteEvent),
});
_lastIDCardEvent = 0;
if (_cardEvents.Count > 0)
{
_lastIDCardEvent = _cardEvents[0].IDCardEvent;
}
}
private void SaveData()
{
Persistence.SaveList(String.Format(CardsPersistenceFile, _idBoard), _cards);
Persistence.SaveList(String.Format(EventsPersistenceFile, _idBoard), _cardEvents);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using VAR.Focus.Web.Code.Entities;
namespace VAR.Focus.Web.Code.BusinessLogic
{
public class MessageBoard
{
#region Declarations
private List<Message> _messages = new List<Message>();
private int _lastIDMessage = 0;
private int _idBoard = 0;
#endregion
#region Life cycle
public MessageBoard(int idBoard)
{
_idBoard = idBoard;
LoadData();
}
#endregion
#region Public methods
public List<Message> Messages_GetList(int idMessage)
{
List<Message> listMessages = new List<Message>();
for (int i = 0, n = _messages.Count; i < n; i++)
{
Message msg = _messages[i];
if (msg.IDMessage > idMessage)
{
listMessages.Insert(0, msg);
}
else { break; }
}
return listMessages;
}
public void Message_Add(string userName, string text)
{
lock (_messages)
{
_lastIDMessage++;
Message msg = new Message();
msg.IDMessage = _lastIDMessage;
msg.UserName = userName;
msg.Text = text;
msg.Date = DateTime.UtcNow;
_messages.Insert(0, msg);
SaveData();
}
}
#endregion
#region Private methods
#region Persistence
private const string PersistenceFile = "priv/messageBoard.{0}.json";
private void LoadData()
{
_messages = Persistence.LoadList<Message>(String.Format(PersistenceFile, _idBoard));
_lastIDMessage = 0;
if (_messages.Count > 0)
{
_lastIDMessage = _messages[0].IDMessage;
}
}
private void SaveData()
{
Persistence.SaveList(String.Format(PersistenceFile, _idBoard), _messages);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using VAR.Focus.Web.Code.JSON;
namespace VAR.Focus.Web.Code.BusinessLogic
{
public class Persistence
{
#region Private methods
private static string GetLocalPath(string path)
{
string currentDir = Path.GetDirectoryName((new System.Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath);
return string.Format("{0}/{1}", Directory.GetParent(currentDir), path);
}
#endregion
#region public methods
public static List<T> LoadList<T>(string file)
{
return LoadList<T>(file, null);
}
public static List<T> LoadList<T>(string file, List<Type> types)
{
List<T> listResult = new List<T>();
JSONParser parser = new JSONParser();
Type typeResult = typeof(T);
if (typeResult.IsInterface == false)
{
parser.KnownTypes.Add(typeof(T));
}
if (types != null)
{
foreach (Type type in types)
{
parser.KnownTypes.Add(type);
}
}
string filePath = GetLocalPath(file);
if (File.Exists(filePath) == false) { return listResult; }
string strJsonUsers = File.ReadAllText(filePath);
object result = parser.Parse(strJsonUsers);
if (result is IEnumerable<object>)
{
foreach (object item in (IEnumerable<object>)result)
{
if (item is T)
{
listResult.Add((T)item);
}
}
}
return listResult;
}
public static bool SaveList(string file, object data)
{
JSONWriter writter = new JSONWriter(true);
string strJsonUsers = writter.Write(data);
File.WriteAllText(GetLocalPath(file), strJsonUsers);
return true;
}
#endregion
}
}

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Web;
using VAR.Focus.Web.Code.Entities;
namespace VAR.Focus.Web.Code.BusinessLogic
{
public class Sessions
{
#region declarations
private static Sessions _currentInstance = null;
private List<Session> _sessions = new List<Session>();
private string _cookieName = "ScrummerSID";
private int _cookieExpirationDays = 30;
#endregion
#region Properties
public static Sessions Current
{
get
{
if (_currentInstance == null)
{
_currentInstance = new Sessions();
}
return _currentInstance;
}
set { _currentInstance = value; }
}
public string CookieName
{
get { return _cookieName; }
set { _cookieName = value; }
}
public int CookieExpirationDays
{
get { return _cookieExpirationDays; }
set { _cookieExpirationDays = value; }
}
#endregion
#region Life cycle
public Sessions()
{
LoadData();
}
#endregion
#region Public methods
public void Session_SetCookie(HttpContext context, Session session)
{
HttpCookie cookie = new HttpCookie(_cookieName, session.SessionToken);
cookie.Expires = DateTime.Now.AddDays(_cookieExpirationDays);
context.Response.Cookies.Add(cookie);
}
public bool Session_Init(HttpContext context, string userName)
{
lock (_sessions)
{
var session = new Session();
session.UserName = userName;
session.SessionToken = CryptoUtils.GetCryptoToken();
session.StartDate = DateTime.UtcNow;
_sessions.Add(session);
Session_SetCookie(context, session);
SaveData();
}
return true;
}
public Session Session_GetCurrent(HttpContext context)
{
HttpCookie cookie = context.Request.Cookies[_cookieName];
if (cookie == null) { return null; }
string sessionToken = cookie.Value;
if (string.IsNullOrEmpty(sessionToken)) { return null; }
Session session = Session_GetByToken(sessionToken);
return session;
}
public bool Session_FinalizeCurrent(HttpContext context)
{
lock (_sessions)
{
Session session = Session_GetCurrent(context);
if (session == null) { return false; }
if (_sessions.Remove(session) == false) { return false; }
HttpCookie cookie = new HttpCookie(_cookieName);
cookie.Expires = DateTime.Now.AddDays(-1d);
context.Response.Cookies.Add(cookie);
SaveData();
}
return true;
}
#endregion
#region Private methods
private Session Session_GetByToken(string sessionToken)
{
foreach (Session session in _sessions)
{
if (session.SessionToken == sessionToken)
{
return session;
}
}
return null;
}
#region Persistence
private const string PersistenceFile = "priv/sessions.json";
private void LoadData()
{
_sessions = Persistence.LoadList<Session>(PersistenceFile);
}
private void SaveData()
{
Persistence.SaveList(PersistenceFile, _sessions);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.IO;
using VAR.Focus.Web.Code.Entities;
using VAR.Focus.Web.Code.JSON;
namespace VAR.Focus.Web.Code.BusinessLogic
{
public class Users
{
#region declarations
private static Users _currentInstance = null;
private List<User> _users = new List<User>();
#endregion
#region Properties
public static Users Current
{
get
{
if (_currentInstance == null)
{
_currentInstance = new Users();
}
return _currentInstance;
}
set { _currentInstance = value; }
}
#endregion
#region Life cycle
public Users()
{
LoadData();
}
#endregion
#region Public methods
public User User_GetByName(string name)
{
name=name.ToLower();
foreach (User userAux in _users)
{
if (name.CompareTo(userAux.Name.ToLower()) == 0)
{
return userAux;
}
}
return null;
}
public User User_GetByEmail(string email)
{
email = email.ToLower();
foreach (User userAux in _users)
{
if (email.CompareTo(userAux.Email.ToLower()) == 0)
{
return userAux;
}
}
return null;
}
public User User_GetByNameOrEmail(string name, string email)
{
name = name.ToLower();
email = email.ToLower();
foreach (User userAux in _users)
{
if (name.CompareTo(userAux.Name.ToLower()) == 0 ||
email.CompareTo(userAux.Email.ToLower()) == 0)
{
return userAux;
}
}
return null;
}
public User User_Set(string name, string email, string password)
{
User user = null;
bool isNew = false;
lock (_users)
{
user = User_GetByName(name);
if (user == null) { user = User_GetByEmail(name); }
if (user == null) { user = new User(); isNew = true; }
user.Name = name;
user.Email = email;
if (string.IsNullOrEmpty(password) == false)
{
user.PasswordSalt = CryptoUtils.GetCryptoToken();
user.PasswordHash = CryptoUtils.GetHashedPassword(password, user.PasswordSalt);
}
if (isNew) { _users.Add(user); }
SaveData();
}
return user;
}
public bool User_Authenticate(string nameOrMail, string password)
{
User user = User_GetByNameOrEmail(nameOrMail, nameOrMail);
if (user == null) { return false; }
string passwordHash = CryptoUtils.GetHashedPassword(password, user.PasswordSalt);
if (passwordHash != user.PasswordHash) { return false; }
return true;
}
#endregion
#region Private methods
#region Persistence
private const string PersistenceFile = "priv/users.json";
private void LoadData()
{
_users = Persistence.LoadList<User>(PersistenceFile);
}
private void SaveData()
{
Persistence.SaveList(PersistenceFile, _users);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace VAR.Focus.Web.Code
{
public class CryptoUtils
{
public static string GetSHA1(string str)
{
SHA1 sha1 = SHA1Managed.Create();
UTF8Encoding encoding = new UTF8Encoding();
byte[] stream = null;
StringBuilder sb = new StringBuilder();
stream = sha1.ComputeHash(encoding.GetBytes(str));
for (int i = 0; i < stream.Length; i++) sb.AppendFormat("{0:x2}", stream[i]);
return sb.ToString();
}
public static string GetRandString(int len)
{
byte[] bytes = new byte[len];
var cryptoRandom = new RNGCryptoServiceProvider();
cryptoRandom.GetBytes(bytes);
UTF8Encoding encoding = new UTF8Encoding();
return encoding.GetString(bytes);
}
public static string GetCryptoToken()
{
return CryptoUtils.GetSHA1(CryptoUtils.GetRandString(10));
}
public static string GetHashedPassword(string password, string passwordSalt)
{
return CryptoUtils.GetSHA1(String.Format("{1}{0}{1}", password, passwordSalt));
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace VAR.Focus.Web.Code.Entities
{
public class Card
{
public int IDCard { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public int X { get; set; }
public int Y { get; set; }
public bool Active { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
}
}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace VAR.Focus.Web.Code.Entities
{
public interface ICardEvent
{
int IDCardEvent { get; set; }
string EventType { get; set; }
int IDCard { get; set; }
string UserName { get; set; }
DateTime Date { get; set; }
}
public class CardCreateEvent : ICardEvent
{
#region ICardEvent
public int IDCardEvent { get; set; }
private string _eventType="CardCreate";
public string EventType { get { return _eventType; } set { _eventType = value; } }
public int IDCard { get; set; }
public string UserName { get; set; }
public DateTime Date { get; set; }
#endregion
public string Title { get; set; }
public string Body { get; set; }
public int X { get; set; }
public int Y { get; set; }
}
public class CardMoveEvent : ICardEvent
{
#region ICardEvent
public int IDCardEvent { get; set; }
private string _eventType = "CardMove";
public string EventType { get { return _eventType; } set { _eventType = value; } }
public int IDCard { get; set; }
public string UserName { get; set; }
public DateTime Date { get; set; }
#endregion
public int X { get; set; }
public int Y { get; set; }
}
public class CardEditEvent : ICardEvent
{
#region ICardEvent
public int IDCardEvent { get; set; }
private string _eventType = "CardEdit";
public string EventType { get { return _eventType; } set { _eventType = value; } }
public int IDCard { get; set; }
public string UserName { get; set; }
public DateTime Date { get; set; }
#endregion
public string Title { get; set; }
public string Body { get; set; }
}
public class CardDeleteEvent : ICardEvent
{
#region ICardEvent
public int IDCardEvent { get; set; }
private string _eventType = "CardDelete";
public string EventType { get { return _eventType; } set { _eventType = value; } }
public int IDCard { get; set; }
public string UserName { get; set; }
public DateTime Date { get; set; }
#endregion
}
}

View File

@@ -0,0 +1,12 @@
using System;
namespace VAR.Focus.Web.Code.Entities
{
public class Message
{
public int IDMessage { get; set; }
public string UserName { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
};
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace VAR.Focus.Web.Code.Entities
{
public class OperationStatus
{
public bool IsOK { get; set; }
public string Message { get; set; }
public string ReturnValue { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace VAR.Focus.Web.Code.Entities
{
public class Session
{
public string UserName { get; set; }
public string SessionToken { get; set; }
public DateTime StartDate { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace VAR.Focus.Web.Code.Entities
{
public class User
{
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public string PasswordSalt { get; set; }
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Text;
using System.Web;
using VAR.Focus.Web.Pages;
namespace VAR.Focus.Web.Code
{
public static class GlobalErrorHandler
{
#region Private methods
private static void ShowInternalError(HttpContext context, Exception ex)
{
context.Response.StatusCode = 500;
context.Response.Clear();
StringBuilder sbOutput = new StringBuilder();
sbOutput.Append("<h2>Internal error</h2>");
Exception exAux = ex;
if (exAux is HttpUnhandledException && exAux.InnerException != null) { exAux = exAux.InnerException; }
while (exAux != null)
{
sbOutput.AppendFormat("<p><b>Message:</b> {0}</p>", exAux.Message);
sbOutput.AppendFormat("<p><b>StackTrace:</b></p> <pre><code>{0}</code></pre>", exAux.StackTrace);
exAux = exAux.InnerException;
}
// Fill response to 512 bytes to avoid browser "beauty" response of errors.
long fillResponse = 512 - sbOutput.Length;
if (fillResponse > 0)
{
sbOutput.Append("<!--");
for (int i = 0; i < fillResponse; i++)
{
sbOutput.Append("A");
}
sbOutput.Append("-->");
}
context.Response.Write(sbOutput.ToString());
}
#endregion
#region Public methods
public static void HandleError(HttpContext context, Exception ex)
{
try
{
IHttpHandler frmError = new FrmError(ex);
context.Response.Clear();
context.Handler = frmError;
frmError.ProcessRequest(context);
}
catch
{
ShowInternalError(context, ex);
}
}
#endregion
}
}

View File

@@ -0,0 +1,499 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace VAR.Focus.Web.Code.JSON
{
public class JSONParser
{
#region Declarations
private ParserContext ctx;
private bool tainted = false;
private List<Type> _knownTypes = new List<Type>();
#endregion
#region Properties
public bool Tainted
{
get { return tainted; }
}
public List<Type> KnownTypes
{
get { return _knownTypes; }
}
#endregion
#region Private methods
private static Dictionary<Type, PropertyInfo[]> _dictProperties = new Dictionary<Type, PropertyInfo[]>();
private PropertyInfo[] Type_GetProperties(Type type)
{
PropertyInfo[] typeProperties = null;
if (_dictProperties.ContainsKey(type)) { typeProperties = _dictProperties[type]; }
else
{
lock(_dictProperties){
if (_dictProperties.ContainsKey(type)) { typeProperties = _dictProperties[type]; }
else
{
typeProperties = type.GetProperties(BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.Instance);
_dictProperties.Add(type, typeProperties);
}
}
}
return typeProperties;
}
private float CompareToType(Dictionary<string, object> obj, Type type)
{
PropertyInfo[] typeProperties = Type_GetProperties(type);
int count = 0;
foreach (PropertyInfo prop in typeProperties)
{
if (obj.ContainsKey(prop.Name))
{
count++;
}
}
return ((float)count / (float)typeProperties.Length);
}
private object ConvertToType(Dictionary<string, object> obj, Type type)
{
PropertyInfo[] typeProperties = Type_GetProperties(type);
object newObj = Activator.CreateInstance(type);
foreach (PropertyInfo prop in typeProperties)
{
if (obj.ContainsKey(prop.Name))
{
prop.SetValue(newObj, Convert.ChangeType(obj[prop.Name], prop.PropertyType), null);
}
}
return newObj;
}
private object TryConvertToTypes(Dictionary<string, object> obj)
{
Type bestMatch = null;
float bestMatchFactor = 0.0f;
foreach (Type type in _knownTypes)
{
float matchFactor = CompareToType(obj, type);
if (matchFactor > bestMatchFactor)
{
bestMatch = type;
bestMatchFactor = matchFactor;
}
}
if (bestMatch != null)
{
return ConvertToType(obj, bestMatch);
}
return obj;
}
private int ParseHexShort()
{
int value = 0;
for (int i = 0; i < 4; i++)
{
char c = ctx.Next();
if (Char.IsDigit(c))
{
value = (value << 4) | (c - '0');
}
else
{
c = Char.ToLower(c);
if (c >= 'a' && c <= 'f')
{
value = (value << 4) | ((c - 'a') + 10);
}
}
}
return value;
}
private String ParseQuotedString()
{
StringBuilder scratch = new StringBuilder();
char c = ctx.SkipWhite();
if (c == '"')
{
c = ctx.Next();
}
do
{
if (c == '\\')
{
c = ctx.Next();
if (c == '"')
{
scratch.Append('"');
}
else if (c == '\\')
{
scratch.Append('\\');
}
else if (c == '/')
{
scratch.Append('/');
}
else if (c == 'b')
{
scratch.Append('\b');
}
else if (c == 'f')
{
scratch.Append('\f');
}
else if (c == 'n')
{
scratch.Append('\n');
}
else if (c == 'r')
{
scratch.Append('\r');
}
else if (c == 't')
{
scratch.Append('\t');
}
else if (c == 'u')
{
scratch.Append((char)ParseHexShort());
}
c = ctx.Next();
}
else if (c == '"')
{
break;
}
else
{
scratch.Append(c);
c = ctx.Next();
}
} while (!ctx.AtEnd());
if (c == '"')
{
ctx.Next();
}
return scratch.ToString();
}
private String ParseString()
{
char c = ctx.SkipWhite();
if (c == '"')
{
return ParseQuotedString();
}
StringBuilder scratch = new StringBuilder();
while (!ctx.AtEnd()
&& (Char.IsLetter(c) || Char.IsDigit(c) || c == '_'))
{
scratch.Append(c);
c = ctx.Next();
}
return scratch.ToString();
}
private Object ParseNumber()
{
StringBuilder scratch = new StringBuilder();
bool isFloat = false;
int numberLenght = 0;
char c;
c = ctx.SkipWhite();
// Sign
if (c == '-')
{
scratch.Append('-');
c = ctx.Next();
}
// Integer part
while (Char.IsDigit(c))
{
scratch.Append(c);
c = ctx.Next();
numberLenght++;
}
// Decimal part
if (c == '.')
{
isFloat = true;
scratch.Append('.');
c = ctx.Next();
while (Char.IsDigit(c))
{
scratch.Append(c);
c = ctx.Next();
numberLenght++;
}
}
if (numberLenght == 0)
{
tainted = true;
return null;
}
// Exponential part
if (c == 'e' || c == 'E')
{
isFloat = true;
scratch.Append('E');
c = ctx.Next();
if (c == '+' || c == '-')
{
scratch.Append(c);
}
while (Char.IsDigit(c))
{
scratch.Append(c);
c = ctx.Next();
numberLenght++;
}
}
// Build number object from the parsed string
String s = scratch.ToString();
return isFloat ? (numberLenght < 17) ? (Object)Double.Parse(s)
: Decimal.Parse(s) : (numberLenght < 19) ? (Object)System.Int32.Parse(s)
: (Object)System.Int32.Parse(s);
}
private List<object> ParseArray()
{
char c = ctx.SkipWhite();
List<object> array = new List<object>();
if (c == '[')
{
ctx.Next();
}
do
{
c = ctx.SkipWhite();
if (c == ']')
{
ctx.Next();
break;
}
else if (c == ',')
{
ctx.Next();
}
else
{
array.Add(ParseValue());
}
} while (!ctx.AtEnd());
return array;
}
private Dictionary<string, object> ParseObject()
{
char c = ctx.SkipWhite();
Dictionary<string, object> obj = new Dictionary<string, object>();
if (c == '{')
{
ctx.Next();
c = ctx.SkipWhite();
}
String attributeName;
Object attributeValue;
do
{
attributeName = ParseString();
c = ctx.SkipWhite();
if (c == ':')
{
ctx.Next();
attributeValue = ParseValue();
if (attributeName.Length > 0)
{
obj.Add(attributeName, attributeValue);
}
}
else if (c == ',')
{
ctx.Next();
c = ctx.SkipWhite();
}
else if (c == '}')
{
ctx.Next();
break;
}
else
{
// Unexpected character
tainted = true;
break;
}
} while (!ctx.AtEnd());
if (obj.Count == 0)
{
return null;
}
return obj;
}
private Object ParseValue()
{
Object token = null;
char c = ctx.SkipWhite();
switch (c)
{
case '"':
token = ParseQuotedString();
break;
case '{':
Dictionary<string, object> obj = ParseObject();
token = TryConvertToTypes(obj);
break;
case '[':
token = ParseArray();
break;
default:
if (Char.IsDigit(c) || c == '-')
{
token = ParseNumber();
}
else
{
String aux = ParseString();
if (aux.CompareTo("true") == 0)
{
token = true;
}
else if (aux.CompareTo("false") == 0)
{
token = false;
}
else if (aux.CompareTo("null") == 0)
{
token = null;
}
else
{
// Unexpected string
if (aux.Length == 0)
{
ctx.Next();
}
tainted = true;
token = null;
}
}
break;
}
return token;
}
private String CleanIdentifier(String input)
{
int i;
char c;
i = input.Length - 1;
if (i < 0)
{
return input;
}
c = input[i];
while (Char.IsLetter(c) || Char.IsDigit(c) || c == '_')
{
i--;
if (i < 0)
{
break;
}
c = input[i];
}
return input.Substring(i + 1);
}
#endregion
#region Public methods
public Object Parse(String text)
{
// Get the first object
ctx = new ParserContext(text);
tainted = false;
ctx.Mark();
Object obj = ParseValue();
if (ctx.AtEnd())
{
return obj;
}
// "But wait, there is more!"
int idx = 0;
String name = "";
String strInvalidPrev = "";
Dictionary<string, object> superObject = new Dictionary<string, object>();
do
{
// Add the object to the superObject
if (!tainted && name.Length > 0 && obj != null)
{
if (name.Length == 0)
{
name = String.Format("{0:D2}", idx);
}
superObject.Add(name, obj);
idx++;
name = "";
}
else
{
String strInvalid = ctx.GetMarked();
strInvalid = strInvalid.Trim();
if (strInvalidPrev.Length > 0
&& "=".CompareTo(strInvalid) == 0)
{
name = CleanIdentifier(strInvalidPrev);
}
else
{
name = "";
}
strInvalidPrev = strInvalid;
}
// Check end
if (ctx.AtEnd())
{
break;
}
// Get next object
tainted = false;
ctx.Mark();
obj = ParseValue();
} while (true);
return superObject;
}
#endregion
}
}

View File

@@ -0,0 +1,335 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace VAR.Focus.Web.Code.JSON
{
public class JSONWriter
{
#region Declarations
private bool indent = false;
private bool useTabForIndent = false;
private int indentChars = 4;
private int indentThresold = 3;
#endregion
#region Creator
public JSONWriter() { }
public JSONWriter(int indentChars)
{
this.indent = true;
this.indentChars = indentChars;
this.useTabForIndent = false;
}
public JSONWriter(bool useTabForIndent)
{
this.indent = true;
this.useTabForIndent = useTabForIndent;
}
#endregion
#region Private methods
private bool IsValue(Object obj)
{
if (obj == null)
{
return true;
}
if ((obj is float) || (obj is double) ||
(obj is System.Int16) || (obj is System.Int32) || (obj is System.Int64)
|| (obj is String) || (obj is Boolean))
{
return true;
}
return false;
}
private void WriteIndent(StringBuilder sbOutput, int level)
{
if (!indent)
{
return;
}
sbOutput.Append('\n');
if (useTabForIndent)
{
for (int i = 0; i < level; i++) { sbOutput.Append('\t'); }
}
else
{
int n = level * indentChars;
for (int i = 0; i < n; i++) { sbOutput.Append(' '); }
}
}
private void WriteString(StringBuilder sbOutput, String str)
{
sbOutput.Append('"');
char c;
int n = str.Length;
for (int i = 0; i < n; i++)
{
c = str[i];
if (c == '"') { sbOutput.Append("\\\""); }
else if (c == '\\') { sbOutput.Append("\\\\"); }
else if (c == '/') { sbOutput.Append("\\/"); }
else if (c == '\b') { sbOutput.Append("\\b"); }
else if (c == '\f') { sbOutput.Append("\\f"); }
else if (c == '\n') { sbOutput.Append("\\n"); }
else if (c == '\r') { sbOutput.Append("\\r"); }
else if (c == '\t') { sbOutput.Append("\\t"); }
else { sbOutput.Append(c); }
// FIXME: Unicode characters
}
sbOutput.Append('"');
}
private void WriteValue(StringBuilder sbOutput, Object obj, int level, bool useReflection)
{
if (obj == null || obj is DBNull)
{
// NULL
sbOutput.Append("null");
}
else if ((obj is float) || (obj is double) ||
(obj is System.Int16) || (obj is System.Int32) || (obj is System.Int64))
{
// Numbers
sbOutput.Append(obj.ToString());
}
else if (obj is String)
{
// Strings
WriteString(sbOutput, (String)obj);
}
else if (obj is Boolean)
{
// Booleans
sbOutput.Append(((Boolean)obj) ? "true" : "false");
}
else if (obj is DateTime)
{
// DateTime
sbOutput.Append('"');
sbOutput.Append(((DateTime)obj).ToString("yyyy-MM-ddTHH:mm:ssZ"));
sbOutput.Append('"');
}
else if (obj is IDictionary)
{
// Objects
WriteObject(sbOutput, obj, level);
}
else if (obj is IEnumerable)
{
// Array/List
WriteList(sbOutput, obj, level);
}
else
{
if (useReflection)
{
// Reflected object
WriteReflectedObject(sbOutput, obj, level);
}
else
{
WriteString(sbOutput, Convert.ToString(obj));
}
}
}
private void WriteList(StringBuilder sbOutput, Object obj, int level)
{
IEnumerable list = (IEnumerable)obj;
int n = 0;
// Check if it is a leaf object
bool isLeaf = true;
foreach (object childObj in list)
{
if (!IsValue(childObj))
{
isLeaf = false;
}
n++;
}
// Empty
if (n == 0)
{
sbOutput.Append("[ ]");
return;
}
// Write array
bool first = true;
sbOutput.Append("[ ");
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level + 1);
}
foreach (object childObj in list)
{
if (!first)
{
sbOutput.Append(", ");
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level + 1);
}
}
first = false;
WriteValue(sbOutput, childObj, level + 1, true);
}
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level);
}
sbOutput.Append(" ]");
}
private void WriteObject(StringBuilder sbOutput, Object obj, int level)
{
IDictionary map = (IDictionary)obj;
int n = map.Count;
// Empty
if (map.Count == 0)
{
sbOutput.Append("{ }");
return;
}
// Check if it is a leaf object
bool isLeaf = true;
foreach (object value in map.Values)
{
if (!IsValue(value))
{
isLeaf = false;
break;
}
}
// Write object
bool first = true;
sbOutput.Append("{ ");
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level + 1);
}
foreach (object key in map.Keys)
{
object value = map[key];
if (!first)
{
sbOutput.Append(", ");
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level + 1);
}
}
first = false;
WriteString(sbOutput, Convert.ToString(key));
sbOutput.Append(": ");
WriteValue(sbOutput, value, level + 1, true);
}
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level);
}
sbOutput.Append(" }");
}
private void WriteReflectedObject(StringBuilder sbOutput, Object obj, int level)
{
Type type = obj.GetType();
PropertyInfo[] rawProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
List<PropertyInfo> properties = new List<PropertyInfo>();
foreach (PropertyInfo property in rawProperties)
{
if (property.CanRead)
{
properties.Add(property);
}
}
int n = properties.Count;
// Empty
if (n == 0)
{
sbOutput.Append("{ }");
return;
}
// Check if it is a leaf object
bool isLeaf = true;
foreach (PropertyInfo property in properties)
{
object value = property.GetValue(obj, null);
if (!IsValue(value))
{
isLeaf = false;
break;
}
}
// Write object
bool first = true;
sbOutput.Append("{ ");
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level + 1);
}
foreach (PropertyInfo property in properties)
{
object value = null;
MethodInfo getMethod = property.GetGetMethod();
ParameterInfo[] parameters = getMethod.GetParameters();
if (parameters.Length == 0)
{
value = property.GetValue(obj, null);
}
if (!first)
{
sbOutput.Append(", ");
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level + 1);
}
}
first = false;
WriteString(sbOutput, property.Name);
sbOutput.Append(": ");
WriteValue(sbOutput, value, level + 1, false);
}
if (!isLeaf || n > indentThresold)
{
WriteIndent(sbOutput, level);
}
sbOutput.Append(" }");
}
#endregion
#region Public methods
public String Write(Object obj)
{
StringBuilder sbOutput = new StringBuilder();
WriteValue(sbOutput, obj, 0, true);
return sbOutput.ToString();
}
#endregion
}
}

View File

@@ -0,0 +1,84 @@
using System;
namespace VAR.Focus.Web.Code.JSON
{
public class ParserContext
{
#region Declarations
private String text;
private int length;
private int i;
private int markStart;
#endregion
#region Creator
public ParserContext(String text)
{
this.text = text;
this.length = text.Length;
this.i = 0;
this.markStart = 0;
}
#endregion
#region Public methods
public char SkipWhite()
{
while (i < length && Char.IsWhiteSpace(text[i]))
{
i++;
}
if (AtEnd())
{
return (char)0;
}
return text[i];
}
public char Next()
{
i++;
if (AtEnd())
{
return (char)0;
}
return text[i];
}
public bool AtEnd()
{
return i >= length;
}
public void Mark()
{
markStart = this.i;
}
public String GetMarked()
{
if (i < length && markStart < length)
{
return text.Substring(markStart, i);
}
else
{
if (markStart < length)
{
return text.Substring(markStart, length);
}
else
{
return string.Empty;
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,20 @@
using System.Web;
namespace VAR.Focus.Web.Code
{
public class ScriptsBundler : IHttpHandler
{
#region IHttpHandler
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
Bundler bundler = new Bundler(context.Server.MapPath("~/Scripts/"));
context.Response.ContentType = "text/javascript";
bundler.WriteResponse(context.Response.OutputStream);
}
#endregion
}
}

View File

@@ -0,0 +1,20 @@
using System.Web;
namespace VAR.Focus.Web.Code
{
public class StylesBundler : IHttpHandler
{
#region IHttpHandler
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
Bundler bundler = new Bundler(context.Server.MapPath("~/Styles/"));
context.Response.ContentType = "text/css";
bundler.WriteResponse(context.Response.OutputStream);
}
#endregion
}
}