2009-06-19 07:39:16 +00:00
using System ;
using System.Collections ;
2010-03-03 17:13:42 +00:00
using System.Collections.Generic ;
2009-06-19 07:39:16 +00:00
using System.Diagnostics ;
using System.IO ;
using System.Net ;
using System.Reflection ;
2011-01-10 12:23:26 -01:00
using System.Security.Cryptography ;
2010-12-06 11:47:46 +00:00
using System.Security.Permissions ;
2009-06-19 07:39:16 +00:00
using System.Text ;
using System.Text.RegularExpressions ;
using System.Web ;
using System.Web.Caching ;
using System.Web.UI ;
using System.Web.UI.WebControls ;
using System.Xml ;
using System.Xml.Xsl ;
using umbraco.BusinessLogic ;
2010-12-06 13:49:34 +00:00
using umbraco.cms.businesslogic.macro ;
2009-06-19 07:39:16 +00:00
using umbraco.cms.businesslogic.member ;
using umbraco.DataLayer ;
using umbraco.interfaces ;
2010-12-06 11:47:46 +00:00
using umbraco.IO ;
2010-12-23 20:42:50 -01:00
using umbraco.NodeFactory ;
2010-12-06 11:47:46 +00:00
using umbraco.presentation.templateControls ;
2009-06-19 07:39:16 +00:00
using umbraco.presentation.xslt.Exslt ;
using umbraco.scripting ;
2010-12-06 11:47:46 +00:00
using Content = umbraco . cms . businesslogic . Content ;
using Macro = umbraco . cms . businesslogic . macro . Macro ;
2009-06-19 07:39:16 +00:00
namespace umbraco
{
/// <summary>
/// Summary description for macro.
/// </summary>
public class macro : Page
{
#region private properties
2010-12-06 11:47:46 +00:00
private static Hashtable _macroAlias = new Hashtable ( ) ;
/// <summary>Cache for <see cref="GetPredefinedXsltExtensions"/>.</summary>
private static Dictionary < string , object > m_PredefinedExtensions ;
private readonly string loadUserControlKey = "loadUserControl" ;
2009-06-19 07:39:16 +00:00
private readonly StringBuilder mContent = new StringBuilder ( ) ;
private readonly Cache macroCache = HttpRuntime . Cache ;
private readonly String macroCacheIdentifier = "umbMacro" ;
2010-12-06 11:47:46 +00:00
private readonly int macroType ;
2009-06-19 07:39:16 +00:00
private readonly string macrosAddedKey = "macrosAdded" ;
2010-12-06 11:47:46 +00:00
private readonly Hashtable propertyDefinitions = new Hashtable ( ) ;
2009-06-19 07:39:16 +00:00
// Macro-elements
private int macroID ;
2010-12-06 11:47:46 +00:00
private Hashtable properties = new Hashtable ( ) ;
private String scriptAssembly ;
2010-01-28 12:51:46 +00:00
private String scriptFile ;
2009-06-19 07:39:16 +00:00
private String scriptType ;
2010-12-06 11:47:46 +00:00
private String xsltFile ;
2009-06-19 07:39:16 +00:00
protected static ISqlHelper SqlHelper
{
2010-12-06 11:47:46 +00:00
get { return BusinessLogic . Application . SqlHelper ; }
2009-06-19 07:39:16 +00:00
}
#endregion
#region public properties
public int MacroID
{
set { macroID = value ; }
get { return macroID ; }
}
2010-12-06 11:47:46 +00:00
public bool CacheByPersonalization { set ; get ; }
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
public bool CacheByPage { set ; get ; }
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
public bool DontRenderInEditor { get ; set ; }
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
public int RefreshRate { set ; get ; }
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
public String Alias { set ; get ; }
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
public String Name { set ; get ; }
2009-06-19 07:39:16 +00:00
public String XsltFile
{
set { xsltFile = value ; }
get { return xsltFile ; }
}
2010-01-28 12:51:46 +00:00
public String ScriptFile
2009-06-19 07:39:16 +00:00
{
2010-01-28 12:51:46 +00:00
set { scriptFile = value ; }
get { return scriptFile ; }
2009-06-19 07:39:16 +00:00
}
public String ScriptType
{
set { scriptType = value ; }
get { return scriptType ; }
}
public String ScriptAssembly
{
set { scriptAssembly = value ; }
get { return scriptAssembly ; }
}
public Hashtable Properties
{
get { return properties ; }
set { properties = value ; }
}
public int MacroType
{
get { return macroType ; }
}
public String MacroContent
{
set { mContent . Append ( value ) ; }
get { return mContent . ToString ( ) ; }
}
#endregion
/// <summary>
/// Creates an empty macro object.
/// </summary>
public macro ( )
{
}
/// <summary>
/// Creates a macro object
/// </summary>
/// <param name="id">Specify the macro-id which should be loaded (from table macro)</param>
public macro ( int id )
{
macroID = id ;
if ( macroCache [ macroCacheIdentifier + id ] ! = null )
{
2010-12-06 11:47:46 +00:00
var tempMacro = ( macro ) macroCache [ macroCacheIdentifier + id ] ;
2009-06-19 07:39:16 +00:00
Name = tempMacro . Name ;
Alias = tempMacro . Alias ;
ScriptType = tempMacro . ScriptType ;
ScriptAssembly = tempMacro . ScriptAssembly ;
XsltFile = tempMacro . XsltFile ;
2010-01-28 12:51:46 +00:00
scriptFile = tempMacro . ScriptFile ;
2009-06-19 07:39:16 +00:00
Properties = tempMacro . Properties ;
propertyDefinitions = tempMacro . propertyDefinitions ;
RefreshRate = tempMacro . RefreshRate ;
CacheByPage = tempMacro . CacheByPage ;
CacheByPersonalization = tempMacro . CacheByPersonalization ;
DontRenderInEditor = tempMacro . DontRenderInEditor ;
HttpContext . Current . Trace . Write ( "umbracoMacro" ,
string . Format ( "Macro loaded from cache (ID: {0}, {1})" , id , Name ) ) ;
}
else
{
2010-12-06 11:47:46 +00:00
using (
IRecordsReader macroDef =
SqlHelper . ExecuteReader (
"select * from cmsMacro left join cmsMacroProperty property on property.macro = cmsMacro.id left join cmsMacroPropertyType editPropertyType on editPropertyType.id = property.macroPropertyType where cmsMacro.id = @macroID order by property.macroPropertySortOrder" ,
SqlHelper . CreateParameter ( "@macroID" , id ) ) )
2009-06-19 07:39:16 +00:00
{
2011-01-10 13:33:55 -01:00
bool hasRows = macroDef . Read ( ) ;
if ( ! hasRows )
2009-06-19 07:39:16 +00:00
HttpContext . Current . Trace . Warn ( "Macro" , "No definition found for id " + id ) ;
2011-01-10 13:33:55 -01:00
while ( hasRows )
2009-06-19 07:39:16 +00:00
{
string tmpStr ;
bool tmpBool ;
int tmpInt ;
if ( TryGetColumnBool ( macroDef , "macroCacheByPage" , out tmpBool ) )
CacheByPage = tmpBool ;
if ( TryGetColumnBool ( macroDef , "macroCachePersonalized" , out tmpBool ) )
CacheByPersonalization = tmpBool ;
if ( TryGetColumnBool ( macroDef , "macroDontRender" , out tmpBool ) )
DontRenderInEditor = tmpBool ;
if ( TryGetColumnInt32 ( macroDef , "macroRefreshRate" , out tmpInt ) )
RefreshRate = tmpInt ;
if ( TryGetColumnInt32 ( macroDef , "macroRefreshRate" , out tmpInt ) )
RefreshRate = tmpInt ;
if ( TryGetColumnString ( macroDef , "macroName" , out tmpStr ) )
Name = tmpStr ;
if ( TryGetColumnString ( macroDef , "macroAlias" , out tmpStr ) )
Alias = tmpStr ;
if ( TryGetColumnString ( macroDef , "macroScriptType" , out tmpStr ) )
ScriptType = tmpStr ;
if ( TryGetColumnString ( macroDef , "macroScriptAssembly" , out tmpStr ) )
ScriptAssembly = tmpStr ;
if ( TryGetColumnString ( macroDef , "macroXSLT" , out tmpStr ) )
XsltFile = tmpStr ;
2010-01-28 12:51:46 +00:00
2009-06-19 07:39:16 +00:00
if ( TryGetColumnString ( macroDef , "macroPython" , out tmpStr ) )
2010-01-28 12:51:46 +00:00
ScriptFile = tmpStr ;
2010-03-03 07:20:55 +00:00
2009-06-19 07:39:16 +00:00
if ( TryGetColumnString ( macroDef , "macroPropertyAlias" , out tmpStr ) )
{
string typeAlias ;
2010-12-06 11:47:46 +00:00
if ( TryGetColumnString ( macroDef , "macroPropertyTypeAlias" , out typeAlias ) & &
! properties . ContainsKey ( tmpStr ) )
2009-06-19 07:39:16 +00:00
properties . Add ( tmpStr , typeAlias ) ;
string baseType ;
2010-12-06 11:47:46 +00:00
if ( TryGetColumnString ( macroDef , "macroPropertyTypeBaseType" , out baseType ) & &
! propertyDefinitions . ContainsKey ( tmpStr ) )
2009-06-19 07:39:16 +00:00
propertyDefinitions . Add ( tmpStr , baseType ) ;
}
2011-01-10 13:33:55 -01:00
hasRows = macroDef . Read ( ) ;
2009-06-19 07:39:16 +00:00
}
}
// add current macro-object to cache
macroCache . Insert ( macroCacheIdentifier + id , this ) ;
}
2011-01-10 12:23:26 -01:00
macroType = ( int ) Macro . FindMacroType ( XsltFile , ScriptFile , ScriptType , ScriptAssembly ) ;
2009-06-19 07:39:16 +00:00
}
2010-12-06 11:47:46 +00:00
public override string ToString ( )
2009-06-19 07:39:16 +00:00
{
2010-12-06 11:47:46 +00:00
return Name ;
}
2010-03-03 07:20:55 +00:00
2010-12-06 11:47:46 +00:00
public static macro ReturnFromAlias ( string alias )
{
if ( _macroAlias . ContainsKey ( alias ) )
return new macro ( ( int ) _macroAlias [ alias ] ) ;
else
{
try
{
int macroID = Macro . GetByAlias ( alias ) . Id ;
_macroAlias . Add ( alias , macroID ) ;
return new macro ( macroID ) ;
}
catch
{
HttpContext . Current . Trace . Warn ( "macro" , "No macro with alias '" + alias + "' found" ) ;
return null ;
}
}
}
public static bool TryGetColumnString ( IRecordsReader reader , string columnName , out string value )
{
2009-06-19 07:39:16 +00:00
if ( reader . ContainsField ( columnName ) & & ! reader . IsNull ( columnName ) )
{
value = reader . GetString ( columnName ) ;
return true ;
}
else
{
value = string . Empty ;
return false ;
}
}
public static bool TryGetColumnInt32 ( IRecordsReader reader , string columnName , out int value )
{
if ( reader . ContainsField ( columnName ) & & ! reader . IsNull ( columnName ) )
{
value = reader . GetInt ( columnName ) ;
return true ;
}
else
{
value = - 1 ;
return false ;
}
}
public static bool TryGetColumnBool ( IRecordsReader reader , string columnName , out bool value )
{
if ( reader . ContainsField ( columnName ) & & ! reader . IsNull ( columnName ) )
{
value = reader . GetBoolean ( columnName ) ;
return true ;
}
else
{
value = false ;
return false ;
}
}
public static void ClearAliasCache ( )
{
_macroAlias = new Hashtable ( ) ;
}
/// <summary>
/// Deletes macro definition from cache.
/// </summary>
/// <returns>True if succesfull, false if nothing has been removed</returns>
public bool removeFromCache ( )
{
ClearAliasCache ( ) ;
if ( macroID > 0 )
{
if ( macroCache [ macroCacheIdentifier + macroID ] ! = null )
{
macroCache . Remove ( macroCacheIdentifier + macroID ) ;
return true ;
}
else
return false ;
}
else
return false ;
}
2011-01-10 12:23:26 -01:00
private string getCacheGuid ( MacroModel model , Hashtable pageElements , int pageId )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
string tempGuid = ! String . IsNullOrEmpty ( model . ScriptCode )
? Macro . GenerateCacheKeyFromCode ( model . ScriptCode ) + "-"
: model . Alias + "-" ;
2010-10-20 10:25:28 +00:00
2009-06-19 07:39:16 +00:00
if ( CacheByPage )
2010-10-20 10:25:28 +00:00
{
2009-06-19 07:39:16 +00:00
tempGuid = pageId + "-" ;
2010-10-20 10:25:28 +00:00
}
2009-06-19 07:39:16 +00:00
if ( CacheByPersonalization )
{
if ( Member . GetCurrentMember ( ) ! = null )
tempGuid + = "m" + Member . GetCurrentMember ( ) . Id + "-" ;
else
tempGuid + = "m" ;
}
2011-01-10 12:23:26 -01:00
foreach ( MacroPropertyModel prop in model . Properties )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
string attValue = prop . Value ;
2009-06-19 07:39:16 +00:00
if ( attValue . Length > 255 )
tempGuid + = attValue . Remove ( 255 , attValue . Length - 255 ) + "-" ;
else
tempGuid + = attValue + "-" ;
}
return tempGuid ;
}
public Control renderMacro ( Hashtable attributes , Hashtable pageElements , int pageId )
2011-01-10 12:23:26 -01:00
{
MacroModel m = ConvertToMacroModel ( attributes ) ;
return renderMacro ( m , pageElements , pageId ) ;
}
public Control renderMacro ( MacroModel model , Hashtable pageElements , int pageId )
2009-06-19 07:39:16 +00:00
{
HttpContext . Current . Trace . Write ( "renderMacro" ,
string . Format ( "Rendering started (macro: {0}, type: {1}, cacheRate: {2})" ,
2011-01-10 12:23:26 -01:00
Name , MacroType , model . CacheDuration ) ) ;
2009-06-19 07:39:16 +00:00
StateHelper . SetContextValue ( macrosAddedKey , StateHelper . GetContextValue < int > ( macrosAddedKey ) + 1 ) ;
2010-10-20 10:25:28 +00:00
String macroHtml = null ;
Control macroControl = null ;
2009-06-19 07:39:16 +00:00
2011-01-12 07:57:21 -01:00
model . CacheIdentifier = getCacheGuid ( model , pageElements , pageId ) ;
2009-06-19 07:39:16 +00:00
2011-01-10 12:23:26 -01:00
if ( model . CacheDuration > 0 )
2009-06-19 07:39:16 +00:00
{
2011-01-12 07:57:21 -01:00
macroHtml = macroCache [ "macroHtml_" + model . CacheIdentifier ] as String ;
2010-10-20 10:25:28 +00:00
if ( ! String . IsNullOrEmpty ( macroHtml ) )
2009-06-19 07:39:16 +00:00
{
2011-01-12 07:57:21 -01:00
macroHtml = macroCache [ "macroHtml_" + model . CacheIdentifier ] as String ;
HttpContext . Current . Trace . Write ( "renderMacro" , "Content loaded from cache ('" + model . CacheIdentifier + "')..." ) ;
2009-06-19 07:39:16 +00:00
}
}
2010-10-20 10:25:28 +00:00
if ( String . IsNullOrEmpty ( macroHtml ) )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
int macroType = model . MacroType ! = MacroTypes . Unknown ? ( int ) model . MacroType : MacroType ;
switch ( macroType )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
case ( int ) MacroTypes . UserControl :
2009-06-19 07:39:16 +00:00
try
{
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Usercontrol added (" + scriptType + ")" ) ;
2011-01-10 12:23:26 -01:00
macroControl = loadUserControl ( ScriptType , model , pageElements ) ;
2009-06-19 07:39:16 +00:00
break ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Error loading userControl (" + scriptType + ")" , e ) ;
2010-10-20 10:25:28 +00:00
macroControl = new LiteralControl ( "Error loading userControl '" + scriptType + "'" ) ;
2009-06-19 07:39:16 +00:00
break ;
}
2011-01-10 12:23:26 -01:00
case ( int ) MacroTypes . CustomControl :
2009-06-19 07:39:16 +00:00
try
{
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Custom control added (" + scriptType + ")" ) ;
HttpContext . Current . Trace . Write ( "umbracoMacro" , "ScriptAssembly (" + scriptAssembly + ")" ) ;
2011-01-10 12:23:26 -01:00
macroControl = loadControl ( scriptAssembly , ScriptType , model , pageElements ) ;
2009-06-19 07:39:16 +00:00
break ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Error loading customControl (Assembly: " + scriptAssembly +
", Type: '" + scriptType + "'" , e ) ;
2010-10-20 10:25:28 +00:00
macroControl =
2009-06-19 07:39:16 +00:00
new LiteralControl ( "Error loading customControl (Assembly: " + scriptAssembly +
", Type: '" +
scriptType + "'" ) ;
break ;
}
2011-01-10 12:23:26 -01:00
case ( int ) MacroTypes . XSLT :
macroControl = loadMacroXSLT ( this , model , pageElements ) ;
2009-06-19 07:39:16 +00:00
break ;
2011-01-10 12:23:26 -01:00
case ( int ) MacroTypes . Script :
2009-06-19 07:39:16 +00:00
try
{
2010-12-06 11:47:46 +00:00
HttpContext . Current . Trace . Write ( "umbracoMacro" ,
2010-12-06 13:49:34 +00:00
"MacroEngine script added (" + ScriptFile + ")" ) ;
2010-12-06 11:47:46 +00:00
macroControl = loadMacroDLR ( model ) ;
2009-06-19 07:39:16 +00:00
break ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
2010-12-06 13:49:34 +00:00
"Error loading MacroEngine script (file: " + ScriptFile +
2009-06-19 07:39:16 +00:00
", Type: '" + scriptType + "'" , e ) ;
2010-01-28 12:51:46 +00:00
2010-12-06 13:49:34 +00:00
var result = new LiteralControl ( "Error loading MacroEngine script (file: " + ScriptFile + ")" ) ;
2010-01-28 12:51:46 +00:00
/ *
string args = "<ul>" ;
foreach ( object key in attributes . Keys )
args + = "<li><strong>" + key . ToString ( ) + ": </strong> " + attributes [ key ] + "</li>" ;
foreach ( object key in pageElements . Keys )
args + = "<li><strong>" + key . ToString ( ) + ": </strong> " + pageElements [ key ] + "</li>" ;
args + = "</ul>" ;
result . Text + = args ;
* /
2010-10-20 10:25:28 +00:00
macroControl = result ;
2010-01-28 12:51:46 +00:00
2009-06-19 07:39:16 +00:00
break ;
}
default :
if ( GlobalSettings . DebugMode )
2010-10-20 10:25:28 +00:00
macroControl =
2009-06-19 07:39:16 +00:00
new LiteralControl ( "<Macro: " + Name + " (" + ScriptAssembly + "," + ScriptType +
")>" ) ;
break ;
}
// Add result to cache
2011-01-10 12:23:26 -01:00
if ( model . CacheDuration > 0 )
2009-06-19 07:39:16 +00:00
{
// do not add to cache if there's no member and it should cache by personalization
2011-01-10 12:23:26 -01:00
if ( ! model . CacheByMember | | ( model . CacheByMember & & Member . GetCurrentMember ( ) ! = null ) )
2010-10-20 10:25:28 +00:00
{
if ( macroControl ! = null )
{
2010-12-06 11:47:46 +00:00
using ( var sw = new StringWriter ( ) )
2010-10-20 10:25:28 +00:00
{
2010-12-06 11:47:46 +00:00
var hw = new HtmlTextWriter ( sw ) ;
2010-10-20 10:25:28 +00:00
macroControl . RenderControl ( hw ) ;
2011-01-12 07:57:21 -01:00
macroCache . Insert ( "macroHtml_" + model . CacheIdentifier ,
2010-12-06 11:47:46 +00:00
sw . ToString ( ) ,
null ,
2011-01-10 12:23:26 -01:00
DateTime . Now . AddSeconds ( model . CacheDuration ) ,
2010-12-06 11:47:46 +00:00
TimeSpan . Zero ,
CacheItemPriority . Low ,
null ) ;
2010-10-20 10:25:28 +00:00
}
}
}
2009-06-19 07:39:16 +00:00
}
}
2010-10-20 10:25:28 +00:00
else
{
macroControl = new LiteralControl ( macroHtml ) ;
}
return macroControl ;
2009-06-19 07:39:16 +00:00
}
public static XslCompiledTransform getXslt ( string XsltFile )
{
if ( HttpRuntime . Cache [ "macroXslt_" + XsltFile ] ! = null )
{
2010-03-03 07:20:55 +00:00
return ( XslCompiledTransform ) HttpRuntime . Cache [ "macroXslt_" + XsltFile ] ;
2009-06-19 07:39:16 +00:00
}
else
{
2010-12-06 11:47:46 +00:00
var xslReader =
2010-03-03 07:20:55 +00:00
new XmlTextReader ( IOHelper . MapPath ( SystemDirectories . Xslt + "/" + XsltFile ) ) ;
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
XslCompiledTransform macroXSLT = CreateXsltTransform ( xslReader , GlobalSettings . DebugMode ) ;
2009-06-19 07:39:16 +00:00
HttpRuntime . Cache . Insert (
"macroXslt_" + XsltFile ,
macroXSLT ,
2010-03-03 07:20:55 +00:00
new CacheDependency ( IOHelper . MapPath ( SystemDirectories . Xslt + "/" + XsltFile ) ) ) ;
2009-06-19 07:39:16 +00:00
return macroXSLT ;
}
}
2010-12-06 13:49:34 +00:00
public MacroModel ConvertToMacroModel ( Hashtable attributes )
{
MacroModel model = new MacroModel (
this . Name ,
this . Alias ,
this . ScriptAssembly ,
this . ScriptType ,
this . XsltFile ,
this . ScriptFile ,
this . RefreshRate ,
this . CacheByPage ,
this . CacheByPersonalization
) ;
foreach ( string key in attributes . Keys )
{
model . Properties . Add ( new MacroPropertyModel ( key , attributes [ key ] . ToString ( ) ) ) ;
}
return model ;
}
2009-06-19 07:39:16 +00:00
public static XslCompiledTransform CreateXsltTransform ( XmlTextReader xslReader , bool debugMode )
{
2010-12-06 11:47:46 +00:00
var macroXSLT = new XslCompiledTransform ( debugMode ) ;
var xslResolver = new XmlUrlResolver ( ) ;
2009-06-19 07:39:16 +00:00
xslResolver . Credentials = CredentialCache . DefaultCredentials ;
xslReader . EntityHandling = EntityHandling . ExpandEntities ;
2010-03-03 07:20:55 +00:00
try
{
if ( GlobalSettings . ApplicationTrustLevel > AspNetHostingPermissionLevel . Medium )
{
2010-03-03 02:50:06 +00:00
macroXSLT . Load ( xslReader , XsltSettings . TrustedXslt , xslResolver ) ;
2010-03-03 07:20:55 +00:00
}
else
{
2010-03-03 02:50:06 +00:00
macroXSLT . Load ( xslReader , XsltSettings . Default , xslResolver ) ;
}
2010-03-03 07:20:55 +00:00
}
finally
{
2009-06-19 07:39:16 +00:00
xslReader . Close ( ) ;
}
return macroXSLT ;
}
public static void unloadXslt ( string XsltFile )
{
if ( HttpRuntime . Cache [ "macroXslt_" + XsltFile ] ! = null )
HttpRuntime . Cache . Remove ( "macroXslt_" + XsltFile ) ;
}
2010-01-28 12:51:46 +00:00
private Hashtable keysToLowerCase ( Hashtable input )
{
2010-12-06 11:47:46 +00:00
var retval = new Hashtable ( ) ;
2010-01-28 12:51:46 +00:00
foreach ( object key in input . Keys )
retval . Add ( key . ToString ( ) . ToLower ( ) , input [ key ] ) ;
return retval ;
}
2010-12-06 11:47:46 +00:00
2011-01-10 12:23:26 -01:00
public Control loadMacroXSLT ( macro macro , MacroModel model , Hashtable pageElements )
2009-06-19 07:39:16 +00:00
{
if ( XsltFile . Trim ( ) ! = string . Empty )
{
// Get main XML
XmlDocument umbracoXML = content . Instance . XmlContent ;
// Create XML document for Macro
2010-12-06 11:47:46 +00:00
var macroXML = new XmlDocument ( ) ;
2009-06-19 07:39:16 +00:00
macroXML . LoadXml ( "<macro/>" ) ;
foreach ( DictionaryEntry macroDef in macro . properties )
{
2011-01-12 07:57:21 -01:00
var prop = model . Properties . Find ( m = > m . Key = = ( string ) macroDef . Key . ToString ( ) . ToLower ( ) ) ;
2011-01-10 12:23:26 -01:00
string propValue = prop ! = null
? helper . parseAttribute ( pageElements , prop . Value )
: helper . parseAttribute ( pageElements , "" ) ;
if ( ! String . IsNullOrEmpty ( propValue ) )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
if ( propValue ! = string . Empty )
2009-06-19 07:39:16 +00:00
addMacroXmlNode ( umbracoXML , macroXML , macroDef . Key . ToString ( ) , macroDef . Value . ToString ( ) ,
2011-01-10 12:23:26 -01:00
propValue ) ;
2009-06-19 07:39:16 +00:00
else
addMacroXmlNode ( umbracoXML , macroXML , macroDef . Key . ToString ( ) , macroDef . Value . ToString ( ) ,
string . Empty ) ;
}
}
if ( HttpContext . Current . Request . QueryString [ "umbDebug" ] ! = null & & GlobalSettings . DebugMode )
{
return
new LiteralControl ( "<div style=\"border: 2px solid green; padding: 5px;\"><b>Debug from " +
macro . Name +
"</b><br/><p>" + Page . Server . HtmlEncode ( macroXML . OuterXml ) + "</p></div>" ) ;
}
else
{
try
{
XslCompiledTransform xsltFile = getXslt ( XsltFile ) ;
try
{
Control result = CreateControlsFromText ( GetXsltTransformResult ( macroXML , xsltFile ) ) ;
HttpContext . Current . Trace . Write ( "umbracoMacro" , "After performing transformation" ) ;
return result ;
}
catch ( Exception e )
{
// inner exception code by Daniel Lindstr<74> m from SBBS.se
2010-05-11 05:27:28 +00:00
Exception ie = e ;
2009-06-19 07:39:16 +00:00
while ( ie ! = null )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro InnerException" , ie . Message , ie ) ;
ie = ie . InnerException ;
}
return new LiteralControl ( "Error parsing XSLT file: \\xslt\\" + XsltFile ) ;
}
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" , "Error loading XSLT " + xsltFile , e ) ;
return new LiteralControl ( "Error reading XSLT file: \\xslt\\" + XsltFile ) ;
}
}
}
else
{
Page . Trace . Warn ( "macro" , "Xslt is empty" ) ;
return new LiteralControl ( string . Empty ) ;
}
}
/// <summary>
/// Parses the text for umbraco Item controls that need to be rendered.
/// </summary>
/// <param name="text">The text to parse.</param>
/// <returns>A control containing the parsed text.</returns>
protected Control CreateControlsFromText ( string text )
{
// the beginning and end tags
const string tagStart = "[[[[umbraco:Item" ;
const string tagEnd = "]]]]" ;
// container that will hold parsed controls
2010-12-06 11:47:46 +00:00
var container = new PlaceHolder ( ) ;
2009-06-19 07:39:16 +00:00
// loop through all text
int textPos = 0 ;
while ( textPos < text . Length )
{
// try to find an item tag, carefully staying inside the string bounds (- 1)
int tagStartPos = text . IndexOf ( tagStart , textPos ) ;
int tagEndPos = tagStartPos < 0 ? - 1 : text . IndexOf ( tagEnd , tagStartPos + tagStart . Length - 1 ) ;
// item tag found?
if ( tagStartPos > = 0 & & tagEndPos > = 0 )
{
// add the preceding text as a literal control
if ( tagStartPos > textPos )
container . Controls . Add ( new LiteralControl ( text . Substring ( textPos , tagStartPos - textPos ) ) ) ;
// extract the tag and parse it
string tag = text . Substring ( tagStartPos , ( tagEndPos + tagEnd . Length ) - tagStartPos ) ;
Hashtable attributes = helper . ReturnAttributes ( tag ) ;
// create item with the parameters specified in the tag
2010-12-06 11:47:46 +00:00
var item = new Item ( ) ;
2009-06-19 07:39:16 +00:00
item . NodeId = helper . FindAttribute ( attributes , "nodeid" ) ;
item . Field = helper . FindAttribute ( attributes , "field" ) ;
item . Xslt = helper . FindAttribute ( attributes , "xslt" ) ;
item . XsltDisableEscaping = helper . FindAttribute ( attributes , "xsltdisableescaping" ) = = "true" ;
container . Controls . Add ( item ) ;
// advance past the end of the tag
textPos = tagEndPos + tagEnd . Length ;
}
else
{
// no more tags found, just add the remaning text
container . Controls . Add ( new LiteralControl ( text . Substring ( textPos ) ) ) ;
textPos = text . Length ;
}
}
return container ;
}
public static string GetXsltTransformResult ( XmlDocument macroXML , XslCompiledTransform xslt )
{
return GetXsltTransformResult ( macroXML , xslt , null ) ;
}
2010-12-06 11:47:46 +00:00
public static string GetXsltTransformResult ( XmlDocument macroXML , XslCompiledTransform xslt ,
Dictionary < string , object > parameters )
2009-06-19 07:39:16 +00:00
{
TextWriter tw = new StringWriter ( ) ;
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Before adding extensions" ) ;
XsltArgumentList xslArgs ;
xslArgs = AddXsltExtensions ( ) ;
2010-12-06 11:47:46 +00:00
var lib = new library ( ) ;
2009-06-19 07:39:16 +00:00
xslArgs . AddExtensionObject ( "urn:umbraco.library" , lib ) ;
HttpContext . Current . Trace . Write ( "umbracoMacro" , "After adding extensions" ) ;
// Add parameters
if ( parameters = = null | | ! parameters . ContainsKey ( "currentPage" ) )
{
xslArgs . AddParam ( "currentPage" , string . Empty , library . GetXmlNodeCurrent ( ) ) ;
}
if ( parameters ! = null )
{
2010-12-06 11:47:46 +00:00
foreach ( var parameter in parameters )
2009-06-19 07:39:16 +00:00
xslArgs . AddParam ( parameter . Key , string . Empty , parameter . Value ) ;
}
// Do transformation
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Before performing transformation" ) ;
xslt . Transform ( macroXML . CreateNavigator ( ) , xslArgs , tw ) ;
2010-07-20 08:39:13 +00:00
return IOHelper . ResolveUrlsFromTextString ( tw . ToString ( ) ) ;
2009-06-19 07:39:16 +00:00
}
public static XsltArgumentList AddXsltExtensions ( )
{
return AddMacroXsltExtensions ( ) ;
}
/// <summary>
/// Gets a collection of all XSLT extensions for macros, including predefined extensions.
/// </summary>
/// <returns>A dictionary of name/extension instance pairs.</returns>
public static Dictionary < string , object > GetXsltExtensions ( )
{
// fill a dictionary with the predefined extensions
2010-12-06 11:47:46 +00:00
var extensions = new Dictionary < string , object > ( GetPredefinedXsltExtensions ( ) ) ;
2009-06-19 07:39:16 +00:00
// Load the XSLT extensions configuration
2010-12-06 11:47:46 +00:00
var xsltExt = new XmlDocument ( ) ;
2010-03-03 07:20:55 +00:00
xsltExt . Load ( IOHelper . MapPath ( SystemDirectories . Config + "/xsltExtensions.config" ) ) ;
2009-06-19 07:39:16 +00:00
// add all descendants of the XsltExtensions element
foreach ( XmlNode xsltEx in xsltExt . SelectSingleNode ( "/XsltExtensions" ) )
{
if ( xsltEx . NodeType = = XmlNodeType . Element )
{
Debug . Assert ( xsltEx . Attributes [ "assembly" ] ! = null , "Extension attribute 'assembly' not specified." ) ;
Debug . Assert ( xsltEx . Attributes [ "type" ] ! = null , "Extension attribute 'type' not specified." ) ;
Debug . Assert ( xsltEx . Attributes [ "alias" ] ! = null , "Extension attribute 'alias' not specified." ) ;
// load the extension assembly
2010-12-06 11:47:46 +00:00
string extensionFile =
IOHelper . MapPath ( string . Format ( "{0}/{1}.dll" , SystemDirectories . Bin ,
xsltEx . Attributes [ "assembly" ] . Value ) ) ;
2010-03-03 07:20:55 +00:00
2009-06-19 07:39:16 +00:00
Assembly extensionAssembly ;
try
{
extensionAssembly = Assembly . LoadFrom ( extensionFile ) ;
}
2010-03-03 07:20:55 +00:00
catch ( Exception ex )
2009-06-19 07:39:16 +00:00
{
2010-12-06 11:47:46 +00:00
throw new Exception (
String . Format (
"Could not load assembly {0} for XSLT extension {1}. Please check config/xsltExentions.config." ,
extensionFile , xsltEx . Attributes [ "alias" ] . Value ) , ex ) ;
2009-06-19 07:39:16 +00:00
}
// load the extension type
Type extensionType = extensionAssembly . GetType ( xsltEx . Attributes [ "type" ] . Value ) ;
2010-03-03 07:20:55 +00:00
if ( extensionType = = null )
2010-12-06 11:47:46 +00:00
throw new Exception (
String . Format (
"Could not load type {0} ({1}) for XSLT extension {1}. Please check config/xsltExentions.config." ,
xsltEx . Attributes [ "type" ] . Value , extensionFile , xsltEx . Attributes [ "alias" ] . Value ) ) ;
2009-06-19 07:39:16 +00:00
// create an instance and add it to the extensions list
extensions . Add ( xsltEx . Attributes [ "alias" ] . Value , Activator . CreateInstance ( extensionType ) ) ;
}
}
2010-12-16 11:15:56 -01:00
//also get types marked with XsltExtension attribute
2010-05-10 14:34:18 +00:00
try
{
2010-12-16 11:15:56 -01:00
foreach ( Type xsltType in BusinessLogic . Utils . TypeFinder . FindClassesMarkedWithAttribute ( typeof ( XsltExtensionAttribute ) ) )
2010-05-10 14:34:18 +00:00
{
2010-12-16 11:15:56 -01:00
object [ ] tpAttributes = xsltType . GetCustomAttributes ( typeof ( XsltExtensionAttribute ) , true ) ;
foreach ( XsltExtensionAttribute tpAttribute in tpAttributes )
2010-05-10 14:34:18 +00:00
{
2010-12-16 11:15:56 -01:00
if ( tpAttribute . Namespace ! = String . Empty )
2010-05-10 14:34:18 +00:00
{
2010-12-16 11:15:56 -01:00
extensions . Add ( tpAttribute . Namespace , Activator . CreateInstance ( xsltType ) ) ;
2010-05-10 14:34:18 +00:00
}
else
{
2010-12-16 11:15:56 -01:00
extensions . Add ( xsltType . FullName , Activator . CreateInstance ( xsltType ) ) ;
2010-03-03 02:50:06 +00:00
}
}
2010-05-10 14:34:18 +00:00
}
2010-03-03 02:50:06 +00:00
}
2010-12-16 11:15:56 -01:00
catch { }
//Assembly appCodeAssembly;
//try
//{
// if (Directory.Exists(GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "App_Code"))
// {
// if (Directory.GetFiles(GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "App_Code",
// "*.*",
// SearchOption.AllDirectories).Length > 0)
// {
// appCodeAssembly = Assembly.Load("__code");
// Type[] appCodeType = appCodeAssembly.GetExportedTypes();
// if (appCodeType.Length == 0)
// {
// Log.Add(LogTypes.System, Node.GetCurrent().Id,
// String.Format(
// "Could not load types in App_Code ({0}) for XSLT extensions. Ensure you have used the public keyword to ensure class and method exposure.",
// appCodeAssembly.FullName));
// }
// else
// {
// // create an instance and add it to the extensions list
// foreach (Type tp in appCodeType)
// {
// object[] tpAttributes = tp.GetCustomAttributes(typeof(XsltExtensionAttribute), true);
// foreach (XsltExtensionAttribute tpAttribute in tpAttributes)
// {
// if (tpAttribute.Namespace != String.Empty)
// {
// extensions.Add(tpAttribute.Namespace, Activator.CreateInstance(tp));
// }
// else
// {
// extensions.Add(tp.FullName, Activator.CreateInstance(tp));
// }
// }
// }
// }
// }
// }
// else
// {
// Directory.CreateDirectory(GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "App_Code");
// }
//}
//catch (FileNotFoundException)
//{
// //Do nothing - just means there's nothing to load.
//}
//catch (Exception ex)
//{
// throw new Exception("Could not load App_Code classes for XSLT extensions.", ex);
//}
2010-03-03 02:50:06 +00:00
2009-06-19 07:39:16 +00:00
return extensions ;
}
/// <summary>
/// Gets the predefined XSLT extensions.
/// </summary>
/// <remarks>
/// This is a legacy list of EXSLT extensions.
/// The Umbraco library is not included, because its instance is page specific.
/// </remarks>
/// <returns>A dictionary of name/extension instance pairs.</returns>
public static Dictionary < string , object > GetPredefinedXsltExtensions ( )
{
if ( m_PredefinedExtensions = = null )
{
m_PredefinedExtensions = new Dictionary < string , object > ( ) ;
// add predefined EXSLT extensions
m_PredefinedExtensions . Add ( "Exslt.ExsltCommon" , new ExsltCommon ( ) ) ;
m_PredefinedExtensions . Add ( "Exslt.ExsltDatesAndTimes" , new ExsltDatesAndTimes ( ) ) ;
m_PredefinedExtensions . Add ( "Exslt.ExsltMath" , new ExsltMath ( ) ) ;
m_PredefinedExtensions . Add ( "Exslt.ExsltRegularExpressions" , new ExsltRegularExpressions ( ) ) ;
m_PredefinedExtensions . Add ( "Exslt.ExsltStrings" , new ExsltStrings ( ) ) ;
m_PredefinedExtensions . Add ( "Exslt.ExsltSets" , new ExsltSets ( ) ) ;
}
return m_PredefinedExtensions ;
}
/// <summary>
/// Returns an XSLT argument list with all XSLT extensions added,
/// both predefined and configured ones.
/// </summary>
/// <returns>A new XSLT argument list.</returns>
public static XsltArgumentList AddMacroXsltExtensions ( )
{
2010-12-06 11:47:46 +00:00
var xslArgs = new XsltArgumentList ( ) ;
2009-06-19 07:39:16 +00:00
2010-12-06 11:47:46 +00:00
foreach ( var extension in GetXsltExtensions ( ) )
2009-06-19 07:39:16 +00:00
{
string extensionNamespace = "urn:" + extension . Key ;
xslArgs . AddExtensionObject ( extensionNamespace , extension . Value ) ;
HttpContext . Current . Trace . Write ( "umbracoXsltExtension" ,
String . Format ( "Extension added: {0}, {1}" ,
2010-12-06 11:47:46 +00:00
extensionNamespace , extension . Value . GetType ( ) . Name ) ) ;
2009-06-19 07:39:16 +00:00
}
return xslArgs ;
}
private void addMacroXmlNode ( XmlDocument umbracoXML , XmlDocument macroXML , String macroPropertyAlias ,
String macroPropertyType , String macroPropertyValue )
{
XmlNode macroXmlNode = macroXML . CreateNode ( XmlNodeType . Element , macroPropertyAlias , string . Empty ) ;
2010-12-06 11:47:46 +00:00
var x = new XmlDocument ( ) ;
2009-06-19 07:39:16 +00:00
int currentID = - 1 ;
// If no value is passed, then use the current pageID as value
if ( macroPropertyValue = = string . Empty )
{
2010-12-06 11:47:46 +00:00
var umbPage = ( page ) HttpContext . Current . Items [ "umbPageObject" ] ;
2009-06-19 07:39:16 +00:00
if ( umbPage = = null )
return ;
currentID = umbPage . PageID ;
}
HttpContext . Current . Trace . Write ( "umbracoMacro" ,
"Xslt node adding search start (" + macroPropertyAlias + ",'" +
macroPropertyValue + "')" ) ;
switch ( macroPropertyType )
{
case "contentTree" :
XmlAttribute nodeID = macroXML . CreateAttribute ( "nodeID" ) ;
if ( macroPropertyValue ! = string . Empty )
nodeID . Value = macroPropertyValue ;
else
nodeID . Value = currentID . ToString ( ) ;
macroXmlNode . Attributes . SetNamedItem ( nodeID ) ;
// Get subs
try
{
macroXmlNode . AppendChild ( macroXML . ImportNode ( umbracoXML . GetElementById ( nodeID . Value ) , true ) ) ;
}
catch
{
break ;
}
break ;
case "contentCurrent" :
x . LoadXml ( "<nodes/>" ) ;
XmlNode currentNode ;
if ( macroPropertyValue ! = string . Empty )
currentNode = macroXML . ImportNode ( umbracoXML . GetElementById ( macroPropertyValue ) , true ) ;
else
currentNode = macroXML . ImportNode ( umbracoXML . GetElementById ( currentID . ToString ( ) ) , true ) ;
// remove all sub content nodes
foreach ( XmlNode n in currentNode . SelectNodes ( "./node" ) )
currentNode . RemoveChild ( n ) ;
macroXmlNode . AppendChild ( currentNode ) ;
break ;
case "contentSubs" :
x . LoadXml ( "<nodes/>" ) ;
if ( macroPropertyValue ! = string . Empty )
x . FirstChild . AppendChild ( x . ImportNode ( umbracoXML . GetElementById ( macroPropertyValue ) , true ) ) ;
else
x . FirstChild . AppendChild ( x . ImportNode ( umbracoXML . GetElementById ( currentID . ToString ( ) ) , true ) ) ;
macroXmlNode . InnerXml = transformMacroXML ( x , "macroGetSubs.xsl" ) ;
break ;
case "contentAll" :
x . ImportNode ( umbracoXML . DocumentElement . LastChild , true ) ;
break ;
case "contentRandom" :
XmlNode source = umbracoXML . GetElementById ( macroPropertyValue ) ;
if ( source ! = null )
{
XmlNodeList sourceList = source . SelectNodes ( "node" ) ;
if ( sourceList . Count > 0 )
{
int rndNumber ;
Random r = library . GetRandom ( ) ;
lock ( r )
{
rndNumber = r . Next ( sourceList . Count ) ;
}
XmlNode node = macroXML . ImportNode ( sourceList [ rndNumber ] , true ) ;
// remove all sub content nodes
foreach ( XmlNode n in node . SelectNodes ( "./node" ) )
node . RemoveChild ( n ) ;
macroXmlNode . AppendChild ( node ) ;
break ;
}
else
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Error adding random node - parent (" + macroPropertyValue +
") doesn't have children!" ) ;
}
else
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Error adding random node - parent (" + macroPropertyValue +
") doesn't exists!" ) ;
break ;
case "mediaCurrent" :
2010-12-06 11:47:46 +00:00
var c = new Content ( int . Parse ( macroPropertyValue ) ) ;
2009-06-19 07:39:16 +00:00
macroXmlNode . AppendChild ( macroXML . ImportNode ( c . ToXml ( content . Instance . XmlContent , false ) , true ) ) ;
break ;
default :
2010-12-06 11:47:46 +00:00
macroXmlNode . InnerText = HttpContext . Current . Server . HtmlDecode ( macroPropertyValue ) ;
2009-06-19 07:39:16 +00:00
break ;
}
macroXML . FirstChild . AppendChild ( macroXmlNode ) ;
}
private string transformMacroXML ( XmlDocument xmlSource , string xslt_File )
{
2010-12-06 11:47:46 +00:00
var sb = new StringBuilder ( ) ;
var sw = new StringWriter ( sb ) ;
2009-06-19 07:39:16 +00:00
XslCompiledTransform result = getXslt ( xslt_File ) ;
//XmlDocument xslDoc = new XmlDocument();
result . Transform ( xmlSource . CreateNavigator ( ) , null , sw ) ;
if ( sw . ToString ( ) ! = string . Empty )
return sw . ToString ( ) ;
else
return string . Empty ;
}
2011-01-10 12:23:26 -01:00
public Control loadMacroDLR ( MacroModel macro )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
TraceInfo ( "umbracoMacro" , "Loading IMacroEngine script" ) ;
2010-12-06 11:47:46 +00:00
var ret = new LiteralControl ( ) ;
2011-01-12 07:57:21 -01:00
if ( ! String . IsNullOrEmpty ( macro . ScriptCode ) )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
IMacroEngine engine = MacroEngineFactory . GetByExtension ( macro . ScriptLanguage ) ;
ret . Text = engine . Execute (
macro ,
Node . GetCurrent ( ) ) ;
2009-06-19 07:39:16 +00:00
}
2011-01-10 12:23:26 -01:00
else
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
string path = IOHelper . MapPath ( SystemDirectories . Python + "/" + macro . ScriptName ) ;
IMacroEngine engine = MacroEngineFactory . GetByFilename ( path ) ;
ret . Text = engine . Execute ( macro , Node . GetCurrent ( ) ) ;
2009-06-19 07:39:16 +00:00
}
2011-01-10 12:23:26 -01:00
TraceInfo ( "umbracoMacro" , "Loading IMacroEngine script [done]" ) ;
2010-01-28 12:51:46 +00:00
return ret ;
}
2009-06-19 07:39:16 +00:00
/// <summary>
/// Loads a custom or webcontrol using reflection into the macro object
/// </summary>
/// <param name="fileName">The assembly to load from</param>
/// <param name="controlName">Name of the control</param>
/// <returns></returns>
/// <param name="attributes"></param>
2011-01-10 12:23:26 -01:00
public Control loadControl ( string fileName , string controlName , MacroModel model )
2009-06-19 07:39:16 +00:00
{
2011-01-10 12:23:26 -01:00
return loadControl ( fileName , controlName , model , null ) ;
2009-06-19 07:39:16 +00:00
}
/// <summary>
/// Loads a custom or webcontrol using reflection into the macro object
/// </summary>
/// <param name="fileName">The assembly to load from</param>
/// <param name="controlName">Name of the control</param>
/// <returns></returns>
/// <param name="attributes"></param>
/// <param name="umbPage"></param>
2011-01-10 12:23:26 -01:00
public Control loadControl ( string fileName , string controlName , MacroModel model , Hashtable pageElements )
2009-06-19 07:39:16 +00:00
{
Type type ;
Assembly asm ;
try
{
2010-01-28 12:51:46 +00:00
string currentAss = IOHelper . MapPath ( string . Format ( "{0}/{1}.dll" , SystemDirectories . Bin , fileName ) ) ;
2010-03-03 07:20:55 +00:00
2009-06-19 07:39:16 +00:00
if ( ! File . Exists ( currentAss ) )
return new LiteralControl ( "Unable to load user control because is does not exist: " + fileName ) ;
asm = Assembly . LoadFrom ( currentAss ) ;
2010-03-03 07:20:55 +00:00
2009-06-19 07:39:16 +00:00
if ( HttpContext . Current ! = null )
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Assembly file " + currentAss + " LOADED!!" ) ;
}
catch
{
throw new ArgumentException ( string . Format ( "ASSEMBLY NOT LOADED PATH: {0} NOT FOUND!!" ,
2010-01-28 12:51:46 +00:00
IOHelper . MapPath ( SystemDirectories . Bin + "/" + fileName +
2010-12-06 11:47:46 +00:00
".dll" ) ) ) ;
2009-06-19 07:39:16 +00:00
}
if ( HttpContext . Current ! = null )
HttpContext . Current . Trace . Write ( "umbracoMacro" ,
string . Format ( "Assembly Loaded from ({0}.dll)" , fileName ) ) ;
type = asm . GetType ( controlName ) ;
if ( type = = null )
return new LiteralControl ( string . Format ( "Unable to get type {0} from assembly {1}" ,
controlName , asm . FullName ) ) ;
2010-12-06 11:47:46 +00:00
var control = Activator . CreateInstance ( type ) as Control ;
2009-06-19 07:39:16 +00:00
if ( control = = null )
return new LiteralControl ( string . Format ( "Unable to create control {0} from assembly {1}" ,
controlName , asm . FullName ) ) ;
2011-01-07 01:23:09 +00:00
AddCurrentNodeToControl ( control , type ) ;
// Properties
2009-06-19 07:39:16 +00:00
foreach ( string propertyAlias in properties . Keys )
{
PropertyInfo prop = type . GetProperty ( propertyAlias ) ;
if ( prop = = null )
{
if ( HttpContext . Current ! = null )
HttpContext . Current . Trace . Warn ( "macro" ,
2011-01-10 12:23:26 -01:00
string . Format ( "control property '{0}' doesn't exist or aren't accessible (public)" ,
propertyAlias ) ) ;
2009-06-19 07:39:16 +00:00
continue ;
}
2011-01-12 07:57:21 -01:00
MacroPropertyModel propModel = model . Properties . Find ( m = > m . Key = = propertyAlias . ToLower ( ) ) ;
2011-01-10 12:23:26 -01:00
object propValue = propModel ! = null
? helper . parseAttribute ( pageElements , propModel . Value )
: helper . parseAttribute ( pageElements , "" ) ;
2009-06-19 07:39:16 +00:00
// Special case for types of webControls.unit
2010-03-03 07:20:55 +00:00
if ( prop . PropertyType = = typeof ( Unit ) )
2009-06-19 07:39:16 +00:00
propValue = Unit . Parse ( propValue . ToString ( ) ) ;
else
{
foreach ( object s in propertyDefinitions )
{
if ( s ! = null )
Trace . Write ( "macroProp" , s . ToString ( ) ) ;
}
Trace . Warn ( "macro" , propertyAlias ) ;
object o = propertyDefinitions [ propertyAlias ] ;
if ( o = = null )
continue ;
2010-12-06 11:47:46 +00:00
var st = ( TypeCode ) Enum . Parse ( typeof ( TypeCode ) , o . ToString ( ) , true ) ;
2009-06-19 07:39:16 +00:00
// Special case for booleans
2010-03-03 07:20:55 +00:00
if ( prop . PropertyType = = typeof ( bool ) )
2009-06-19 07:39:16 +00:00
{
bool parseResult ;
if (
Boolean . TryParse ( propValue . ToString ( ) . Replace ( "1" , "true" ) . Replace ( "0" , "false" ) ,
out parseResult ) )
propValue = parseResult ;
else
propValue = false ;
}
else
propValue = Convert . ChangeType ( propValue , st ) ;
}
prop . SetValue ( control , Convert . ChangeType ( propValue , prop . PropertyType ) , null ) ;
}
return control ;
}
/// <summary>
/// Loads an usercontrol using reflection into the macro object
/// </summary>
/// <param name="fileName">Filename of the usercontrol - ie. ~wulff.ascx</param>
2011-01-07 01:23:09 +00:00
/// <param name="attributes">The attributes.</param>
/// <param name="pageElements">The page elements.</param>
2009-06-19 07:39:16 +00:00
/// <returns></returns>
2011-01-10 12:23:26 -01:00
public Control loadUserControl ( string fileName , MacroModel model , Hashtable pageElements )
2009-06-19 07:39:16 +00:00
{
Debug . Assert ( ! string . IsNullOrEmpty ( fileName ) , "fileName cannot be empty" ) ;
2011-01-10 12:23:26 -01:00
Debug . Assert ( model . Properties ! = null , "attributes cannot be null" ) ;
2009-06-19 07:39:16 +00:00
Debug . Assert ( pageElements ! = null , "pageElements cannot be null" ) ;
try
{
string userControlPath = @"~/" + fileName ;
2010-01-28 12:51:46 +00:00
if ( ! File . Exists ( IOHelper . MapPath ( userControlPath ) ) )
2009-06-19 07:39:16 +00:00
return new LiteralControl ( string . Format ( "UserControl {0} does not exist." , fileName ) ) ;
2010-12-06 11:47:46 +00:00
var oControl = ( UserControl ) new UserControl ( ) . LoadControl ( userControlPath ) ;
2009-06-19 07:39:16 +00:00
int slashIndex = fileName . LastIndexOf ( "/" ) + 1 ;
if ( slashIndex < 0 )
slashIndex = 0 ;
2011-01-10 12:23:26 -01:00
if ( ! String . IsNullOrEmpty ( model . MacroControlIdentifier ) )
oControl . ID = model . MacroControlIdentifier ;
2009-06-19 07:39:16 +00:00
else
oControl . ID =
string . Format ( "{0}_{1}" , fileName . Substring ( slashIndex , fileName . IndexOf ( ".ascx" ) - slashIndex ) ,
StateHelper . GetContextValue < int > ( macrosAddedKey ) ) ;
TraceInfo ( loadUserControlKey , string . Format ( "Usercontrol added with id '{0}'" , oControl . ID ) ) ;
Type type = oControl . GetType ( ) ;
if ( type = = null )
{
TraceWarn ( loadUserControlKey , "Unable to retrieve control type: " + fileName ) ;
return oControl ;
}
2011-01-07 01:23:09 +00:00
AddCurrentNodeToControl ( oControl , type ) ;
2009-06-19 07:39:16 +00:00
foreach ( string propertyAlias in properties . Keys )
{
PropertyInfo prop = type . GetProperty ( propertyAlias ) ;
if ( prop = = null )
{
TraceWarn ( loadUserControlKey , "Unable to retrieve type from propertyAlias: " + propertyAlias ) ;
continue ;
}
2011-01-12 07:57:21 -01:00
MacroPropertyModel propModel = model . Properties . Find ( m = > m . Key = = propertyAlias . ToLower ( ) ) ;
2011-01-10 12:23:26 -01:00
object propValue = propModel ! = null
? helper . parseAttribute ( pageElements , propModel . Value )
: helper . parseAttribute ( pageElements , "" ) ;
2011-01-12 07:57:21 -01:00
if ( propValue = = null )
2009-06-19 07:39:16 +00:00
continue ;
// Special case for types of webControls.unit
try
{
2010-03-03 07:20:55 +00:00
if ( prop . PropertyType = = typeof ( Unit ) )
2009-06-19 07:39:16 +00:00
propValue = Unit . Parse ( propValue . ToString ( ) ) ;
else
{
try
{
object o = propertyDefinitions [ propertyAlias ] ;
if ( o = = null )
continue ;
2010-12-06 11:47:46 +00:00
var st = ( TypeCode ) Enum . Parse ( typeof ( TypeCode ) , o . ToString ( ) , true ) ;
2009-06-19 07:39:16 +00:00
// Special case for booleans
2010-03-03 07:20:55 +00:00
if ( prop . PropertyType = = typeof ( bool ) )
2009-06-19 07:39:16 +00:00
{
bool parseResult ;
if (
Boolean . TryParse (
propValue . ToString ( ) . Replace ( "1" , "true" ) . Replace ( "0" , "false" ) ,
out parseResult ) )
propValue = parseResult ;
else
propValue = false ;
}
else
propValue = Convert . ChangeType ( propValue , st ) ;
Trace . Write ( "macro.loadControlProperties" ,
2010-12-06 11:47:46 +00:00
string . Format ( "Property added '{0}' with value '{1}'" , propertyAlias ,
propValue ) ) ;
2009-06-19 07:39:16 +00:00
}
catch ( Exception PropException )
{
HttpContext . Current . Trace . Warn ( "macro.loadControlProperties" ,
string . Format (
"Error adding property '{0}' with value '{1}'" ,
propertyAlias , propValue ) , PropException ) ;
}
}
prop . SetValue ( oControl , Convert . ChangeType ( propValue , prop . PropertyType ) , null ) ;
}
catch ( Exception propException )
{
HttpContext . Current . Trace . Warn ( "macro.loadControlProperties" ,
string . Format (
"Error adding property '{0}' with value '{1}', maybe it doesn't exists or maybe casing is wrong!" ,
propertyAlias , propValue ) , propException ) ;
}
}
return oControl ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "macro" , string . Format ( "Error creating usercontrol ({0})" , fileName ) , e ) ;
return new LiteralControl (
string . Format (
"<div style=\"color: black; padding: 3px; border: 2px solid red\"><b style=\"color:red\">Error creating control ({0}).</b><br/> Maybe file doesn't exists or the usercontrol has a cache directive, which is not allowed! See the tracestack for more information!</div>" ,
fileName ) ) ;
}
}
2011-01-07 01:23:09 +00:00
private static void AddCurrentNodeToControl ( Control control , Type type )
{
var currentNodeProperty = type . GetProperty ( "CurrentNode" ) ;
if ( currentNodeProperty ! = null & & currentNodeProperty . CanWrite & & currentNodeProperty . PropertyType . IsAssignableFrom ( typeof ( Node ) ) )
{
currentNodeProperty . SetValue ( control , Node . GetCurrent ( ) , null ) ;
}
currentNodeProperty = type . GetProperty ( "currentNode" ) ;
if ( currentNodeProperty ! = null & & currentNodeProperty . CanWrite & & currentNodeProperty . PropertyType . IsAssignableFrom ( typeof ( Node ) ) )
{
currentNodeProperty . SetValue ( control , Node . GetCurrent ( ) , null ) ;
}
}
2009-06-19 07:39:16 +00:00
private void TraceInfo ( string category , string message )
{
if ( HttpContext . Current ! = null )
HttpContext . Current . Trace . Write ( category , message ) ;
}
private void TraceWarn ( string category , string message )
{
if ( HttpContext . Current ! = null )
HttpContext . Current . Trace . Warn ( category , message ) ;
}
/// <summary>
/// For debug purposes only - should be deleted or made private
/// </summary>
/// <param name="type">The type of object (control) to show properties from</param>
public void macroProperties ( Type type )
{
PropertyInfo [ ] myProperties = type . GetProperties ( BindingFlags . Public | BindingFlags . Instance ) ;
HttpContext . Current . Response . Write ( "<p>" + type . Name + "<br />" ) ;
foreach ( PropertyInfo propertyItem in myProperties )
{
// if (propertyItem.CanWrite)
HttpContext . Current . Response . Write ( propertyItem . Name + " (" + propertyItem . PropertyType +
")<br />" ) ;
}
HttpContext . Current . Response . Write ( "</p>" ) ;
}
public static string renderMacroStartTag ( Hashtable attributes , int pageId , Guid versionId )
{
2010-03-03 07:20:55 +00:00
string div = "<div " ;
2009-06-19 07:39:16 +00:00
IDictionaryEnumerator ide = attributes . GetEnumerator ( ) ;
while ( ide . MoveNext ( ) )
{
div + = string . Format ( "umb_{0}=\"{1}\" " , ide . Key , encodeMacroAttribute ( ide . Value . ToString ( ) ) ) ;
}
div + = "ismacro=\"true\" onresizestart=\"return false;\" umbVersionId=\"" + versionId +
"\" umbPageid=\"" +
pageId +
"\" title=\"This is rendered content from macro\" class=\"umbMacroHolder\"><!-- startUmbMacro -->" ;
return div ;
}
private static string encodeMacroAttribute ( string attributeContents )
{
// Replace linebreaks
attributeContents = attributeContents . Replace ( "\n" , "\\n" ) . Replace ( "\r" , "\\r" ) ;
// Replace quotes
2010-03-03 07:20:55 +00:00
attributeContents =
2009-06-19 07:39:16 +00:00
attributeContents . Replace ( "\"" , """ ) ;
// Replace tag start/ends
attributeContents =
attributeContents . Replace ( "<" , "<" ) . Replace ( ">" , ">" ) ;
return attributeContents ;
}
public static string renderMacroEndTag ( )
{
return "<!-- endUmbMacro --></div>" ;
}
public static string GetRenderedMacro ( int MacroId , page umbPage , Hashtable attributes , int pageId )
{
2010-12-06 11:47:46 +00:00
var m = new macro ( MacroId ) ;
2009-06-19 07:39:16 +00:00
Control c = m . renderMacro ( attributes , umbPage . Elements , pageId ) ;
TextWriter writer = new StringWriter ( ) ;
2010-12-06 11:47:46 +00:00
var ht = new HtmlTextWriter ( writer ) ;
2009-06-19 07:39:16 +00:00
c . RenderControl ( ht ) ;
string result = writer . ToString ( ) ;
// remove hrefs
string pattern = "href=\"([^\"]*)\"" ;
MatchCollection hrefs =
Regex . Matches ( result , pattern , RegexOptions . IgnoreCase | RegexOptions . IgnorePatternWhitespace ) ;
foreach ( Match href in hrefs )
result = result . Replace ( href . Value , "href=\"javascript:void(0)\"" ) ;
return result ;
}
public static string MacroContentByHttp ( int PageID , Guid PageVersion , Hashtable attributes )
{
2010-12-06 11:47:46 +00:00
string tempAlias = ( attributes [ "macroalias" ] ! = null )
? attributes [ "macroalias" ] . ToString ( )
: attributes [ "macroAlias" ] . ToString ( ) ;
2009-06-19 07:39:16 +00:00
if ( ! ReturnFromAlias ( tempAlias ) . DontRenderInEditor )
{
string querystring = "umbPageId=" + PageID + "&umbVersionId=" + PageVersion ;
IDictionaryEnumerator ide = attributes . GetEnumerator ( ) ;
while ( ide . MoveNext ( ) )
querystring + = "&umb_" + ide . Key + "=" + HttpContext . Current . Server . UrlEncode ( ide . Value . ToString ( ) ) ;
// Create a new 'HttpWebRequest' Object to the mentioned URL.
string retVal = string . Empty ;
string url = "http://" + HttpContext . Current . Request . ServerVariables [ "SERVER_NAME" ] + ":" +
2010-12-06 11:47:46 +00:00
HttpContext . Current . Request . ServerVariables [ "SERVER_PORT" ] +
IOHelper . ResolveUrl ( SystemDirectories . Umbraco ) +
2009-06-19 07:39:16 +00:00
"/macroResultWrapper.aspx?" +
querystring ;
2010-12-06 11:47:46 +00:00
var myHttpWebRequest = ( HttpWebRequest ) WebRequest . Create ( url ) ;
2010-10-20 12:16:08 +00:00
// propagate the user's context
HttpCookie inCookie = HttpContext . Current . Request . Cookies [ "UserContext" ] ;
2010-12-06 11:47:46 +00:00
var cookie = new Cookie ( inCookie . Name , inCookie . Value , inCookie . Path ,
HttpContext . Current . Request . ServerVariables [ "SERVER_NAME" ] ) ;
2010-10-20 12:16:08 +00:00
myHttpWebRequest . CookieContainer = new CookieContainer ( ) ;
myHttpWebRequest . CookieContainer . Add ( cookie ) ;
2009-06-19 07:39:16 +00:00
// Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
HttpWebResponse myHttpWebResponse = null ;
try
{
2010-03-03 07:20:55 +00:00
myHttpWebResponse = ( HttpWebResponse ) myHttpWebRequest . GetResponse ( ) ;
2009-06-19 07:39:16 +00:00
if ( myHttpWebResponse . StatusCode = = HttpStatusCode . OK )
{
Stream streamResponse = myHttpWebResponse . GetResponseStream ( ) ;
2010-12-06 11:47:46 +00:00
var streamRead = new StreamReader ( streamResponse ) ;
var readBuff = new Char [ 256 ] ;
2009-06-19 07:39:16 +00:00
int count = streamRead . Read ( readBuff , 0 , 256 ) ;
while ( count > 0 )
{
2010-12-06 11:47:46 +00:00
var outputData = new String ( readBuff , 0 , count ) ;
2009-06-19 07:39:16 +00:00
retVal + = outputData ;
count = streamRead . Read ( readBuff , 0 , 256 ) ;
}
// Close the Stream object.
streamResponse . Close ( ) ;
streamRead . Close ( ) ;
// Find the content of a form
string grabStart = "<!-- grab start -->" ;
string grabEnd = "<!-- grab end -->" ;
int grabStartPos = retVal . IndexOf ( grabStart ) + grabStart . Length ;
int grabEndPos = retVal . IndexOf ( grabEnd ) - grabStartPos ;
retVal = retVal . Substring ( grabStartPos , grabEndPos ) ;
}
else
retVal = "<span style=\"color: green\">No macro content available for WYSIWYG editing</span>" ;
// Release the HttpWebResponse Resource.
myHttpWebResponse . Close ( ) ;
}
2010-10-20 12:16:08 +00:00
catch ( Exception ee )
2009-06-19 07:39:16 +00:00
{
retVal = "<span style=\"color: green\">No macro content available for WYSIWYG editing</span>" ;
}
finally
{
// Release the HttpWebResponse Resource.
if ( myHttpWebResponse ! = null )
myHttpWebResponse . Close ( ) ;
}
return retVal . Replace ( "\n" , string . Empty ) . Replace ( "\r" , string . Empty ) ;
}
else
return "<span style=\"color: green\">This macro does not provides rendering in WYSIWYG editor</span>" ;
}
/// <summary>
/// Adds the XSLT extension namespaces to the XSLT header using
/// {0} as the container for the namespace references and
/// {1} as the container for the exclude-result-prefixes
/// </summary>
/// <param name="xslt">The XSLT</param>
/// <returns></returns>
public static string AddXsltExtensionsToHeader ( string xslt )
{
2010-12-06 11:47:46 +00:00
var namespaceList = new StringBuilder ( ) ;
var namespaceDeclaractions = new StringBuilder ( ) ;
foreach ( var extension in GetXsltExtensions ( ) )
2009-06-19 07:39:16 +00:00
{
namespaceList . Append ( extension . Key ) . Append ( ' ' ) ;
namespaceDeclaractions . AppendFormat ( "xmlns:{0}=\"urn:{0}\" " , extension . Key ) ;
}
// parse xslt
xslt = xslt . Replace ( "{0}" , namespaceDeclaractions . ToString ( ) ) ;
xslt = xslt . Replace ( "{1}" , namespaceList . ToString ( ) ) ;
return xslt ;
}
2011-01-10 12:23:26 -01:00
2009-06-19 07:39:16 +00:00
}
public class MacroCacheContent
{
2010-12-06 11:47:46 +00:00
private readonly Control _control ;
private readonly string _id ;
public MacroCacheContent ( Control control , string ID )
{
_control = control ;
_id = ID ;
}
2009-06-19 07:39:16 +00:00
public string ID
{
get { return _id ; }
}
public Control Content
{
get { return _control ; }
}
}
public class macroCacheRefresh : ICacheRefresher
{
#region ICacheRefresher Members
public string Name
{
get
{
// TODO: Add templateCacheRefresh.Name getter implementation
return "Macro cache refresher" ;
}
}
public Guid UniqueIdentifier
{
get
{
// TODO: Add templateCacheRefresh.UniqueIdentifier getter implementation
return new Guid ( "7B1E683C-5F34-43dd-803D-9699EA1E98CA" ) ;
}
}
public void RefreshAll ( )
{
macro . ClearAliasCache ( ) ;
}
public void Refresh ( Guid Id )
{
// Doesn't do anything
}
void ICacheRefresher . Refresh ( int Id )
{
new macro ( Id ) . removeFromCache ( ) ;
}
2010-03-03 07:20:55 +00:00
void ICacheRefresher . Remove ( int Id )
{
2009-06-19 07:39:16 +00:00
new macro ( Id ) . removeFromCache ( ) ;
}
2010-12-06 11:47:46 +00:00
2009-06-19 07:39:16 +00:00
#endregion
}
2010-03-03 02:50:06 +00:00
/// <summary>
/// Allows App_Code XSLT extensions to be declared using the [XsltExtension] class attribute.
/// </summary>
/// <remarks>
/// An optional XML namespace can be specified using [XsltExtension("MyNamespace")].
/// </remarks>
[AttributeUsage(AttributeTargets.Class)]
2010-12-06 11:47:46 +00:00
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium, Unrestricted = false)]
2010-03-03 02:50:06 +00:00
public class XsltExtensionAttribute : Attribute
{
public XsltExtensionAttribute ( )
{
2010-12-06 11:47:46 +00:00
Namespace = String . Empty ;
2010-03-03 02:50:06 +00:00
}
2010-12-06 11:47:46 +00:00
2010-03-03 02:50:06 +00:00
public XsltExtensionAttribute ( string ns )
{
2010-12-06 11:47:46 +00:00
Namespace = ns ;
2010-03-03 02:50:06 +00:00
}
2010-12-06 11:47:46 +00:00
2010-03-03 02:50:06 +00:00
public string Namespace { get ; set ; }
2010-12-06 11:47:46 +00:00
public override string ToString ( )
{
return Namespace ;
}
}
2009-06-19 07:39:16 +00:00
}