/*
* 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.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web;
using BoxSocial.IO;
namespace BoxSocial.Internals
{
///
/// An object that describes an application
///
public abstract class Application : MarshalByRefObject, IAppInfo
{
protected Core core;
public Application(Core core)
{
this.core = core;
RegisterPages();
}
public List GetSlugs()
{
List slugs = new List();
Type type = this.GetType();
foreach (MemberInfo mi in type.GetMembers(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic))
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(ShowAttribute)))
{
slugs.Add(((ShowAttribute)attr).Slug);
}
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(StaticShowAttribute)))
{
slugs.Add(((StaticShowAttribute)attr).Slug);
}
}
return slugs;
}
public List GetSlugInformation()
{
List slugs = new List();
Type type = this.GetType();
foreach (MemberInfo mi in type.GetMembers(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic))
{
// Show Attribute
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(ShowAttribute)))
{
slugs.Add(new ApplicationSlugInfo(((ShowAttribute)attr)));
}
// Static Show Attribute
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(StaticShowAttribute)))
{
slugs.Add(new ApplicationSlugInfo(((StaticShowAttribute)attr)));
}
}
return slugs;
}
public void RegisterPages()
{
Type type = this.GetType();
int i = 0;
foreach (MethodInfo mi in type.GetMethods(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic))
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(ShowAttribute)))
{
/*if (((ShowAttribute)attr).Primitives & primitives != primitives)
{
continue;
}*/
if (((ShowAttribute)attr).Order > 0)
{
core.RegisterApplicationPage(((ShowAttribute)attr).Primitives, ((ShowAttribute)attr).Slug, (Core.PageHandler)Core.PageHandler.CreateDelegate(typeof(Core.PageHandler), this, mi), ((ShowAttribute)attr).Order);
}
else
{
i++;
core.RegisterApplicationPage(((ShowAttribute)attr).Primitives, ((ShowAttribute)attr).Slug, (Core.PageHandler)Core.PageHandler.CreateDelegate(typeof(Core.PageHandler), this, mi), i);
}
}
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(StaticShowAttribute)))
{
if (((StaticShowAttribute)attr).Order > 0)
{
core.RegisterApplicationPage(AppPrimitives.None, ((StaticShowAttribute)attr).Slug, (Core.PageHandler)Core.PageHandler.CreateDelegate(typeof(Core.PageHandler), this, mi), ((StaticShowAttribute)attr).Order);
}
else
{
i++;
core.RegisterApplicationPage(AppPrimitives.None, ((StaticShowAttribute)attr).Slug, (Core.PageHandler)Core.PageHandler.CreateDelegate(typeof(Core.PageHandler), this, mi), i);
}
}
}
}
public void InstallPages(ApplicationInstallationInfo aii)
{
Type type = this.GetType();
int i = 0;
foreach (MethodInfo mi in type.GetMethods(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic))
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(ShowAttribute)))
{
i++;
if (string.IsNullOrEmpty(((ShowAttribute)attr).Stub))
{
aii.AddSlug(this.Stub, ((ShowAttribute)attr).Slug, ((ShowAttribute)attr).Primitives, false);
}
else
{
aii.AddSlug((ShowAttribute)attr);
}
}
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(StaticShowAttribute)))
{
i++;
aii.AddSlug((StaticShowAttribute)attr);
}
}
}
public static void InstallTypes(Core core, Assembly asm, long applicationId)
{
Type[] types = asm.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(Item)) || type.GetCustomAttributes(typeof(PseudoPrimitiveAttribute), false).Length == 1)
{
SelectQuery query = new SelectQuery(Item.GetTable(typeof(ItemType)));
query.AddCondition("type_namespace", type.FullName);
if (core.Db.Query(query).Rows.Count == 0)
{
InsertQuery iQuery = new InsertQuery(Item.GetTable(typeof(ItemType)));
iQuery.AddField("type_namespace", type.FullName);
iQuery.AddField("type_application_id", applicationId);
core.Db.Query(iQuery);
}
}
}
}
public static void InstallTables(Core core, Assembly asm)
{
Type[] types = asm.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(Item)) && type.GetCustomAttributes(typeof(DataTableAttribute), false).Length == 1)
{
string table = Item.GetTable(type);
if (!string.IsNullOrEmpty(table))
{
List dataFields = Item.GetFields(type);
if (core.Db.TableExists(table))
{
Dictionary columns = core.Db.GetColumns(table);
List newFields = new List();
foreach (DataFieldInfo field in dataFields)
{
if (!columns.ContainsKey(field.Name))
{
newFields.Add(field);
}
else
{
if ((!columns[field.Name].Type.Equals(field.Type)) || columns[field.Name].Length != field.Length)
{
core.Db.ChangeColumn(table, field);
}
}
}
if (newFields.Count > 0)
{
core.Db.AddColumns(table, newFields);
}
core.Db.UpdateTableKeys(table, dataFields);
}
else
{
core.Db.CreateTable(table, dataFields);
}
}
}
}
}
/*public static ApplicationEntry Entry
{
get
{
string assemblyName = Assembly.GetCallingAssembly().GetName().Name;
if (!Functions.core.ApplicationEntries.ContainsKey(assemblyName))
{
Functions.core.LoadApplicationEntry(assemblyName);
}
return Functions.core.ApplicationEntries[assemblyName];
}
}*/
public virtual void Initialise(Core core)
{
}
public abstract ApplicationInstallationInfo Install();
public ApplicationInstallationInfo GetInstallInfo()
{
ApplicationInstallationInfo aii = new ApplicationInstallationInfo();
Type[] types = this.GetType().Assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(AccountModule)))
{
foreach (Attribute attr in type.GetCustomAttributes(typeof(AccountModuleAttribute), false))
{
aii.AddModule(((AccountModuleAttribute)attr).Name);
}
}
}
List slugs = GetSlugInformation();
foreach (ApplicationSlugInfo slug in slugs)
{
aii.AddSlug(slug.Stub, slug.SlugEx, slug.Primitives, slug.IsStatic);
}
return aii;
}
public virtual AppPrimitives GetAppPrimitiveSupport()
{
return AppPrimitives.None;
}
///
/// Application title
///
public abstract string Title
{
get;
}
///
/// Default stub. When no stub is specified, the default one is used.
/// Can be overridden by specifying an overriding stub in the
/// appropriate Show attribute overload.
///
public abstract string Stub
{
get;
}
///
/// A description of the application
///
/// Uses BBcode
public abstract string Description
{
get;
}
///
/// A flag indicating whether the application uses the comments module
///
public abstract bool UsesComments
{
get;
}
///
/// A flag indicating whether the application uses the ratings module
///
public abstract bool UsesRatings
{
get;
}
public abstract Dictionary PageSlugs
{
get;
}
public Dictionary GetPageSlugs(AppPrimitives primitive)
{
Dictionary slugs = null;
if (PageSlugs != null)
{
slugs = PageSlugs;
}
else
{
slugs = new Dictionary();
}
/* Discover page slugs */
Type type = this.GetType();
foreach (MethodInfo mi in type.GetMethods(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic))
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mi, typeof(ShowAttribute)))
{
if ((((ShowAttribute)attr).Primitives & primitive) == primitive)
{
foreach (Attribute psAttr in Attribute.GetCustomAttributes(mi, typeof(PageSlugAttribute)))
{
slugs.Add(((ShowAttribute)attr).CleanSlug, ((PageSlugAttribute)psAttr).PageTitle);
}
}
}
}
return slugs;
}
///
/// A 16x16 image file for the application icon.
///
public abstract System.Drawing.Image Icon
{
get;
}
public abstract byte[] SvgIcon
{
get;
}
///
/// A stylesheet for the application
///
public abstract string StyleSheet
{
get;
}
///
/// Clientside javascript for the application
///
public abstract string JavaScript
{
get;
}
public static string InitialiseApplications(Core core, AppPrimitives primitive)
{
string debug = string.Empty;
Assembly[] assemblies = core.CoreDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(Application)))
{
Application newApplication = System.Activator.CreateInstance(type, new object[] {core}) as Application;
if (newApplication != null)
{
if ((newApplication.GetAppPrimitiveSupport() & primitive) == primitive
|| primitive == AppPrimitives.Any)
{
newApplication.Initialise(core);
debug += ", +" + type.ToString();
}
}
else
{
debug += ", -" + type.ToString();
}
}
}
}
return debug;
}
private static DataTable GetApplicationRows(Core core, Primitive owner)
{
//ushort readAccessLevel = owner.GetAccessLevel(core.Session.LoggedInMember);
long loggedIdUid = core.LoggedInMemberId;
/*DataTable userApplicationsTable = core.db.Query(string.Format(@"SELECT {0}, {1}
FROM applications ap, primitive_apps pa
WHERE (pa.item_id = {2} AND pa.item_type_id = {5})
AND pa.application_id = ap.application_id
AND ap.application_primitives & {6:0}",
ApplicationEntry.APPLICATION_FIELDS, ApplicationEntry.USER_APPLICATION_FIELDS, owner.Id, readAccessLevel, loggedIdUid, owner.TypeId, (byte)owner.AppPrimitive, ItemKey.GetTypeId(typeof(User))));*/
SelectQuery query = Item.GetSelectQueryStub(typeof(PrimitiveApplicationInfo));
query.AddFields(Item.GetFieldsPrefixed(typeof(ApplicationEntry)));
query.AddJoin(JoinTypes.Inner, Item.GetTable(typeof(ApplicationEntry)), "application_id", "application_id");
query.AddCondition("item_id", owner.ItemKey.Id);
query.AddCondition("item_type_id", owner.ItemKey.TypeId);
query.AddCondition(new QueryOperation("application_primitives", QueryOperations.BinaryAnd, (byte)owner.AppPrimitive), ConditionEquality.NotEqual, false);
DataTable userApplicationsTable = core.Db.Query(query);
return userApplicationsTable;
}
private static DataTable GetStaticApplicationRows(Core core)
{
SelectQuery query = Item.GetSelectQueryStub(typeof(ApplicationEntry));
DataTable staticApplicationsTable = core.Db.Query(query);
return staticApplicationsTable;
}
public static List GetModuleApplications(Core core, Primitive owner)
{
List applicationsList = new List();
Dictionary applicationsDictionary = new Dictionary();
DataTable userApplicationsTable = GetApplicationRows(core, owner);
if (userApplicationsTable.Rows.Count > 0)
{
List applicationIds = new List();
foreach (DataRow applicationRow in userApplicationsTable.Rows)
{
ApplicationEntry ae = new ApplicationEntry(core, applicationRow);
applicationsList.Add(ae);
applicationsDictionary.Add(ae.ApplicationId, ae);
applicationIds.Add(ae.Id);
}
SelectQuery query = ControlPanelModuleRegister.GetSelectQueryStub(typeof(ControlPanelModuleRegister));
query.AddCondition("application_id", ConditionEquality.In, applicationIds);
query.AddSort(SortOrder.Ascending, "application_id");
DataTable modulesTable = core.Db.Query(query);
foreach (DataRow moduleRow in modulesTable.Rows)
{
applicationsDictionary[(int)moduleRow["application_id"]].AddModule((string)moduleRow["module_module"]);
}
}
return applicationsList;
}
public static List GetApplications(Core core, Primitive owner)
{
List applicationsList = new List();
Dictionary applicationsDictionary = new Dictionary();
DataTable userApplicationsTable = GetApplicationRows(core, owner);
if (userApplicationsTable.Rows.Count > 0)
{
List applicationIds = new List();
foreach (DataRow applicationRow in userApplicationsTable.Rows)
{
ApplicationEntry ae = new ApplicationEntry(core, applicationRow);
applicationsList.Add(ae);
applicationsDictionary.Add(ae.ApplicationId, ae);
applicationIds.Add(ae.ApplicationId);
}
/*DataTable applicationSlugsTable = core.db.Query(string.Format(@"SELECT {0}
FROM application_slugs al
WHERE application_id IN ({1})
AND slug_primitives & {2:0}
ORDER BY application_id;",
ApplicationEntry.APPLICATION_SLUG_FIELDS, applicationIds, (byte)owner.AppPrimitive));*/
SelectQuery query = Item.GetSelectQueryStub(typeof(ApplicationSlug));
query.AddCondition("application_id", ConditionEquality.In, applicationIds);
query.AddCondition(new QueryOperation("slug_primitives", QueryOperations.BinaryAnd, (byte)owner.AppPrimitive), ConditionEquality.NotEqual, false);
query.AddCondition("slug_static", false);
query.AddSort(SortOrder.Ascending, "application_id");
DataTable applicationSlugsTable = core.Db.Query(query);
foreach (DataRow slugRow in applicationSlugsTable.Rows)
{
applicationsDictionary[(long)slugRow["application_id"]].LoadSlugEx((string)slugRow["slug_slug_ex"]);
}
}
return applicationsList;
}
public static List GetStaticApplications(Core core)
{
List applicationsList = new List();
Dictionary applicationsDictionary = new Dictionary();
DataTable userApplicationsTable = GetStaticApplicationRows(core);
if (userApplicationsTable.Rows.Count > 0)
{
List applicationIds = new List();
foreach (DataRow applicationRow in userApplicationsTable.Rows)
{
ApplicationEntry ae = new ApplicationEntry(core, applicationRow);
applicationsList.Add(ae);
applicationsDictionary.Add(ae.ApplicationId, ae);
applicationIds.Add(ae.ApplicationId);
}
/*DataTable applicationSlugsTable = core.db.Query(string.Format(@"SELECT {0}
FROM application_slugs al
WHERE application_id IN ({1})
AND slug_primitives & {2:0}
ORDER BY application_id;",
ApplicationEntry.APPLICATION_SLUG_FIELDS, applicationIds, (byte)owner.AppPrimitive));*/
SelectQuery query = Item.GetSelectQueryStub(typeof(ApplicationSlug));
query.AddCondition("application_id", ConditionEquality.In, applicationIds);
//query.AddCondition(new QueryOperation("slug_primitives", QueryOperations.BinaryAnd, (byte)AppPrimitives.None), ConditionEquality.NotEqual, false);
// Zero anyway, could be anything
query.AddCondition("slug_static", true);
query.AddSort(SortOrder.Ascending, "application_id");
DataTable applicationSlugsTable = core.Db.Query(query);
foreach (DataRow slugRow in applicationSlugsTable.Rows)
{
applicationsDictionary[(long)slugRow["application_id"]].LoadSlugEx((string)slugRow["slug_slug_ex"]);
}
}
return applicationsList;
}
public static void LoadApplications(List applicationsList)
{
foreach (ApplicationEntry ae in applicationsList)
{
try
{
System.Reflection.Assembly.Load(ae.AssemblyName);
}
catch
{
}
}
}
public static void LoadApplications(Core core, AppPrimitives primitive, string uri, List applicationsList)
{
Stopwatch load = new Stopwatch();
load.Start();
foreach (ApplicationEntry ae in applicationsList)
{
if (ae.SlugMatch(uri))
{
try
{
string assemblyPath;
if (ae.IsPrimitive)
{
assemblyPath = Path.Combine(core.Http.AssemblyPath, string.Format("{0}.dll", ae.AssemblyName));
}
else
{
assemblyPath = Path.Combine(core.Http.AssemblyPath, Path.Combine("applications", string.Format("{0}.dll", ae.AssemblyName)));
}
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(Application)))
{
Application newApplication = System.Activator.CreateInstance(type, new object[] {core}) as Application;
if (newApplication != null)
{
if ((newApplication.GetAppPrimitiveSupport() & primitive) == primitive
|| primitive == AppPrimitives.Any)
{
newApplication.Initialise(core);
core.Template.AddPageAssembly(assembly);
if (ae.HasStyleSheet)
{
VariableCollection styleSheetVariableCollection = core.Template.CreateChild("style_sheet_list");
styleSheetVariableCollection.Parse("URI", @"/styles/applications/" + ae.Key + @".css");
}
if (ae.HasJavascript)
{
VariableCollection javaScriptVariableCollection = core.Template.CreateChild("javascript_list");
javaScriptVariableCollection.Parse("URI", @"/scripts/" + ae.Key + @".js");
}
/* Initialise prose class for the application */
core.Prose.AddApplication(ae.Key);
}
}
}
}
}
catch (Exception ex)
{
//core.Http.Write(ex.ToString() + "
");
// -- DEBUG HERE FOR APPLICATION LOADER --
}
}
}
load.Stop();
}
public static Application GetApplication(Core core, AppPrimitives primitive, ApplicationEntry ae)
{
try
{
string assemblyPath;
if (ae.IsPrimitive)
{
if (core.Http != null)
{
assemblyPath = Path.Combine(core.Http.AssemblyPath, string.Format("{0}.dll", ae.AssemblyName));
}
else
{
//assemblyPath = string.Format("/var/www/bin/{0}.dll", ae.AssemblyName);
assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ae.AssemblyName + ".dll");
}
}
else
{
if (core.Http != null)
{
assemblyPath = Path.Combine(core.Http.AssemblyPath, Path.Combine("applications", string.Format("{0}.dll", ae.AssemblyName)));
}
else
{
//assemblyPath = string.Format("/var/www/bin/applications/{0}.dll", ae.AssemblyName);
assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ae.AssemblyName + ".dll");
}
}
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(Application)))
{
Application newApplication = System.Activator.CreateInstance(type, new object[] {core}) as Application;
if (newApplication != null)
{
return newApplication;
}
}
}
}
catch (Exception ex)
{
// TODO DEBUG HERE
Console.WriteLine(ex.ToString());
}
return null;
}
public static ApplicationEntry GetExecutingApplication(Core core, Primitive installee)
{
return new ApplicationEntry(core, installee, Assembly.GetCallingAssembly().GetName().Name);
}
/*public static ApplicationEntry GetExecutingApplication(Core core, Primitive installee)
{
return GetExecutingApplication(core, installee);
}*/
public static void LoadApplication(Core core, AppPrimitives primitive, ApplicationEntry ae)
{
Application newApplication = GetApplication(core, primitive, ae);
if (newApplication != null)
{
if ((newApplication.GetAppPrimitiveSupport() & primitive) == primitive
|| primitive == AppPrimitives.Any)
{
newApplication.Initialise(core);
if (ae.HasStyleSheet)
{
VariableCollection styleSheetVariableCollection = core.Template.CreateChild("style_sheet_list");
styleSheetVariableCollection.Parse("URI", @"/styles/applications/" + ae.Key + @".css");
}
if (ae.HasJavascript)
{
VariableCollection javaScriptVariableCollection = core.Template.CreateChild("javascript_list");
javaScriptVariableCollection.Parse("URI", @"/scripts/" + ae.Key + @".js");
}
/* Initialise prose class for the application */
core.Prose.AddApplication(ae.Key);
}
}
}
}
}