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.Data ;
using System.Diagnostics ;
using System.IO ;
using System.Net ;
using System.Reflection ;
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 ;
2010-03-03 17:13:42 +00:00
2009-06-19 07:39:16 +00:00
using umbraco.BusinessLogic ;
2010-03-03 17:13:42 +00:00
using umbraco.cms.businesslogic ;
using Content = umbraco . cms . businesslogic . Content ;
2009-06-19 07:39:16 +00:00
using umbraco.cms.businesslogic.macro ;
using umbraco.cms.businesslogic.member ;
using umbraco.DataLayer ;
using umbraco.interfaces ;
using umbraco.presentation.xslt.Exslt ;
using umbraco.scripting ;
2010-03-03 17:13:42 +00:00
using umbraco.presentation.nodeFactory ;
2009-06-19 07:39:16 +00:00
using templateControls = umbraco . presentation . templateControls ;
2010-01-28 12:51:46 +00:00
using umbraco.IO ;
2009-06-19 07:39:16 +00:00
namespace umbraco
{
/// <summary>
/// Summary description for macro.
/// </summary>
public class macro : Page
{
#region private properties
private readonly StringBuilder mContent = new StringBuilder ();
private readonly Cache macroCache = HttpRuntime . Cache ;
private readonly String macroCacheIdentifier = "umbMacro" ;
private readonly string macrosAddedKey = "macrosAdded" ;
private readonly string loadUserControlKey = "loadUserControl" ;
// Alias hashable
private static Hashtable _macroAlias = new Hashtable ();
/// <summary>Cache for <see cref="GetPredefinedXsltExtensions"/>.</summary>
private static Dictionary < string , object > m_PredefinedExtensions ;
// Macro-elements
private int macroID ;
private bool cacheByPersonalization ;
private bool cacheByPage ;
private int cacheRefreshRate ;
private String alias ;
private String name ;
private String xsltFile ;
2010-01-28 12:51:46 +00:00
private String scriptFile ;
2009-06-19 07:39:16 +00:00
private String scriptType ;
private String scriptAssembly ;
private Hashtable properties = new Hashtable ();
private readonly Hashtable propertyDefinitions = new Hashtable ();
private readonly int macroType ;
private bool dontRenderInEditor ;
protected static ISqlHelper SqlHelper
{
get { return umbraco . BusinessLogic . Application . SqlHelper ; }
}
#endregion
#region public properties
public int MacroID
{
set { macroID = value ; }
get { return macroID ; }
}
public bool CacheByPersonalization
{
set { cacheByPersonalization = value ; }
get { return cacheByPersonalization ; }
}
public bool CacheByPage
{
set { cacheByPage = value ; }
get { return cacheByPage ; }
}
public bool DontRenderInEditor
{
get { return dontRenderInEditor ; }
set { dontRenderInEditor = value ; }
}
public int RefreshRate
{
set { cacheRefreshRate = value ; }
get { return cacheRefreshRate ; }
}
public String Alias
{
set { alias = value ; }
get { return alias ; }
}
public String Name
{
set { name = value ; }
get { return name ; }
}
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 (); }
}
public enum eMacroType
{
XSLT = 1 ,
CustomControl = 2 ,
UserControl = 3 ,
Unknown = 4 ,
2010-01-28 12:51:46 +00:00
Python = 5 ,
Script = 6
2009-06-19 07:39:16 +00:00
}
#endregion
/// <summary>
/// Creates an empty macro object.
/// </summary>
public macro ()
{
}
public override string ToString ()
{
return Name ;
}
public static macro ReturnFromAlias ( string alias )
{
if ( _macroAlias . ContainsKey ( alias ))
2010-03-03 07:20:55 +00:00
return new macro (( int ) _macroAlias [ alias ]);
2009-06-19 07:39:16 +00:00
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 ;
}
}
}
/// <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-03-03 07:20:55 +00:00
macro 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
{
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 )))
{
if (! macroDef . HasRecords )
HttpContext . Current . Trace . Warn ( "Macro" , "No definition found for id " + id );
while ( macroDef . Read ())
{
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 ;
if ( TryGetColumnString ( macroDef , "macroPropertyTypeAlias" , out typeAlias ) && ! properties . ContainsKey ( tmpStr ))
properties . Add ( tmpStr , typeAlias );
string baseType ;
if ( TryGetColumnString ( macroDef , "macroPropertyTypeBaseType" , out baseType ) && ! propertyDefinitions . ContainsKey ( tmpStr ))
propertyDefinitions . Add ( tmpStr , baseType );
}
}
}
// add current macro-object to cache
macroCache . Insert ( macroCacheIdentifier + id , this );
}
if (! string . IsNullOrEmpty ( XsltFile ))
2010-03-03 07:20:55 +00:00
macroType = ( int ) eMacroType . XSLT ;
2009-06-19 07:39:16 +00:00
else
{
2010-01-28 12:51:46 +00:00
if (! string . IsNullOrEmpty ( ScriptFile ))
macroType = ( int ) eMacroType . Script ;
2009-06-19 07:39:16 +00:00
else
{
if (! string . IsNullOrEmpty ( ScriptType ) && ScriptType . ToLower (). IndexOf ( ".ascx" ) > - 1 )
{
2010-01-28 12:51:46 +00:00
macroType = ( int ) eMacroType . UserControl ;
2009-06-19 07:39:16 +00:00
}
else if (! string . IsNullOrEmpty ( ScriptType ) && ! string . IsNullOrEmpty ( ScriptAssembly ))
2010-01-28 12:51:46 +00:00
macroType = ( int ) eMacroType . CustomControl ;
2009-06-19 07:39:16 +00:00
}
}
if ( macroType . ToString () == string . Empty )
2010-03-03 07:20:55 +00:00
macroType = ( int ) eMacroType . Unknown ;
2009-06-19 07:39:16 +00:00
}
public static bool TryGetColumnString ( IRecordsReader reader , string columnName , out string value )
{
2010-03-03 07:20:55 +00:00
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 ;
}
private string getCacheGuid ( Hashtable attributes , Hashtable pageElements , int pageId )
{
string tempGuid = string . Empty ;
if ( CacheByPage )
tempGuid = pageId + "-" ;
if ( CacheByPersonalization )
{
if ( Member . GetCurrentMember () != null )
tempGuid += "m" + Member . GetCurrentMember (). Id + "-" ;
else
tempGuid += "m" ;
}
IDictionaryEnumerator id = attributes . GetEnumerator ();
while ( id . MoveNext ())
{
string attValue = helper . FindAttribute ( pageElements , attributes , id . Key . ToString ());
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 )
{
HttpContext . Current . Trace . Write ( "renderMacro" ,
string . Format ( "Rendering started (macro: {0}, type: {1}, cacheRate: {2})" ,
Name , MacroType , RefreshRate ));
StateHelper . SetContextValue ( macrosAddedKey , StateHelper . GetContextValue < int >( macrosAddedKey ) + 1 );
Control macroHtml = null ;
string macroGuid = getCacheGuid ( attributes , pageElements , pageId );
if ( RefreshRate > 0 )
{
if ( macroCache [ "macroHtml_" + macroGuid ] != null )
{
2010-03-03 07:20:55 +00:00
MacroCacheContent cacheContent = ( MacroCacheContent ) macroCache [ "macroHtml_" + macroGuid ];
2009-06-19 07:39:16 +00:00
macroHtml = cacheContent . Content ;
macroHtml . ID = cacheContent . ID ;
HttpContext . Current . Trace . Write ( "renderMacro" , "Content loaded from cache ('" + macroGuid + "')..." );
}
}
if ( macroHtml == null )
{
switch ( MacroType )
{
2010-03-03 07:20:55 +00:00
case ( int ) eMacroType . UserControl :
2009-06-19 07:39:16 +00:00
try
{
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Usercontrol added (" + scriptType + ")" );
macroHtml = loadUserControl ( ScriptType , attributes , pageElements );
break ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Error loading userControl (" + scriptType + ")" , e );
macroHtml = new LiteralControl ( "Error loading userControl '" + scriptType + "'" );
break ;
}
2010-03-03 07:20:55 +00:00
case ( int ) eMacroType . 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 + ")" );
macroHtml = loadControl ( scriptAssembly , ScriptType , attributes , pageElements );
break ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Error loading customControl (Assembly: " + scriptAssembly +
", Type: '" + scriptType + "'" , e );
macroHtml =
new LiteralControl ( "Error loading customControl (Assembly: " + scriptAssembly +
", Type: '" +
scriptType + "'" );
break ;
}
2010-03-03 07:20:55 +00:00
case ( int ) eMacroType . XSLT :
2009-06-19 07:39:16 +00:00
macroHtml = loadMacroXSLT ( this , attributes , pageElements );
break ;
2010-03-03 07:20:55 +00:00
case ( int ) eMacroType . Script :
2009-06-19 07:39:16 +00:00
try
{
2010-01-28 12:51:46 +00:00
HttpContext . Current . Trace . Write ( "umbracoMacro" , "DLR Script script added (" + ScriptFile + ")" );
macroHtml = loadMacroDLR ( this , attributes , pageElements );
2009-06-19 07:39:16 +00:00
break ;
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
2010-01-28 12:51:46 +00:00
"Error loading python script (file: " + ScriptFile +
2009-06-19 07:39:16 +00:00
", Type: '" + scriptType + "'" , e );
2010-01-28 12:51:46 +00:00
LiteralControl result = new LiteralControl ( "Error loading DLR script (file: " + ScriptFile + ")" );
/*
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;
*/
macroHtml = result ;
2009-06-19 07:39:16 +00:00
break ;
}
default :
if ( GlobalSettings . DebugMode )
macroHtml =
new LiteralControl ( "<Macro: " + Name + " (" + ScriptAssembly + "," + ScriptType +
")>" );
break ;
}
// Add result to cache
if ( RefreshRate > 0 )
{
// do not add to cache if there's no member and it should cache by personalization
if (! CacheByPersonalization || ( CacheByPersonalization && Member . GetCurrentMember () != null ))
if ( macroHtml != null )
macroCache . Insert ( "macroHtml_" + macroGuid , new MacroCacheContent ( macroHtml , macroHtml . ID ), null ,
DateTime . Now . AddSeconds ( RefreshRate ), TimeSpan . Zero , CacheItemPriority . Low ,
null );
}
}
return macroHtml ;
}
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
{
XmlTextReader xslReader =
2010-03-03 07:20:55 +00:00
new XmlTextReader ( IOHelper . MapPath ( SystemDirectories . Xslt + "/" + XsltFile ));
2009-06-19 07:39:16 +00:00
XslCompiledTransform macroXSLT = CreateXsltTransform ( xslReader , umbraco . GlobalSettings . DebugMode );
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 ;
}
}
public static XslCompiledTransform CreateXsltTransform ( XmlTextReader xslReader , bool debugMode )
{
XslCompiledTransform macroXSLT = new XslCompiledTransform ( debugMode );
XmlUrlResolver xslResolver = new XmlUrlResolver ();
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 )
{
Hashtable retval = new Hashtable ();
foreach ( object key in input . Keys )
retval . Add ( key . ToString (). ToLower (), input [ key ]);
return retval ;
}
2009-06-19 07:39:16 +00:00
public Control loadMacroXSLT ( macro macro , Hashtable attributes , Hashtable pageElements )
{
if ( XsltFile . Trim () != string . Empty )
{
2010-01-28 12:51:46 +00:00
//get attributes in lowercase...
attributes = keysToLowerCase ( keysToLowerCase ( attributes ));
2009-06-19 07:39:16 +00:00
// Get main XML
XmlDocument umbracoXML = content . Instance . XmlContent ;
// Create XML document for Macro
XmlDocument macroXML = new XmlDocument ();
macroXML . LoadXml ( "<macro/>" );
foreach ( DictionaryEntry macroDef in macro . properties )
{
try
{
if ( helper . FindAttribute ( pageElements , attributes , macroDef . Key . ToString ()) != string . Empty )
addMacroXmlNode ( umbracoXML , macroXML , macroDef . Key . ToString (), macroDef . Value . ToString (),
helper . FindAttribute ( pageElements , attributes , macroDef . Key . ToString ()));
else
addMacroXmlNode ( umbracoXML , macroXML , macroDef . Key . ToString (), macroDef . Value . ToString (),
string . Empty );
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" , "Could not write XML node (" + macroDef . Key + ")" ,
e );
}
}
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ö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
PlaceHolder container = new PlaceHolder ();
// 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
templateControls . Item item = new templateControls . Item ();
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 );
}
public static string GetXsltTransformResult ( XmlDocument macroXML , XslCompiledTransform xslt , Dictionary < string , object > parameters )
{
TextWriter tw = new StringWriter ();
HttpContext . Current . Trace . Write ( "umbracoMacro" , "Before adding extensions" );
XsltArgumentList xslArgs ;
xslArgs = AddXsltExtensions ();
library lib = new library ();
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 )
{
foreach ( KeyValuePair < string , object > parameter in parameters )
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
Dictionary < string , object > extensions = new Dictionary < string , object >( GetPredefinedXsltExtensions ());
// Load the XSLT extensions configuration
XmlDocument 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-03-03 07:20:55 +00:00
string extensionFile = IOHelper . MapPath ( string . Format ( "{0}/{1}.dll" , SystemDirectories . Bin , xsltEx . Attributes [ "assembly" ]. Value ));
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
{
throw new Exception ( String . Format ( "Could not load assembly {0} for XSLT extension {1}. Please check config/xsltExentions.config." ,
2010-03-03 07:20:55 +00:00
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 )
2009-06-19 07:39:16 +00:00
throw new Exception ( String . Format ( "Could not load type {0} ({1}) for XSLT extension {1}. Please check config/xsltExentions.config." ,
2010-03-03 07:20:55 +00:00
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-03-03 02:50:06 +00:00
Assembly appCodeAssembly ;
2010-05-10 14:34:18 +00:00
try
{
if ( Directory . Exists ( GlobalSettings . FullpathToRoot + System . IO . Path . DirectorySeparatorChar + "App_Code" ))
{
2010-05-06 14:06:58 +00:00
if ( Directory . GetFiles ( GlobalSettings . FullpathToRoot + System . IO . Path . DirectorySeparatorChar + "App_Code" ,
2010-03-03 02:50:06 +00:00
"*.*" ,
2010-05-10 14:34:18 +00:00
SearchOption . AllDirectories ). Length > 0 )
{
2010-05-06 14:06:58 +00:00
appCodeAssembly = Assembly . Load ( "__code" );
Type [] appCodeType = appCodeAssembly . GetExportedTypes ();
2010-05-10 14:34:18 +00:00
if ( appCodeType . Length == 0 )
{
2010-05-06 14:06:58 +00:00
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 ));
2010-05-10 14:34:18 +00:00
}
else
{
2010-05-06 14:06:58 +00:00
// create an instance and add it to the extensions list
2010-05-10 14:34:18 +00:00
foreach ( Type tp in appCodeType )
{
2010-05-06 14:06:58 +00:00
object [] tpAttributes = tp . GetCustomAttributes ( typeof ( XsltExtensionAttribute ), true );
2010-05-10 14:34:18 +00:00
foreach ( XsltExtensionAttribute tpAttribute in tpAttributes )
{
if ( tpAttribute . Namespace != String . Empty )
{
2010-05-06 14:06:58 +00:00
extensions . Add ( tpAttribute . Namespace , Activator . CreateInstance ( tp ));
2010-05-10 14:34:18 +00:00
}
else
{
2010-05-06 14:06:58 +00:00
extensions . Add ( tp . FullName , Activator . CreateInstance ( tp ));
}
2010-03-03 02:50:06 +00:00
}
}
}
}
2010-05-10 14:34:18 +00:00
}
else
{
2010-05-06 14:06:58 +00:00
Directory . CreateDirectory ( GlobalSettings . FullpathToRoot + System . IO . Path . DirectorySeparatorChar + "App_Code" );
2010-03-03 02:50:06 +00:00
}
2010-05-10 14:34:18 +00:00
}
catch ( FileNotFoundException )
{ //Do nothing - just means there's nothing to load.
}
catch ( Exception ex )
{
2010-03-03 02:50:06 +00:00
throw new Exception ( "Could not load App_Code classes for XSLT extensions." , ex );
}
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 ()
{
XsltArgumentList xslArgs = new XsltArgumentList ();
foreach ( KeyValuePair < string , object > extension in GetXsltExtensions ())
{
string extensionNamespace = "urn:" + extension . Key ;
xslArgs . AddExtensionObject ( extensionNamespace , extension . Value );
HttpContext . Current . Trace . Write ( "umbracoXsltExtension" ,
String . Format ( "Extension added: {0}, {1}" ,
extensionNamespace , extension . Value . GetType (). Name ));
}
return xslArgs ;
}
private void addMacroXmlNode ( XmlDocument umbracoXML , XmlDocument macroXML , String macroPropertyAlias ,
String macroPropertyType , String macroPropertyValue )
{
XmlNode macroXmlNode = macroXML . CreateNode ( XmlNodeType . Element , macroPropertyAlias , string . Empty );
XmlDocument x = new XmlDocument ();
int currentID = - 1 ;
// If no value is passed, then use the current pageID as value
if ( macroPropertyValue == string . Empty )
{
2010-03-03 07:20:55 +00:00
page 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" :
Content c = new Content ( int . Parse ( macroPropertyValue ));
macroXmlNode . AppendChild ( macroXML . ImportNode ( c . ToXml ( content . Instance . XmlContent , false ), true ));
break ;
default :
macroXmlNode . InnerText = System . Web . HttpContext . Current . Server . HtmlDecode ( macroPropertyValue );
break ;
}
macroXML . FirstChild . AppendChild ( macroXmlNode );
}
private string transformMacroXML ( XmlDocument xmlSource , string xslt_File )
{
StringBuilder sb = new StringBuilder ();
StringWriter sw = new StringWriter ( sb );
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 ;
}
/// <summary>
/// Executes a python script.
/// </summary>
/// <param name="macro">The instance of the macro (this). No idea why passed.</param>
/// <param name="attributes">Relayed attributes to determine the values of the passed properties.</param>
/// <param name="umbPage">The current page.</param>
/// <returns>Returns a LiteralControl stuffed with the StandardOutput of the script execution.</returns>
public Control loadMacroPython ( macro macro , Hashtable attributes , Hashtable pageElements )
{
LiteralControl ret = new LiteralControl ();
try
{
// Adding some global accessible variables to the enviroment.
// Currently no cleanup after execution is done.
Hashtable args = new Hashtable ();
HttpContext . Current . Session . Add ( "pageElements" , pageElements );
HttpContext . Current . Session . Add ( "macro" , this );
HttpContext . Current . Session . Add ( "args" , args );
foreach ( DictionaryEntry macroDef in macro . properties )
{
try
{
args . Add ( macroDef . Key . ToString (),
helper . FindAttribute ( pageElements , attributes , macroDef . Key . ToString ()));
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" ,
"Could not add global variable (" + macroDef . Key +
") to python enviroment" , e );
}
}
2010-01-28 12:51:46 +00:00
if ( string . IsNullOrEmpty ( macro . ScriptFile ))
2009-06-19 07:39:16 +00:00
{
ret . Text = string . Empty ;
}
else
{
// Execute the script and set the text of our LiteralControl with the returned
// result of our script.
2010-01-28 12:51:46 +00:00
string path = IOHelper . MapPath ( SystemDirectories . Python + "/" + macro . scriptFile );
2009-06-19 07:39:16 +00:00
object res = python . executeFile ( path );
ret . Text = res . ToString ();
}
}
catch ( Exception ex )
{
// Let's collect as much info we can get and display it glaring red
ret . Text = "<div style=\"border: 1px solid red; padding: 5px;\">" ;
Exception ie = ex ;
while ( ie != null )
{
ret . Text += "<br/><b>" + ie . Message + "</b><br/>" ;
ret . Text += ie . StackTrace + "<br/>" ;
ie = ie . InnerException ;
}
ret . Text += "</div>" ;
}
return ret ;
}
2010-01-28 12:51:46 +00:00
public Control loadMacroDLR ( macro macro , Hashtable attributes , Hashtable pageElements )
{
LiteralControl ret = new LiteralControl ();
Hashtable args = new Hashtable ();
foreach ( DictionaryEntry macroDef in macro . properties )
{
try
{
args . Add ( macroDef . Key . ToString (), helper . FindAttribute ( pageElements , attributes , macroDef . Key . ToString ()));
}
catch ( Exception e )
{
2010-03-03 07:20:55 +00:00
HttpContext . Current . Trace . Warn ( "umbracoMacro" , "Could not add global variable (" + macroDef . Key + ") to DLR enviroment" , e );
2010-01-28 12:51:46 +00:00
}
}
foreach ( DictionaryEntry pageVal in pageElements )
{
try
{
args . Add ( pageVal . Key . ToString (), pageVal . Value );
}
catch ( Exception e )
{
HttpContext . Current . Trace . Warn ( "umbracoMacro" , "Could not add page value (" + pageVal . Key + ") to DLR enviroment" , e );
}
}
2010-03-03 07:20:55 +00:00
2010-01-28 12:51:46 +00:00
args . Add ( "currentPage" , umbraco . presentation . nodeFactory . Node . GetCurrent ());
string path = IOHelper . MapPath ( SystemDirectories . Python + "/" + macro . scriptFile );
ret . Text = MacroScript . ExecuteFile ( path , args );
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>
public Control loadControl ( string fileName , string controlName , Hashtable attributes )
{
return loadControl ( fileName , controlName , attributes , null );
}
/// <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>
public Control loadControl ( string fileName , string controlName , Hashtable attributes , Hashtable pageElements )
{
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 +
2009-06-19 07:39:16 +00:00
".dll" )));
}
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 ));
Control control = Activator . CreateInstance ( type ) as Control ;
if ( control == null )
return new LiteralControl ( string . Format ( "Unable to create control {0} from assembly {1}" ,
controlName , asm . FullName ));
/// Properties
foreach ( string propertyAlias in properties . Keys )
{
PropertyInfo prop = type . GetProperty ( propertyAlias );
if ( prop == null )
{
if ( HttpContext . Current != null )
HttpContext . Current . Trace . Warn ( "macro" ,
string . Format ( "control property '{0} ({1})' didn't work" ,
propertyAlias ,
helper . FindAttribute ( attributes , propertyAlias )));
continue ;
}
object propValue = helper . FindAttribute ( pageElements , attributes , propertyAlias );
// 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-03-03 07:20:55 +00:00
TypeCode 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 );
if ( HttpContext . Current != null )
HttpContext . Current . Trace . Write ( "macro" ,
string . Format ( "control property '{0} ({1})' worked" ,
propertyAlias ,
helper . FindAttribute ( pageElements , attributes ,
propertyAlias )));
}
return control ;
}
/// <summary>
/// Loads an usercontrol using reflection into the macro object
/// </summary>
/// <param name="fileName">Filename of the usercontrol - ie. ~wulff.ascx</param>
/// <returns></returns>
/// <param name="attributes"></param>
/// <param name="umbPage"></param>
public Control loadUserControl ( string fileName , Hashtable attributes , Hashtable pageElements )
{
Debug . Assert (! string . IsNullOrEmpty ( fileName ), "fileName cannot be empty" );
Debug . Assert ( attributes != null , "attributes cannot be null" );
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-03-03 07:20:55 +00:00
UserControl oControl = ( UserControl ) new UserControl (). LoadControl ( userControlPath );
2009-06-19 07:39:16 +00:00
int slashIndex = fileName . LastIndexOf ( "/" ) + 1 ;
if ( slashIndex < 0 )
slashIndex = 0 ;
if ( attributes [ "controlID" ] != null )
oControl . ID = attributes [ "controlID" ]. ToString ();
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 ;
}
foreach ( string propertyAlias in properties . Keys )
{
PropertyInfo prop = type . GetProperty ( propertyAlias );
if ( prop == null )
{
TraceWarn ( loadUserControlKey , "Unable to retrieve type from propertyAlias: " + propertyAlias );
continue ;
}
object propValue =
helper . FindAttribute ( pageElements , attributes , propertyAlias ). Replace ( "&" , "&" ). Replace (
""" , "\"" ). Replace ( "<" , "<" ). Replace ( ">" , ">" );
if ( string . IsNullOrEmpty ( propValue as string ))
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-03-03 07:20:55 +00:00
TypeCode 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" ,
string . Format ( "Property added '{0}' with value '{1}'" , propertyAlias ,
propValue ));
}
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 ));
}
}
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 )
{
macro m = new macro ( MacroId );
Control c = m . renderMacro ( attributes , umbPage . Elements , pageId );
TextWriter writer = new StringWriter ();
HtmlTextWriter ht = new HtmlTextWriter ( writer );
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 )
{
string tempAlias = ( attributes [ "macroalias" ] != null ) ? attributes [ "macroalias" ]. ToString () : attributes [ "macroAlias" ]. ToString ();
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-03-03 07:20:55 +00:00
HttpContext . Current . Request . ServerVariables [ "SERVER_PORT" ] + IOHelper . ResolveUrl ( SystemDirectories . Umbraco ) +
2009-06-19 07:39:16 +00:00
"/macroResultWrapper.aspx?" +
querystring ;
2010-03-03 07:20:55 +00:00
HttpWebRequest myHttpWebRequest = ( HttpWebRequest ) WebRequest . Create ( url );
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 ();
StreamReader streamRead = new StreamReader ( streamResponse );
Char [] readBuff = new Char [ 256 ];
int count = streamRead . Read ( readBuff , 0 , 256 );
while ( count > 0 )
{
String outputData = new String ( readBuff , 0 , count );
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 ();
}
catch
{
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 )
{
StringBuilder namespaceList = new StringBuilder ();
StringBuilder namespaceDeclaractions = new StringBuilder ();
foreach ( KeyValuePair < string , object > extension in macro . GetXsltExtensions ())
{
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 ;
}
}
public class MacroCacheContent
{
private Control _control ;
private string _id ;
public string ID
{
get { return _id ; }
}
public Control Content
{
get { return _control ; }
}
public MacroCacheContent ( Control control , string ID )
{
_control = control ;
_id = ID ;
}
}
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 ();
}
#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)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium, Unrestricted = false)]
public class XsltExtensionAttribute : Attribute
{
public XsltExtensionAttribute ()
{
this . Namespace = String . Empty ;
}
public XsltExtensionAttribute ( string ns )
{
this . Namespace = ns ;
}
public string Namespace { get ; set ; }
public override string ToString () { return this . Namespace ; }
}
2009-06-19 07:39:16 +00:00
}