using System;
using System.Collections.Generic;
using System.Web;
using System.Data;
using System.Web.Caching;
using CMS.CMSHelper;
using CMS.DataEngine;
using CMS.GlobalHelper;
using CMS.IO;
using CMS.PortalEngine;
using CMS.SettingsProvider;
using CMS.SiteProvider;
using CMS.DocumentEngine;
using CMS.UIControls;
using CMS.URLRewritingEngine;
using CMS.WebAnalytics;
public partial class CMSPages_GetFile : GetFilePage
{
#region "Advanced settings"
///
/// Sets to false to disable the client caching.
///
protected bool useClientCache = true;
///
/// Sets to 0 if you do not wish to cache large files.
///
protected int largeFilesCacheMinutes = 1;
#endregion
#region "Variables"
protected CMSOutputFile outputFile = null;
protected TreeProvider mTreeProvider = null;
protected GeneralConnection mConnection = null;
protected TreeNode node = null;
protected PageInfo pi = null;
protected int? mVersionHistoryID = null;
protected bool mIsLatestVersion = false;
protected bool? mIsLiveSite = null;
protected Guid guid = Guid.Empty;
protected string mCulture = null;
protected Guid nodeGuid = Guid.Empty;
protected string aliasPath = null;
protected string fileName = null;
protected int latestForDocumentId = 0;
protected int latestForHistoryId = 0;
protected bool allowLatestVersion = false;
#endregion
#region "Properties"
///
/// Gets the language for current file.
///
public override string CultureCode
{
get
{
if (mCulture == null)
{
string culture = QueryHelper.GetString(URLHelper.LanguageParameterName, CMSContext.PreferredCultureCode);
if (!CultureInfoProvider.IsCultureAllowed(culture, CurrentSiteName))
{
culture = CMSContext.PreferredCultureCode;
}
mCulture = culture;
}
return mCulture;
}
}
///
/// Tree provider.
///
public TreeProvider TreeProvider
{
get
{
return mTreeProvider ?? (mTreeProvider = new TreeProvider());
}
}
///
/// Document version history ID.
///
public int VersionHistoryID
{
get
{
if (mVersionHistoryID == null)
{
mVersionHistoryID = QueryHelper.GetInteger("versionhistoryid", 0);
}
return mVersionHistoryID.Value;
}
}
///
/// Indicates if the file is latest version or comes from version history.
///
public bool LatestVersion
{
get
{
return mIsLatestVersion || (VersionHistoryID > 0);
}
}
///
/// Indicates if live site mode.
///
public bool IsLiveSite
{
get
{
if (mIsLiveSite == null)
{
mIsLiveSite = (ViewMode == ViewModeEnum.LiveSite);
}
return mIsLiveSite.Value;
}
}
///
/// Returns true if the process allows cache.
///
public override bool AllowCache
{
get
{
if (mAllowCache == null)
{
// By default, cache for the files is disabled outside of the live site
mAllowCache = CacheHelper.AlwaysCacheFiles || IsLiveSite;
}
return mAllowCache.Value;
}
set
{
mAllowCache = value;
}
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
DebugHelper.SetContext("GetFile");
// Load the site name
LoadSiteName();
// Check the site
if (CurrentSiteName == "")
{
throw new Exception("[GetFile.aspx]: Site not running.");
}
ValidateCulture();
// Set campaign
if (IsLiveSite)
{
// Store campaign name if present
string campaign = AnalyticsHelper.CurrentCampaign(CurrentSiteName);
if (!String.IsNullOrEmpty(campaign) && CMSContext.CurrentPageInfo != null)
{
AnalyticsHelper.SetCampaign(campaign, CurrentSiteName, CMSContext.CurrentPageInfo.NodeAliasPath);
}
}
int cacheMinutes = CacheMinutes;
// Try to get data from cache
using (CachedSection cs = new CachedSection(ref outputFile, cacheMinutes, true, null, "getfile", CurrentSiteName, GetBaseCacheKey(), Request.QueryString))
{
if (cs.LoadData)
{
// Store current value and temporary disable caching
bool cached = cs.Cached;
cs.Cached = false;
// Process the file
ProcessAttachment();
// Restore cache settings - data were loaded
cs.Cached = cached;
if (cs.Cached)
{
// Do not cache if too big file which would be stored in memory
if ((outputFile != null) &&
(outputFile.Attachment != null) &&
!CacheHelper.CacheImageAllowed(CurrentSiteName, outputFile.Attachment.AttachmentSize) &&
!AttachmentInfoProvider.StoreFilesInFileSystem(CurrentSiteName))
{
cacheMinutes = largeFilesCacheMinutes;
}
if (cacheMinutes > 0)
{
// Prepare the cache dependency
CacheDependency cd = null;
if (outputFile != null)
{
List dependencies = new List()
{
"node|" + CurrentSiteName.ToLowerCSafe() + "|" + outputFile.AliasPath.ToLowerCSafe(),
""
};
// Do not cache if too big file which would be stored in memory
if (outputFile.Attachment != null)
{
if (!CacheHelper.CacheImageAllowed(CurrentSiteName, outputFile.Attachment.AttachmentSize) && !AttachmentInfoProvider.StoreFilesInFileSystem(CurrentSiteName))
{
cacheMinutes = largeFilesCacheMinutes;
}
dependencies.Add("attachment|" + outputFile.Attachment.AttachmentGUID.ToString().ToLowerCSafe());
}
cd = GetCacheDependency(dependencies);
}
if (cd == null)
{
// Set default dependency
if (guid != Guid.Empty)
{
// By attachment GUID
cd = CacheHelper.GetCacheDependency(new string[] { "attachment|" + guid.ToString().ToLowerCSafe() });
}
else if (nodeGuid != Guid.Empty)
{
// By node GUID
cd = CacheHelper.GetCacheDependency(new string[] { "nodeguid|" + CurrentSiteName.ToLowerCSafe() + "|" + nodeGuid.ToString().ToLowerCSafe() });
}
else if (aliasPath != null)
{
// By node alias path
cd = CacheHelper.GetCacheDependency(new string[] { "node|" + CurrentSiteName.ToLowerCSafe() + "|" + aliasPath.ToLowerCSafe() });
}
}
cs.CacheDependency = cd;
}
// Cache the data
cs.CacheMinutes = cacheMinutes;
}
cs.Data = outputFile;
}
}
// Do not cache images in the browser if cache is not allowed
if (LatestVersion)
{
useClientCache = false;
}
// Send the data
SendFile(outputFile);
DebugHelper.ReleaseContext();
}
///
/// Sends the given file within response.
///
/// File to send
protected void SendFile(CMSOutputFile file)
{
// Clear response.
CookieHelper.ClearResponseCookies();
Response.Clear();
// Set the revalidation
SetRevalidation();
// Send the file
if ((file != null) && file.IsValid)
{
// Redirect if the file should be redirected
if (file.RedirectTo != "")
{
// Log hit or activity before redirecting
LogEvent(file);
if (StorageHelper.IsExternalStorage(file.RedirectTo))
{
string url = File.GetFileUrl(file.RedirectTo, CurrentSiteName);
if (!string.IsNullOrEmpty(url))
{
URLHelper.Redirect(url, true, CurrentSiteName);
}
}
URLHelper.Redirect(file.RedirectTo, true, CurrentSiteName);
return;
}
// Check authentication if secured file
if (file.IsSecured)
{
URLRewriter.CheckSecured(CurrentSiteName, ViewMode);
}
string etag = GetFileETag(file);
// Client caching - only on the live site
if (useClientCache && AllowCache && AllowClientCache && ETagsMatch(etag, file.LastModified))
{
// Set the file time stamps to allow client caching
SetTimeStamps(file);
// Ensure correct content type
if (file.Attachment != null)
{
Response.ContentType = GetResponseContentType(file.MimeType, file.Attachment.AttachmentExtension);
}
RespondNotModified(etag, !file.IsSecured);
return;
}
// If physical file not present, try to load
if (file.PhysicalFile == null)
{
EnsurePhysicalFile(outputFile);
}
// If the output data should be cached, return the output data
bool cacheOutputData = false;
if (file.Attachment != null)
{
// Cache data if allowed
if (!LatestVersion && (CacheMinutes > 0))
{
cacheOutputData = CacheHelper.CacheImageAllowed(CurrentSiteName, file.Attachment.AttachmentSize);
}
}
// Ensure the file data if physical file not present
if (!file.DataLoaded && (file.PhysicalFile == ""))
{
byte[] cachedData = GetCachedOutputData();
if (file.EnsureData(cachedData))
{
if ((cachedData == null) && cacheOutputData)
{
SaveOutputDataToCache(file.OutputData, GetOutputDataDependency(file.Attachment));
}
}
}
// Send the file
if ((file.OutputData != null) || (file.PhysicalFile != ""))
{
// Setup the mime type - Fix the special types
if (file.Attachment != null)
{
string extension = file.Attachment.AttachmentExtension;
// Prepare response
Response.ContentType = GetResponseContentType(file.MimeType, extension);
SetDisposition(file.Attachment.AttachmentName, extension);
// Setup Etag property
ETag = etag;
// Set if resumable downloads should be supported
AcceptRange = !IsExtensionExcludedFromRanges(extension);
}
if (useClientCache && AllowCache)
{
// Set the file time stamps to allow client caching
SetTimeStamps(file);
Response.Cache.SetETag(etag);
}
else
{
SetCacheability();
}
// Log hit or activity
LogEvent(file);
// Add the file data
if ((file.PhysicalFile != "") && (file.OutputData == null))
{
if (!File.Exists(file.PhysicalFile))
{
// File doesn't exist
NotFound();
}
else
{
// Stream the file from the file system
file.OutputData = WriteFile(file.PhysicalFile, cacheOutputData);
}
}
else
{
// Use output data of the file in memory if present
WriteBytes(file.OutputData);
}
}
else
{
NotFound();
}
}
else
{
NotFound();
}
CompleteRequest();
}
///
/// Gets the file ETag
///
/// File
private static string GetFileETag(CMSOutputFile file)
{
// Prepare etag
string etag = file.CultureCode.ToLowerCSafe();
if (file.Attachment != null)
{
etag += "|" + file.Attachment.AttachmentGUID + "|" + file.Attachment.AttachmentLastModified.ToUniversalTime();
}
if (file.IsSecured)
{
// For secured files, add user name to etag
etag += "|" + HttpContext.Current.User.Identity.Name;
}
etag += "|" + CMSContext.ViewMode;
// Put etag into ""
etag = "\"" + etag + "\"";
return etag;
}
///
/// Sets the last modified and expires header to the response
///
/// Output file data
private void SetTimeStamps(CMSOutputFile file)
{
DateTime expires = DateTime.Now;
// Send last modified header to allow client caching
Response.Cache.SetLastModified(file.LastModified);
if (!file.IsSecured)
{
// Setup the client cache
Response.Cache.SetCacheability(HttpCacheability.Public);
if (AllowClientCache)
{
expires = DateTime.Now.AddMinutes(ClientCacheMinutes);
}
}
Response.Cache.SetExpires(expires);
}
///
/// Processes the attachment.
///
protected void ProcessAttachment()
{
outputFile = null;
// If guid given, process the attachment
guid = QueryHelper.GetGuid("guid", Guid.Empty);
allowLatestVersion = CheckAllowLatestVersion();
if (guid != Guid.Empty)
{
// Check version
if (VersionHistoryID > 0)
{
ProcessFile(guid, VersionHistoryID);
}
else
{
ProcessFile(guid);
}
}
else
{
// Get by node GUID
nodeGuid = QueryHelper.GetGuid("nodeguid", Guid.Empty);
if (nodeGuid != Guid.Empty)
{
// If node GUID given, process the file
ProcessNode(nodeGuid);
}
else
{
// Get by alias path and file name
aliasPath = QueryHelper.GetString("aliaspath", null);
fileName = QueryHelper.GetString("filename", null);
if (aliasPath != null)
{
ProcessNode(aliasPath, fileName);
}
}
}
// If chset specified, do not cache
string chset = QueryHelper.GetString("chset", null);
if (chset != null)
{
mIsLatestVersion = true;
}
}
///
/// Processes the specified file and returns the data to the output stream.
///
/// Attachment guid
protected void ProcessFile(Guid attachmentGuid)
{
AttachmentInfo atInfo = null;
bool requiresData = true;
// Check if it is necessary to load the file data
if (useClientCache && IsLiveSite && AllowClientCache)
{
// If possibly cached by client, do not load data (may not be sent)
string ifModifiedString = Request.Headers["If-Modified-Since"];
if (ifModifiedString != null)
{
requiresData = false;
}
}
// If output data available from cache, do not require loading the data
byte[] cachedData = GetCachedOutputData();
if (cachedData != null)
{
requiresData = false;
}
// Get AttachmentInfo object
if (!IsLiveSite)
{
// Not livesite mode - get latest version
if (node != null)
{
atInfo = DocumentHelper.GetAttachment(node, attachmentGuid, TreeProvider, true);
}
else
{
atInfo = DocumentHelper.GetAttachment(attachmentGuid, TreeProvider, CurrentSiteName);
}
}
else
{
if (!requiresData || AttachmentInfoProvider.StoreFilesInFileSystem(CurrentSiteName))
{
// Do not require data from DB - Not necessary or available from file system
atInfo = AttachmentInfoProvider.GetAttachmentInfoWithoutBinary(attachmentGuid, CurrentSiteName);
}
else
{
// Require data from DB - Stored in DB
atInfo = AttachmentInfoProvider.GetAttachmentInfo(attachmentGuid, CurrentSiteName);
}
// If attachment not found,
if (allowLatestVersion && ((atInfo == null) || (latestForHistoryId > 0) || (atInfo.AttachmentDocumentID == latestForDocumentId)))
{
// Get latest version
if (node != null)
{
atInfo = DocumentHelper.GetAttachment(node, attachmentGuid, TreeProvider, true);
}
else
{
atInfo = DocumentHelper.GetAttachment(attachmentGuid, TreeProvider, CurrentSiteName);
}
// If not attachment for the required document, do not return
if ((atInfo.AttachmentDocumentID != latestForDocumentId) && (latestForHistoryId == 0))
{
atInfo = null;
}
else
{
mIsLatestVersion = true;
}
}
}
if (atInfo != null)
{
// Temporary attachment is always latest version
if (atInfo.AttachmentFormGUID != Guid.Empty)
{
mIsLatestVersion = true;
}
// Check if current mimetype is allowed
if (!CheckRequiredMimeType(atInfo))
{
return;
}
bool checkPublishedFiles = AttachmentInfoProvider.CheckPublishedFiles(CurrentSiteName);
bool checkFilesPermissions = AttachmentInfoProvider.CheckFilesPermissions(CurrentSiteName);
// Get the document node
if ((node == null) && (checkPublishedFiles || checkFilesPermissions))
{
// Try to get data from cache
using (CachedSection cs = new CachedSection(ref node, CacheMinutes, !allowLatestVersion, null, "getfilenodebydocumentid", atInfo.AttachmentDocumentID))
{
if (cs.LoadData)
{
// Get the document
node = TreeProvider.SelectSingleDocument(atInfo.AttachmentDocumentID, false);
// Cache the document
CacheNode(cs, node);
}
}
}
bool secured = false;
if ((node != null) && checkFilesPermissions)
{
secured = (node.IsSecuredNode == 1);
// Check secured pages
if (secured)
{
URLRewriter.CheckSecuredAreas(CurrentSiteName, false, ViewMode);
}
if (node.RequiresSSL == 1)
{
URLRewriter.RequestSecurePage(false, node.RequiresSSL, ViewMode, CurrentSiteName);
}
// Check permissions
bool checkPermissions = false;
switch (URLRewriter.CheckPagePermissions(CurrentSiteName))
{
case PageLocationEnum.All:
checkPermissions = true;
break;
case PageLocationEnum.SecuredAreas:
checkPermissions = secured;
break;
}
// Check the read permission for the page
if (checkPermissions)
{
if (CurrentUser.IsAuthorizedPerDocument(node, NodePermissionsEnum.Read) == AuthorizationResultEnum.Denied)
{
URLHelper.Redirect(URLRewriter.AccessDeniedPageURL(CurrentSiteName));
}
}
}
bool resizeImage = (ImageHelper.IsImage(atInfo.AttachmentExtension) && AttachmentInfoProvider.CanResizeImage(atInfo, Width, Height, MaxSideSize));
// If the file should be redirected, redirect the file
if (!mIsLatestVersion && IsLiveSite && SettingsKeyProvider.GetBoolValue(CurrentSiteName + ".CMSRedirectFilesToDisk"))
{
if (AttachmentInfoProvider.StoreFilesInFileSystem(CurrentSiteName))
{
string path = null;
if (!resizeImage)
{
path = AttachmentInfoProvider.GetFilePhysicalURL(CurrentSiteName, atInfo.AttachmentGUID.ToString(), atInfo.AttachmentExtension);
}
else
{
int[] newDim = ImageHelper.EnsureImageDimensions(Width, Height, MaxSideSize, atInfo.AttachmentImageWidth, atInfo.AttachmentImageHeight);
path = AttachmentInfoProvider.GetFilePhysicalURL(CurrentSiteName, atInfo.AttachmentGUID.ToString(), atInfo.AttachmentExtension, newDim[0], newDim[1]);
}
// If path is valid, redirect
if (path != null)
{
// Check if file exists
string filePath = Server.MapPath(path);
if (File.Exists(filePath))
{
outputFile = NewOutputFile();
outputFile.IsSecured = secured;
outputFile.RedirectTo = path;
outputFile.Attachment = atInfo;
}
}
}
}
// Get the data
if ((outputFile == null) || (outputFile.Attachment == null))
{
outputFile = NewOutputFile(atInfo, null);
outputFile.Width = Width;
outputFile.Height = Height;
outputFile.MaxSideSize = MaxSideSize;
outputFile.SiteName = CurrentSiteName;
outputFile.Resized = resizeImage;
// Load the data if required
if (requiresData)
{
// Try to get the physical file, if not latest version
if (!mIsLatestVersion)
{
EnsurePhysicalFile(outputFile);
}
bool loadData = string.IsNullOrEmpty(outputFile.PhysicalFile);
// Load data if necessary
if (loadData)
{
if (atInfo.AttachmentBinary != null)
{
// Load from the attachment
outputFile.LoadData(atInfo.AttachmentBinary);
}
else
{
// Load from the disk
byte[] data = AttachmentInfoProvider.GetFile(atInfo, CurrentSiteName);
outputFile.LoadData(data);
}
// Save data to the cache, if not latest version
if (!mIsLatestVersion && (CacheMinutes > 0))
{
SaveOutputDataToCache(outputFile.OutputData, GetOutputDataDependency(outputFile.Attachment));
}
}
}
else if (cachedData != null)
{
// Load the cached data if available
outputFile.OutputData = cachedData;
}
}
if (outputFile != null)
{
outputFile.IsSecured = secured;
// Add node data
if (node != null)
{
outputFile.AliasPath = node.NodeAliasPath;
outputFile.CultureCode = node.DocumentCulture;
outputFile.FileNode = node;
// Set the file validity
if (IsLiveSite && !mIsLatestVersion && checkPublishedFiles)
{
outputFile.ValidFrom = ValidationHelper.GetDateTime(node.GetValue("DocumentPublishFrom"), DateTime.MinValue);
outputFile.ValidTo = ValidationHelper.GetDateTime(node.GetValue("DocumentPublishTo"), DateTime.MaxValue);
// Set the published flag
outputFile.IsPublished = node.IsPublished;
}
}
}
}
}
///
/// Processes the specified document node.
///
/// Alias path
/// File name
protected void ProcessNode(string currentAliasPath, string currentFileName)
{
// Load the document node
if (node == null)
{
// Try to get data from cache
using (CachedSection cs = new CachedSection(ref node, CacheMinutes, !allowLatestVersion, null, "getfilenodebyaliaspath|", CurrentSiteName, CacheHelper.GetBaseCacheKey(false, true), currentAliasPath))
{
if (cs.LoadData)
{
// Get the document
string className = null;
bool combineWithDefaultCulture = SettingsKeyProvider.GetBoolValue(CurrentSiteName + ".CMSCombineImagesWithDefaultCulture");
string culture = CultureCode;
// Get the document
if (currentFileName == null)
{
// CMS.File
className = "CMS.File";
}
// Get the document data
if (!IsLiveSite)
{
node = DocumentHelper.GetDocument(CurrentSiteName, currentAliasPath, culture, combineWithDefaultCulture, className, null, null, -1, false, null, TreeProvider);
}
else
{
node = TreeProvider.SelectSingleNode(CurrentSiteName, currentAliasPath, culture, combineWithDefaultCulture, className, null, null, -1, false, null);
// Documents should be combined with default culture
if ((node != null) && combineWithDefaultCulture && !node.IsPublished)
{
// Try to find published document in default culture
string defaultCulture = CultureHelper.GetDefaultCulture(CurrentSiteName);
TreeNode cultureNode = TreeProvider.SelectSingleNode(CurrentSiteName, currentAliasPath, defaultCulture, false, className, null, null, -1, false, null);
if ((cultureNode != null) && cultureNode.IsPublished)
{
node = cultureNode;
}
}
}
// Try to find node using the document aliases
if (node == null)
{
DataSet ds = DocumentAliasInfoProvider.GetDocumentAliases("AliasURLPath='" + SqlHelperClass.GetSafeQueryString(currentAliasPath, false) + "'", "AliasCulture DESC", 1, "AliasNodeID, AliasCulture");
if (!DataHelper.DataSourceIsEmpty(ds))
{
DataRow dr = ds.Tables[0].Rows[0];
int nodeId = (int)dr["AliasNodeID"];
string nodeCulture = ValidationHelper.GetString(DataHelper.GetDataRowValue(dr, "AliasCulture"), null);
if (!IsLiveSite)
{
node = DocumentHelper.GetDocument(nodeId, nodeCulture, combineWithDefaultCulture, TreeProvider);
}
else
{
node = TreeProvider.SelectSingleNode(nodeId, nodeCulture, combineWithDefaultCulture);
// Documents should be combined with default culture
if ((node != null) && combineWithDefaultCulture && !node.IsPublished)
{
// Try to find published document in default culture
string defaultCulture = CultureHelper.GetDefaultCulture(CurrentSiteName);
TreeNode cultureNode = TreeProvider.SelectSingleNode(nodeId, defaultCulture, false);
if ((cultureNode != null) && cultureNode.IsPublished)
{
node = cultureNode;
}
}
}
}
}
// Cache the document
CacheNode(cs, node);
}
}
}
// Process the document
ProcessNode(node, null, currentFileName);
}
///
/// Processes the specified document node.
///
/// Node GUID
protected void ProcessNode(Guid currentNodeGuid)
{
// Load the document node
string columnName = QueryHelper.GetString("columnName", String.Empty);
if (node == null)
{
// Try to get data from cache
using (CachedSection cs = new CachedSection(ref node, CacheMinutes, !allowLatestVersion, null, "getfilenodebyguid|", CurrentSiteName, CacheHelper.GetBaseCacheKey(false, true), currentNodeGuid))
{
if (cs.LoadData)
{
// Get the document
bool combineWithDefaultCulture = SettingsKeyProvider.GetBoolValue(CurrentSiteName + ".CMSCombineImagesWithDefaultCulture");
string culture = CultureCode;
string where = "NodeGUID = '" + currentNodeGuid + "'";
// Get the document
string className = null;
if (columnName == "")
{
// CMS.File
className = "CMS.File";
}
else
{
// Other document types
TreeNode srcNode = TreeProvider.SelectSingleNode(currentNodeGuid, CultureCode, CurrentSiteName);
if (srcNode != null)
{
className = srcNode.NodeClassName;
}
}
// Get the document data
if (!IsLiveSite || allowLatestVersion)
{
node = DocumentHelper.GetDocument(CurrentSiteName, null, culture, combineWithDefaultCulture, className, where, null, -1, false, null, TreeProvider);
}
else
{
node = TreeProvider.SelectSingleNode(CurrentSiteName, null, culture, combineWithDefaultCulture, className, where, null, -1, false, null);
// Documents should be combined with default culture
if ((node != null) && combineWithDefaultCulture && !node.IsPublished)
{
// Try to find published document in default culture
string defaultCulture = CultureHelper.GetDefaultCulture(CurrentSiteName);
TreeNode cultureNode = TreeProvider.SelectSingleNode(CurrentSiteName, null, defaultCulture, false, className, where, null, -1, false, null);
if ((cultureNode != null) && cultureNode.IsPublished)
{
node = cultureNode;
}
}
}
// Cache the document
CacheNode(cs, node);
}
}
}
// Process the document node
ProcessNode(node, columnName, null);
}
///
/// Processes the specified document node.
///
/// Document node to process
/// Column name
/// File name
protected void ProcessNode(TreeNode treeNode, string columnName, string processedFileName)
{
if (treeNode != null)
{
// Check if latest or live site version is required
bool latest = !IsLiveSite;
if (allowLatestVersion && ((treeNode.DocumentID == latestForDocumentId) || (treeNode.DocumentCheckedOutVersionHistoryID == latestForHistoryId)))
{
latest = true;
}
// If not published, return no content
if (!latest && !treeNode.IsPublished)
{
outputFile = NewOutputFile(null, null);
outputFile.AliasPath = treeNode.NodeAliasPath;
outputFile.CultureCode = treeNode.DocumentCulture;
if (IsLiveSite && AttachmentInfoProvider.CheckPublishedFiles(CurrentSiteName))
{
outputFile.IsPublished = treeNode.IsPublished;
}
outputFile.FileNode = treeNode;
outputFile.Height = Height;
outputFile.Width = Width;
outputFile.MaxSideSize = MaxSideSize;
}
else
{
// Get valid site name if link
if (treeNode.IsLink)
{
TreeNode origNode = TreeProvider.GetOriginalNode(treeNode);
if (origNode != null)
{
SiteInfo si = SiteInfoProvider.GetSiteInfo(origNode.NodeSiteID);
if (si != null)
{
CurrentSiteName = si.SiteName;
}
}
}
// Process the node
// Get from specific column
if (String.IsNullOrEmpty(columnName) && String.IsNullOrEmpty(processedFileName) && treeNode.NodeClassName.EqualsCSafe("CMS.File", true))
{
columnName = "FileAttachment";
}
if (!String.IsNullOrEmpty(columnName))
{
// File document type or specified by column
Guid attachmentGuid = ValidationHelper.GetGuid(treeNode.GetValue(columnName), Guid.Empty);
if (attachmentGuid != Guid.Empty)
{
ProcessFile(attachmentGuid);
}
}
else
{
// Get by file name
if (processedFileName == null)
{
// CMS.File - Get
Guid attachmentGuid = ValidationHelper.GetGuid(treeNode.GetValue("FileAttachment"), Guid.Empty);
if (attachmentGuid != Guid.Empty)
{
ProcessFile(attachmentGuid);
}
}
else
{
// Other document types, get the attachment by file name
AttachmentInfo ai = null;
if (latest)
{
// Not livesite mode - get latest version
ai = DocumentHelper.GetAttachment(treeNode, processedFileName, TreeProvider, false);
}
else
{
// Live site mode, get directly from database
ai = AttachmentInfoProvider.GetAttachmentInfo(treeNode.DocumentID, processedFileName, false);
}
if (ai != null)
{
ProcessFile(ai.AttachmentGUID);
}
}
}
}
}
}
///
/// Processes the specified version of the file and returns the data to the output stream.
///
/// Attachment GUID
/// Document version history ID
protected void ProcessFile(Guid attachmentGuid, int versionHistoryId)
{
AttachmentInfo atInfo = GetFile(attachmentGuid, versionHistoryId);
if (atInfo != null)
{
// If attachment is image, try resize
byte[] mFile = atInfo.AttachmentBinary;
if (mFile != null)
{
string mimetype = null;
if (ImageHelper.IsImage(atInfo.AttachmentExtension))
{
if (AttachmentInfoProvider.CanResizeImage(atInfo, Width, Height, MaxSideSize))
{
// Do not search thumbnail on the disk
mFile = AttachmentInfoProvider.GetImageThumbnail(atInfo, CurrentSiteName, Width, Height, MaxSideSize, false);
mimetype = "image/jpeg";
}
}
if (mFile != null)
{
outputFile = NewOutputFile(atInfo, mFile);
}
else
{
outputFile = NewOutputFile();
}
outputFile.Height = Height;
outputFile.Width = Width;
outputFile.MaxSideSize = MaxSideSize;
outputFile.MimeType = mimetype;
}
// Get the file document
if (node == null)
{
node = TreeProvider.SelectSingleDocument(atInfo.AttachmentDocumentID);
}
if (node != null)
{
// Check secured area
SiteInfo si = SiteInfoProvider.GetSiteInfo(node.NodeSiteID);
if (si != null)
{
if (pi == null)
{
pi = PageInfoProvider.GetPageInfo(si.SiteName, node.NodeAliasPath, node.DocumentCulture, node.DocumentUrlPath, false);
}
if (pi != null)
{
URLRewriter.RequestSecurePage(pi, false, ViewMode, CurrentSiteName);
URLRewriter.CheckSecuredAreas(CurrentSiteName, pi, false, ViewMode);
}
}
// Check the permissions for the document
if ((CurrentUser.IsAuthorizedPerDocument(node, NodePermissionsEnum.Read) == AuthorizationResultEnum.Allowed) || (node.NodeOwner == CurrentUser.UserID))
{
if (outputFile == null)
{
outputFile = NewOutputFile();
}
outputFile.AliasPath = node.NodeAliasPath;
outputFile.CultureCode = node.DocumentCulture;
if (IsLiveSite && AttachmentInfoProvider.CheckPublishedFiles(CurrentSiteName))
{
outputFile.IsPublished = node.IsPublished;
}
outputFile.FileNode = node;
}
else
{
outputFile = null;
}
}
}
}
///
/// Gets the file from version history.
///
/// Atachment GUID
/// Version history ID
protected AttachmentInfo GetFile(Guid attachmentGuid, int versionHistoryId)
{
VersionManager vm = VersionManager.GetInstance(TreeProvider);
// Get the attachment version
AttachmentHistoryInfo attachmentVersion = vm.GetAttachmentVersion(versionHistoryId, attachmentGuid);
if (attachmentVersion == null)
{
return null;
}
else
{
// Create the attachment object from the version
AttachmentInfo ai = new AttachmentInfo(attachmentVersion.Generalized.DataClass);
ai.AttachmentVersionHistoryID = versionHistoryId;
return ai;
}
}
///
/// Returns the output data dependency based on the given attachment record.
///
/// Attachment object
protected CacheDependency GetOutputDataDependency(AttachmentInfo ai)
{
return (ai == null) ? null : CacheHelper.GetCacheDependency(AttachmentInfoProvider.GetDependencyCacheKeys(ai));
}
///
/// Returns the cache dependency for the given document node.
///
/// Document node
protected CacheDependency GetNodeDependency(TreeNode node)
{
string siteName = CurrentSiteName.ToLowerCSafe();
return CacheHelper.GetCacheDependency(new string[]
{
CacheHelper.FILENODE_KEY,
CacheHelper.FILENODE_KEY + "|" + siteName,
"node|" + siteName + "|" + node.NodeAliasPath.ToLowerCSafe()
});
}
///
/// Ensures the security settings in the given document node.
///
/// Document node
protected void EnsureSecuritySettings(TreeNode node)
{
if (AttachmentInfoProvider.CheckFilesPermissions(CurrentSiteName))
{
// Load secured values
node.LoadInheritedValues(new string[] { "IsSecuredNode", "RequiresSSL" });
}
}
///
/// Handles the document caching actions.
///
/// Cached section
/// Document node
protected void CacheNode(CachedSection cs, TreeNode node)
{
if (node != null)
{
// Load the security settings
EnsureSecuritySettings(node);
// Save to the cache
if (cs.Cached)
{
cs.CacheDependency = GetNodeDependency(node);
}
}
else
{
// Do not cache in case not cached
cs.CacheMinutes = 0;
}
cs.Data = node;
}
///
/// Logs analytics and/or activity event.
///
/// File to be sent
protected void LogEvent(CMSOutputFile file)
{
if (IsLiveSite && (file != null) && (file.FileNode != null) && (file.FileNode.NodeClassName.ToLowerCSafe() == "cms.file"))
{
// Check if request is multipart request and log event if not
GetRange(100, HttpContext.Current); // GetRange() parses request header and sets 'IsMultipart' and 'IsRangeRequest' properties
if (IsMultipart || IsRangeRequest)
{
return;
}
if (file.Attachment == null)
{
return;
}
// Log analytics hit
if (AnalyticsHelper.IsLoggingEnabled(CurrentSiteName, String.Empty, LogExcludingFlags.SkipFileExtensionCheck) && AnalyticsHelper.TrackFileDownloadsEnabled(CurrentSiteName) && !AnalyticsHelper.IsFileExtensionExcluded(CurrentSiteName, file.Attachment.AttachmentExtension))
{
HitLogProvider.LogHit(HitLogProvider.FILE_DOWNLOADS, CurrentSiteName, file.FileNode.DocumentCulture, file.FileNode.NodeAliasPath, file.FileNode.NodeID);
}
// Log download activity
if (LoggingActivityEnabled(file) && LogFileDownload(file))
{
Activity activity = new ActivityPageVisit(file.FileNode, file.FileNode.GetDocumentName(), null, null, CMSContext.ActivityEnvironmentVariables);
if (activity.Data != null)
{
activity.Data.Value = file.Attachment.AttachmentName;
activity.Data.Culture = file.FileNode.DocumentCulture;
activity.Data.NodeID = file.FileNode.NodeID;
activity.Data.SiteID = SiteInfoProvider.GetSiteID(CurrentSiteName);
activity.Log();
}
}
}
}
///
/// Checks if page visit activity logging is enabled, if so returns contact ID.
///
/// File to be sent
protected bool LoggingActivityEnabled(CMSOutputFile file)
{
if ((file == null) || (file.FileNode == null))
{
return false;
}
// Check if logging is enabled
if (ActivitySettingsHelper.ActivitiesEnabledAndModuleLoaded(CurrentSiteName) && ActivitySettingsHelper.ActivitiesEnabledForThisUser(CMSContext.CurrentUser))
{
if (file.Attachment != null)
{
// Get allowed extensions (if not specified log everything)
bool doLog = true;
string tracked = SettingsKeyProvider.GetStringValue(CurrentSiteName + ".CMSActivityTrackedExtensions");
if (!String.IsNullOrEmpty(tracked))
{
string extension = file.Attachment.AttachmentExtension;
if (extension != null)
{
string extensions = String.Format(";{0};", tracked.ToLowerCSafe().Trim().Trim(';'));
extension = extension.TrimStart('.').ToLowerCSafe();
doLog = extensions.Contains(String.Format(";{0};", extension));
}
}
return doLog;
}
}
return false;
}
///
/// Check if logging is enabled for current document.
///
private bool LogFileDownload(CMSOutputFile file)
{
if ((file == null) || (file.FileNode == null))
{
return false;
}
return (((file.FileNode.DocumentLogVisitActivity == true)
|| (file.FileNode.DocumentLogVisitActivity == null)
&& ValidationHelper.GetBoolean(file.FileNode.GetInheritedValue("DocumentLogVisitActivity", SiteInfoProvider.CombineWithDefaultCulture(CurrentSiteName)), false)));
}
///
/// Ensures the physical file.
///
/// Output file
public bool EnsurePhysicalFile(CMSOutputFile file)
{
if (file == null)
{
return false;
}
// Try to link to file system
if (String.IsNullOrEmpty(file.Watermark) && (file.Attachment != null) && (file.Attachment.AttachmentVersionHistoryID == 0) && AttachmentInfoProvider.StoreFilesInFileSystem(file.SiteName))
{
string filePath = AttachmentInfoProvider.EnsurePhysicalFile(file.Attachment, file.SiteName);
if (filePath != null)
{
if (file.Resized)
{
// If resized, ensure the thumbnail file
if (AttachmentInfoProvider.GenerateThumbnails(file.SiteName))
{
filePath = AttachmentInfoProvider.EnsureThumbnailFile(file.Attachment, file.SiteName, Width, Height, MaxSideSize);
if (filePath != null)
{
// Link to the physical file
file.PhysicalFile = filePath;
return true;
}
}
}
else
{
// Link to the physical file
file.PhysicalFile = filePath;
return false;
}
}
}
file.PhysicalFile = "";
return false;
}
///
/// Returns true if latest version of the document is allowed.
///
public bool CheckAllowLatestVersion()
{
// Check if latest version is required
latestForDocumentId = QueryHelper.GetInteger("latestfordocid", 0);
latestForHistoryId = QueryHelper.GetInteger("latestforhistoryid", 0);
if ((latestForDocumentId > 0) || (latestForHistoryId > 0))
{
// Validate the hash
string hash = QueryHelper.GetString("hash", "");
string validate = (latestForDocumentId > 0) ? "d" + latestForDocumentId : "h" + latestForHistoryId;
if (!String.IsNullOrEmpty(hash) && QueryHelper.ValidateHashString(validate, hash))
{
return true;
}
}
return false;
}
///
/// Gets the new output file object.
///
public CMSOutputFile NewOutputFile()
{
CMSOutputFile file = new CMSOutputFile();
file.Watermark = Watermark;
file.WatermarkPosition = WatermarkPosition;
return file;
}
///
/// Gets the new output file object.
///
/// AttachmentInfo
/// Output file data
public CMSOutputFile NewOutputFile(AttachmentInfo ai, byte[] data)
{
CMSOutputFile file = new CMSOutputFile(ai, data);
file.Watermark = Watermark;
file.WatermarkPosition = WatermarkPosition;
return file;
}
}