/* * Box Social™ * http://boxsocial.net/ * Copyright © 2007, David Lachlan Smith * * $Id:$ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Web; using BoxSocial.IO; namespace BoxSocial.Internals { public sealed class Core { private Http http; private Mysql db; private Template template; private SessionState session; private int pageNo; private AppDomain coreDomain; private string pagePath; private GroupCollection pagePathParts; private UnixTime tz; private Prose prose; private Bbcode bbcode; private Functions functions; private Display display; private Email email; private Ajax ajax; private Linker uri; private Settings applicationSettings; internal TPage page; private PrimitivesCache userProfileCache; public delegate void HookHandler(HookEventArgs e); public delegate void LoadHandler(Core core, object sender); public delegate void PageHandler(Core core, object sender); public delegate bool CommentHandler(ItemKey itemKey, User viewer); public delegate void CommentCountHandler(ItemKey itemKey, int adjustment); public delegate void CommentPostedHandler(CommentPostedEventArgs e); public delegate void RatingHandler(ItemRatedEventArgs e); public delegate List PermissionGroupHandler(Core core, Primitive owner); public event HookHandler HeadHooks; public event HookHandler FootHooks; public event HookHandler PageHooks; public event LoadHandler LoadApplication; public event PermissionGroupHandler primitivePermissionGroupHook; private Dictionary primitiveTypes = new Dictionary(); private Dictionary primitiveAttributes = new Dictionary(); private List pages = new List(); private Dictionary commentHandles = new Dictionary(); private Dictionary ratingHandles = new Dictionary(); /// /// A cache of application entries. /// private Dictionary applicationEntryCache = new Dictionary(); /// /// The applicaton domain from which the web application is executed. /// public AppDomain CoreDomain { get { return coreDomain; } internal set { coreDomain = value; } } /// /// Current path path /// public string PagePath { get { return pagePath; } /*internal*/ set /* TODO: make internal*/ { pagePath = value; } } /// /// A collection of the structure of the current page /// public GroupCollection PagePathParts { get { return pagePathParts; } internal set { pagePathParts = value; } } /// /// Current page number for paginated pages /// public int PageNo { get { return pageNo; } internal set { pageNo = value; } } /// /// Gets the http object /// public Http Http { get { return http; } internal set { http = value; } } /// /// Gets the database abstraction object /// public Mysql Db { get { return db; } } /// /// Gets the page template /// public Template Template { get { return template; } internal set { template = value; } } /// /// Gets the current user session /// public SessionState Session { get { return session; } internal set { session = value; } } /// /// Gets the current timezone /// public UnixTime Tz { get { return tz; } internal set { tz = value; } } /// /// Gets the Language prose class /// public Prose Prose { get { return prose; } internal set { prose = value; } } /// /// Gets the BBcode class /// public Bbcode Bbcode { get { return bbcode; } internal set { bbcode = value; } } /// /// Gets the generic Functions class /// public Functions Functions { get { return functions; } internal set { functions = value; } } /// /// Gets the Display functions class /// public Display Display { get { return display; } internal set { display = value; } } /// /// Gets the Email class /// public Email Email { get { return email; } internal set { email = value; } } /// /// Gets the Ajax Interface /// public Ajax Ajax { get { return ajax; } internal set { ajax = value; } } /// /// Gets the Uri Builder /// public Linker Uri { get { return uri; } internal set { uri = value; } } public Settings ApplicationSettings { get { return applicationSettings; } internal set { applicationSettings = value; } } /// /// Creates a new session and associates it with Core /// /// /// Use by Installer to initiate a session into Core public void CreateNewSession(User user) { session = new SessionState(this, user); } /// /// Returns a list of user profiles cached in memory. /// public PrimitivesCache PrimitiveCache { get { return userProfileCache; } } public void LoadUserProfile(long userId) { userProfileCache.LoadUserProfile(userId); } public long LoadUserProfile(string username) { return userProfileCache.LoadUserProfile(username); } public void LoadUserProfiles(List userIds) { userProfileCache.LoadUserProfiles(userIds); } public List LoadUserProfiles(List usernames) { return userProfileCache.LoadUserProfiles(usernames); } public List GetPrimitivePermissionGroups(Primitive owner) { List ppgs = new List(); ppgs.AddRange(owner.GetPrimitivePermissionGroups()); foreach (Type type in primitiveTypes.Values) { if (type.GetMethod(type.Name + "_GetPrimitiveGroups", new Type[] {typeof(Core), typeof(Primitive)}) != null) { ppgs.AddRange((List)type.InvokeMember(type.Name + "_GetPrimitiveGroups", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { this, owner })); } } return ppgs; } /// /// Returns a list of application entries cached in memory. /// public Dictionary ApplicationEntries { get { return applicationEntryCache; } } public ApplicationEntry CallingApplication { get { string assemblyName = Assembly.GetCallingAssembly().GetName().Name; if (!ApplicationEntries.ContainsKey(assemblyName)) { LoadApplicationEntry(assemblyName); } return ApplicationEntries[assemblyName]; } } public long LoggedInMemberId { get { return User.GetMemberId(session.LoggedInMember); } } public bool IsAjax { get { return page.IsAjax; } } /// /// Loads the application entry for the calling application /// internal void LoadApplicationEntry(string assemblyName) { applicationEntryCache.Add(assemblyName, new ApplicationEntry(this, session.LoggedInMember, assemblyName)); } public Core(Mysql db, Template template) { HeadHooks += new HookHandler(Core_HeadHooks); FootHooks +=new HookHandler(Core_FootHooks); PageHooks += new HookHandler(Core_Hooks); LoadApplication += new LoadHandler(Core_LoadApplication); this.db = db; this.template = template; ItemKey.populateItemTypeCache(this); userProfileCache = new PrimitivesCache(this); AddPrimitiveType(typeof(User)); AddPrimitiveType(typeof(ApplicationEntry)); FindAllPrimitivesLoaded(); } public void Dispose() { userProfileCache = null; } void Core_LoadApplication(Core core, object sender) { } void Core_HeadHooks(HookEventArgs eventArgs) { } void Core_FootHooks(HookEventArgs eventArgs) { } void Core_Hooks(HookEventArgs eventArgs) { } public void InvokeHeadHooks(HookEventArgs eventArgs) { HeadHooks(eventArgs); } public void InvokeFootHooks(HookEventArgs eventArgs) { FootHooks(eventArgs); } public void InvokeHooks(HookEventArgs eventArgs) { PageHooks(eventArgs); } public void InvokeNaked(object sender) { LoadApplication(this, sender); } public void InvokeApplication(AppPrimitives primitive, object sender) { LoadApplication(this, sender); pages.Sort(); foreach (PageHandle page in pages) { if ((page.Primitives & primitive) == primitive || primitive == AppPrimitives.Any) { Regex rex = new Regex(page.Expression, RegexOptions.Compiled); Match pathMatch = rex.Match(PagePath); if (pathMatch.Success) { PagePathParts = pathMatch.Groups; page.Execute(this, sender); return; } } } Functions.Generate404(); } public bool CanPostComment(ItemKey itemKey) { if (commentHandles.ContainsKey(itemKey.TypeId)) { return commentHandles[itemKey.TypeId].CanPostComment(itemKey, session.LoggedInMember); } else { throw new InvalidItemException(); } } public bool CanDeleteComment(ItemKey itemKey) { if (commentHandles.ContainsKey(itemKey.TypeId)) { return commentHandles[itemKey.TypeId].CanDeleteComment(itemKey, session.LoggedInMember); } else { throw new InvalidItemException(); } } public void AdjustCommentCount(ItemKey itemKey, int adjustment) { if (commentHandles.ContainsKey(itemKey.TypeId)) { commentHandles[itemKey.TypeId].AdjustCommentCount(itemKey, adjustment); } else { throw new InvalidItemException(); } } public void CommentPosted(ItemKey itemKey, Comment comment, User poster) { if (commentHandles.ContainsKey(itemKey.TypeId)) { commentHandles[itemKey.TypeId].CommentPosted(comment, poster, itemKey); } else { throw new InvalidItemException(); } } public void CommentDeleted(ItemKey itemKey, Comment comment, User poster) { if (commentHandles.ContainsKey(itemKey.TypeId)) { commentHandles[itemKey.TypeId].CommentDeleted(comment, poster, itemKey); } else { throw new InvalidItemException(); } } public void ItemRated(ItemKey itemKey, int rating, User rater) { if (ratingHandles.ContainsKey(itemKey.TypeId)) { ratingHandles[itemKey.TypeId](new ItemRatedEventArgs(rating, rater, itemKey)); } else { throw new InvalidItemException(); } } public void RegisterApplicationPage(AppPrimitives primitives, string expression, Core.PageHandler pageHandle) { // register with a moderately high priority leaving room for higher priority registration // it doesn't matter if two pages have the same priority RegisterApplicationPage(primitives, expression, pageHandle, 8); } public void RegisterApplicationPage(AppPrimitives primitives, string expression, Core.PageHandler pageHandle, int order) { pages.Add(new PageHandle(primitives, expression, pageHandle, order)); } public void RegisterCommentHandle(long itemTypeId, Core.CommentHandler canPostComment, Core.CommentHandler canDeleteComment, Core.CommentCountHandler adjustCommentCount) { RegisterCommentHandle(itemTypeId, canPostComment, canDeleteComment, adjustCommentCount, null, null); } public void RegisterCommentHandle(long itemTypeId, Core.CommentHandler canPostComment, Core.CommentHandler canDeleteComment, Core.CommentCountHandler adjustCommentCount, Core.CommentPostedHandler commentPosted) { RegisterCommentHandle(itemTypeId, canPostComment, canDeleteComment, adjustCommentCount, commentPosted, null); } public void RegisterCommentHandle(long itemTypeId, Core.CommentHandler canPostComment, Core.CommentHandler canDeleteComment, Core.CommentCountHandler adjustCommentCount, Core.CommentPostedHandler commentPosted, Core.CommentPostedHandler commentDeleted) { commentHandles.Add(itemTypeId, new CommentHandle(itemTypeId, canPostComment, canDeleteComment, adjustCommentCount, commentPosted, commentDeleted)); } public void RegisterRatingHandle(long itemTypeId, Core.RatingHandler itemRated) { ratingHandles.Add(itemTypeId, itemRated); } private VariableCollection createHeadPanel() { return template.CreateChild("head_hook"); } private VariableCollection createFootPanel() { return template.CreateChild("foot_hook"); } private VariableCollection createMainPanel() { return template.CreateChild("app_panel"); } private VariableCollection createSidePanel() { return template.CreateChild("app_panel_side"); } public void AddHeadPanel(Template t) { VariableCollection panelVariableCollection = createHeadPanel(); panelVariableCollection.ParseRaw("BODY", t.ToString()); } public void AddFootPanel(Template t) { VariableCollection panelVariableCollection = createFootPanel(); panelVariableCollection.ParseRaw("BODY", t.ToString()); } public void AddMainPanel(Template t) { VariableCollection panelVariableCollection = createMainPanel(); panelVariableCollection.ParseRaw("BODY", t.ToString()); } public void AddSidePanel(Template t) { VariableCollection panelVariableCollection = createSidePanel(); panelVariableCollection.ParseRaw("BODY", t.ToString()); } public void AddPageAssembly(Assembly assembly) { template.AddPageAssembly(assembly); } public void AddPrimitiveType(Type type) { bool typeAdded = false; long primitiveTypeId = ItemKey.GetTypeId(type); if (type.IsSubclassOf(typeof(Primitive))) { foreach (object attr in type.GetCustomAttributes(typeof(PrimitiveAttribute), false)) { if (primitiveTypeId > 0) { if (!primitiveTypes.ContainsKey(primitiveTypeId)) { primitiveAttributes.Add(primitiveTypeId, (PrimitiveAttribute)attr); primitiveTypes.Add(primitiveTypeId, type); } typeAdded = true; } } if (!typeAdded) { if (!primitiveTypes.ContainsKey(primitiveTypeId)) { primitiveTypes.Add(primitiveTypeId, type); } } } } internal void FindAllPrimitivesLoaded() { AssemblyName[] assemblies = Assembly.Load(new AssemblyName("BoxSocial.FrontEnd")).GetReferencedAssemblies(); foreach (AssemblyName an in assemblies) { Assembly asm = Assembly.Load(an); Type[] types = asm.GetTypes(); foreach (Type type in types) { if (type.IsSubclassOf(typeof(Primitive))) { AddPrimitiveType(type); } } } } public Type GetPrimitiveType(long typeId) { if (primitiveTypes.ContainsKey(typeId)) { return primitiveTypes[typeId]; } else { return null; } } public PrimitiveAttribute GetPrimitiveAttributes(long typeId) { if (primitiveAttributes.ContainsKey(typeId)) { return primitiveAttributes[typeId]; } else { return null; } } public bool IsPrimitiveType(long typeId) { if (primitiveTypes.ContainsKey(typeId)) { return true; } else { return false; } } public void EndResponse() { page.EndResponse(); } /*public Access GetAccessFromItem(long itemId, string tableName, string columnPrefix) { DataTable itemTable = db.Query(string.Format("SELECT {2}item_id, {2}item_type, {2}access FROM {1} WHERE gi.{2}id = {0};", itemId, tableName, columnPrefix)); if (itemTable.Rows.Count == 1) { Primitive owner = null; switch ((string)itemTable.Rows[0][columnPrefix + "item_type"]) { case "USER": owner = new Member(db, (long)itemTable.Rows[0][columnPrefix + "item_id"]); break; case "GROUP": owner = new ZinZam.Groups.Group(db, (long)itemTable.Rows[0][columnPrefix + "item_id"]); break; case "NETWORK": owner = new Network(db, (long)itemTable.Rows[0][columnPrefix + "item_id"]); break; default: throw new InvalidItemException(); break; } Access photoAccess = new Access(core, (ushort)itemTable.Rows[0][columnPrefix + "access"], owner); return photoAccess; } }*/ } }