using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using CMS.CMSHelper; using CMS.ExtendedControls; using CMS.GlobalHelper; using CMS.IO; using CMS.SettingsProvider; using CMS.UIControls; public partial class CMSAdminControls_Silverlight_MultiFileUploader_MultiFileUploader : CMSUserControl { #region "Constants" private const string PARAMETER_SEPARATOR = "|"; private const string APPLICATION_PATH = "~/ClientBin/MultiFileUploader.xap"; #endregion #region "Variables" private bool? mEnabled = null; private int mResizeToWidth = -1; private int mResizeToHeight = -1; private int mResizeToMaxSideSize = -1; private bool mMultiSelect = false; private int mMaxNumberToUpload = 0; private long mMaximumTotalUpload = 0; private long mMaximumUpload = 0; private int mMaxConcurrentUploads = 1; private long mUploadChunkSize = 0; private MultifileUploaderModeEnum mUploadMode = MultifileUploaderModeEnum.DirectSingle; private bool mIsInsertMode = false; private bool mCheckPermissions = false; private bool mOnlyImages = false; private string mTargetFolderPath = null; private string mTargetFilePath = null; private string mTargetAliasPath = null; private string mTargetCulture = null; private bool mIncludeExtension = false; private MediaSourceEnum mSourceType = MediaSourceEnum.Web; private bool mIncludeNewItemInfo = false; private bool mRaiseOnClick = false; private int mNodeID = 0; private string mDocumentCulture = null; private string mNodeSiteName = null; private int mNodeGroupID = 0; private int mMediaLibraryID = 0; private bool mIsMediaThumbnail = false; private int mMediaFileID = 0; private int mPostForumID = 0; private int mPostID = 0; private Guid mAttachmentGroupGUID = Guid.Empty; private Guid mFormGUID = Guid.Empty; private int mDocumentID = 0; private int mDocumentParentNodeID = 0; private bool mIsFiledAttachment = false; private Guid mAttachmentGUID = Guid.Empty; private int mSiteID = 0; private int mMetaFileID = 0; private int mObjectID = 0; private string mObjectType = null; private string mCategory = null; #endregion #region "General properties" /// /// Indicates whether the post-upload JavaScript function call should include created attachment GUID information. /// public bool IncludeNewItemInfo { get { return mIncludeNewItemInfo; } set { mIncludeNewItemInfo = value; } } /// /// Gets or sets type of the content uploaded by the control. /// public virtual MediaSourceEnum SourceType { get { return mSourceType; } set { mSourceType = value; // Ensure field attachment flag if (value == MediaSourceEnum.Attachment) { IsFieldAttachment = true; } } } /// /// Unique ID of the control, for which the postback should be made after upload is finished. /// public string EventTarget { get; set; } /// /// Target folder path, to which physical files will be uploaded. /// public string TargetFolderPath { get { return mTargetFolderPath; } set { mTargetFolderPath = value; } } /// /// Target file name, to which physical files will be uploaded. /// public string TargetFileName { get { return mTargetFilePath; } set { mTargetFilePath = value; } } /// /// Target alias path, to which files will be uploaded. /// public string TargetAliasPath { get { return mTargetAliasPath; } set { mTargetAliasPath = value; } } /// /// Target culture, to which files will be uploaded. /// public string TargetCulture { get { return mTargetCulture; } set { mTargetCulture = value; } } /// /// Indicates if file extension sould be included in file name during grid file upload. /// public bool IncludeExtension { get { return mIncludeExtension; } set { mIncludeExtension = value; } } /// /// ID of parent element. /// public string ParentElemID { get; set; } /// /// JavaScript function name called after save of new file. /// public string AfterSaveJavascript { get; set; } /// /// Uploader instance guid. /// private Guid InstanceGuid { get { object o = ViewState["InstanceGuid"]; if (o == null) { o = Guid.NewGuid(); } return ValidationHelper.GetGuid(o, Guid.Empty); } } /// /// Indicates if only images is allowed for upload. /// public bool OnlyImages { get { return mOnlyImages; } set { mOnlyImages = value; } } /// /// Indicates whether the permissions should be explicitly checked. /// public bool CheckPermissions { get { return mCheckPermissions; } set { mCheckPermissions = value; } } /// /// Value indicating whether the silverlight application should be windowless or not. Default is true. /// public bool IsWindowless { get { return slApplication.IsWindowless; } set { slApplication.IsWindowless = value; } } /// /// Upload mode for the silverlight uploader application. /// public MultifileUploaderModeEnum UploadMode { get { return mUploadMode; } set { mUploadMode = value; } } /// /// Size of the upload chunk. If set to 0 the default value is used. The default value is 4 MB. /// public long UploadChunkSize { get { return mUploadChunkSize; } set { mUploadChunkSize = value; } } /// /// Max number of concurrent uploads. /// public int MaxConcurrentUploads { get { return mMaxConcurrentUploads; } set { mMaxConcurrentUploads = value; } } /// /// Value of the maximum upload size of a single file. /// public long MaximumUpload { get { return mMaximumUpload; } set { mMaximumUpload = value; } } /// /// Value of the maximum total upload. /// public long MaximumTotalUpload { get { return mMaximumTotalUpload; } set { mMaximumTotalUpload = value; } } /// /// Max number of possible upload files. /// public int MaxNumberToUpload { get { return mMaxNumberToUpload; } set { mMaxNumberToUpload = value; } } /// /// Value indicating whether multiselect is enabled in the open file dialog window. /// public bool Multiselect { get { return mMultiSelect; } set { mMultiSelect = value; } } /// /// Silverlight application container width. /// public Unit Width { get { return slApplication.Width; } set { slApplication.Width = value; } } /// /// Silverlight application container height. /// public Unit Height { get { return slApplication.Height; } set { slApplication.Height = value; } } /// /// Width of attachment. /// public int ResizeToWidth { get { if (mResizeToWidth == -1) { mResizeToWidth = SettingsKeyProvider.GetIntValue(CMSContext.CurrentSiteName + ".CMSAutoResizeImageWidth"); } return mResizeToWidth; } set { mResizeToWidth = value; } } /// /// Height of attachment. /// public int ResizeToHeight { get { if (mResizeToHeight == -1) { mResizeToHeight = SettingsKeyProvider.GetIntValue(CMSContext.CurrentSiteName + ".CMSAutoResizeImageHeight"); } return mResizeToHeight; } set { mResizeToHeight = value; } } /// /// Maximum side size of attachment. /// public int ResizeToMaxSideSize { get { if (mResizeToMaxSideSize == -1) { mResizeToMaxSideSize = SettingsKeyProvider.GetIntValue(CMSContext.CurrentSiteName + ".CMSAutoResizeImageMaxSideSize"); } return mResizeToMaxSideSize; } set { mResizeToMaxSideSize = value; } } /// /// List of allowed extensions. /// public string AllowedExtensions { get; set; } /// /// Correct file handler url according to uploader mode. /// public string UploadHandlerUrl { get { string url = string.Empty; if (MediaLibraryID > 0) { url = "~/CMSModules/MediaLibrary/CMSPages/MultiFileUploader.ashx"; } else { if (PostForumID > 0) { url = "~/CMSModules/Forums/CMSPages/MultiFileUploader.ashx"; } else { url = "~/CMSModules/Content/CMSPages/MultiFileUploader.ashx"; } } return HttpUtility.UrlEncode(URLHelper.GetAbsoluteUrl(url)); } } /// /// Gets the ClientID of the silverlight application. /// public string SilverlightApplicationClientID { get { return slApplication.ClientID; } } /// /// Value indicating whether control is in insert mode or not. Default is false. /// public bool IsInsertMode { get { return mIsInsertMode; } set { mIsInsertMode = value; } } /// /// Indicates if supported browser. /// public bool RaiseOnClick { get { return mRaiseOnClick; } set { mRaiseOnClick = value; } } /// /// Enabled property specifing whether the silverlight uploader application is enabled. If set to false only alternate uploader is rendered. /// public bool Enabled { get { if (mEnabled == null) { mEnabled = ValidationHelper.GetBoolean(SettingsHelper.AppSettings["CMSUseSilverlightUploader"], true) && DirectoryHelper.CheckPermissions(Server.MapPath(UploaderHelper.TEMP_PATH), true, true, true, true); } return (mEnabled ?? false); } set { mEnabled = value; } } /// /// HTML content which is displayed to user when Silverlight plugin is not installed. /// [PersistenceMode(PersistenceMode.InnerDefaultProperty)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public virtual ControlCollection AlternateContent { get { return (ControlCollection)slApplication.Controls; } } #endregion #region "Media Library Properties" /// /// ID of the media file /// public int MediaFileID { get { return mMediaFileID; } set { mMediaFileID = value; } } /// /// Determines whether the uploader should upload media file thumbnail or basic media file /// public bool IsMediaThumbnail { get { return mIsMediaThumbnail; } set { mIsMediaThumbnail = value; } } /// /// Media file name /// public string MediaFileName { get; set; } /// /// Id of the media library. /// public int MediaLibraryID { get { return mMediaLibraryID; } set { mMediaLibraryID = value; } } /// /// Name of the media library folder. /// public string MediaFolderPath { get; set; } #endregion #region "CMS.File Properties" /// /// Current site name. /// public string NodeSiteName { get { if (mNodeSiteName == null) { mNodeSiteName = CMSContext.CurrentSiteName; } return mNodeSiteName; } set { mNodeSiteName = value; } } /// /// ID of the parent node, where to upload CMS.File. /// public int NodeID { get { return mNodeID; } set { mNodeID = value; } } /// /// The culture in which the new CMS.Files should be created. /// public string DocumentCulture { get { if (mDocumentCulture == null) { mDocumentCulture = CMSContext.CurrentUser.PreferredCultureCode; } return mDocumentCulture; } set { mDocumentCulture = value; } } /// /// If set, NodeGroupID of content file is set also. /// public virtual int NodeGroupID { get { return mNodeGroupID; } set { mNodeGroupID = value; } } #endregion #region "Forum Attachment Properties" /// /// ID of the post forum. /// public int PostForumID { get { return mPostForumID; } set { mPostForumID = value; } } /// /// ID of the post. /// public int PostID { get { return mPostID; } set { mPostID = value; } } #endregion #region "Attachment properties" /// /// GUID of attachment /// public Guid AttachmentGUID { get { return mAttachmentGUID; } set { mAttachmentGUID = value; } } /// /// GUID of the attachment group. /// public Guid AttachmentGroupGUID { get { return mAttachmentGroupGUID; } set { mAttachmentGroupGUID = value; } } /// /// The name of the document attachment column. /// public string AttachmentGUIDColumnName { get; set; } /// /// GUID of the form. /// public Guid FormGUID { get { return mFormGUID; } set { mFormGUID = value; } } /// /// ID of the document. /// public int DocumentID { get { return mDocumentID; } set { mDocumentID = value; } } /// /// Id of the parent node. /// public int DocumentParentNodeID { get { return mDocumentParentNodeID; } set { mDocumentParentNodeID = value; } } /// /// Document class name. /// public string NodeClassName { get; set; } /// /// Value which determines whether the upload is for field attachment or not. /// public bool IsFieldAttachment { get { return mIsFiledAttachment; } set { mIsFiledAttachment = value; } } #endregion #region "MetaFile Properties" /// /// ID of the site, where to upload MetaFile. /// public int SiteID { get { return mSiteID; } set { mSiteID = value; } } /// /// Metafile ID for reupload. /// public int MetaFileID { get { return mMetaFileID; } set { mMetaFileID = value; } } /// /// ID of the meta file parent object. /// public int ObjectID { get { return mObjectID; } set { mObjectID = value; } } /// /// The object type of the metafile. /// public string ObjectType { get { return mObjectType; } set { mObjectType = value; } } /// /// The category of the metafile. /// public string Category { get { return mCategory; } set { mCategory = value; } } #endregion #region "Javascript Properties" /// /// Container client Id passed to each upload javascript functions(OnUploadBegin, OnUploadProgressChanged, OnUploadCompleted) as first parameter. /// public string ContainerID { get; set; } /// /// Name of the javascript function called when upload progress is changed. /// public string OnUploadProgressChanged { get; set; } /// /// Name of the javascript function called when upload is finished. /// public string OnUploadCompleted { get; set; } /// /// Name of the javascript function called before upload begins. /// public string OnUploadBegin { get; set; } #endregion #region "Page Events" protected void Page_Load(object sender, EventArgs e) { if (!RequestHelper.IsPostBack()) { ReloadData(); } } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); ReloadData(); } #endregion #region "Public Methods" /// /// Loads data of the control. /// public void ReloadData() { if (BrowserHelper.IsSafari() || BrowserHelper.IsOpera()) { // Disable uploader in safari and opera - silverlight is not fully supported slApplication.Enabled = false; } else { string[,] additionParams = new string[1, 2]; additionParams[0, 0] = "splashscreensource"; additionParams[0, 1] = ResolveUrl("~/ClientBin/MultiFileUploader.xaml"); slApplication.AdditionalParameters = additionParams; slApplication.Enabled = Enabled; slApplication.ApplicationPath = APPLICATION_PATH; slApplication.Parameters = GetParameters(); LoadResources(); } } private void LoadResources() { StringBuilder sb = new StringBuilder(); List resources = new List() { "sl.mfu.upload", "sl.mfu.cancel", "sl.mfu.name", "sl.mfu.size", "sl.mfu.progress", "sl.mfu.totalfiles", "sl.mfu.totalsize", "sl.mfu.selectfiles", "sl.mfu.clear", "sl.mfu.error.noaliaspath", "sl.mfu.error.maxnumbertoupload", "sl.mfu.error.maxuploadamount", "sl.mfu.error.maxuploadsize", "sl.mfu.error.fileexists" }; // Create javascript object with all resources sb.Append("window.MFUResourceKeys = [];\nwindow.MFUResources = {};\n"); resources.ForEach(resource => sb.Append(String.Format("window.MFUResourceKeys.push('{0}');\nwindow.MFUResources['{0}'] = {1};\n", resource, ScriptHelper.GetString(ResHelper.GetString(resource))) ) ); ScriptHelper.RegisterStartupScript(Page, typeof(string), "MFUResources", sb.ToString(), true); } #endregion #region "Private Methods" /// /// Returns arguments string with security hash. /// /// Arguments array private static string GetArgumentsString(string[] args) { string arguments = null; if ((args != null) && (args.Length > 0)) { arguments = String.Join(PARAMETER_SEPARATOR, args); } if (!String.IsNullOrEmpty(arguments)) { arguments = String.Format("{0}{1}Hash{1}{2}", arguments, PARAMETER_SEPARATOR, ValidationHelper.GetHashString(arguments, false)); } return HttpUtility.UrlEncode(arguments); } /// /// Returns additional parameters needed by the handler. /// private string GetAdditionalParameters() { string[] args = new string[] { "SourceType", SourceType.ToString(), "ParentElementID", ParentElemID, "IsInsertMode", IsInsertMode.ToString(), "AfterSaveJavascript", AfterSaveJavascript, "TargetFolderPath", HttpUtility.UrlEncode(TargetFolderPath), "TargetFileName", HttpUtility.UrlEncode(TargetFileName), "IncludeNewItemInfo", IncludeNewItemInfo.ToString(), "OnlyImages", OnlyImages.ToString(), "RaiseOnClick", RaiseOnClick.ToString(), "TargetAliasPath", TargetAliasPath, "TargetCulture", TargetCulture, "EventTarget", EventTarget }; return "AdditionalParameters=" + GetArgumentsString(args); } /// /// Returns parameters according to the upload mode. /// private string GetModeParameters() { string[] args = null; if (MediaLibraryID > 0) { // MediaLibrary mode args = new string[] { "MediaLibraryID", MediaLibraryID.ToString(), "MediaFolderPath", HttpUtility.UrlEncode(MediaFolderPath), "MediaFileID", MediaFileID.ToString(), "IsMediaThumbnail", IsMediaThumbnail.ToString(), "MediaFileName", HttpUtility.UrlEncode(MediaFileName) }; return "MediaLibraryArgs=" + GetArgumentsString(args); } else { if ((NodeID > 0) && (SourceType == MediaSourceEnum.Content)) { // CMS.File mode args = new string[] { "NodeID", NodeID.ToString(), "DocumentCulture", DocumentCulture, "IncludeExtension", IncludeExtension.ToString(), "NodeGroupID", NodeGroupID.ToString() }; return "FileArgs=" + GetArgumentsString(args); } else { if (ObjectID > 0) { // MetaFile mode args = new string[] { "MetaFileID", MetaFileID.ToString(), "ObjectID", ObjectID.ToString(), "SiteID", SiteID.ToString(), "ObjectType", ObjectType, "Category", Category }; return "MetaFileArgs=" + GetArgumentsString(args); } else { if (PostForumID > 0) { // Forum attachment args = new string[] { "PostForumID", PostForumID.ToString(), "PostID", PostID.ToString() }; return "ForumArgs=" + GetArgumentsString(args); } else { if ((DocumentID > 0) || (FormGUID != Guid.Empty)) { // Attachment mode args = new string[] { "DocumentID", DocumentID.ToString(), "DocumentParentNodeID", DocumentParentNodeID.ToString(), "NodeClassName", NodeClassName, "AttachmentGUIDColumnName", AttachmentGUIDColumnName, "AttachmentGUID", AttachmentGUID.ToString(), "AttachmentGroupGUID", AttachmentGroupGUID.ToString(), "FormGUID", FormGUID.ToString(), "IsFieldAttachment", mIsFiledAttachment.ToString() }; return "AttachmentArgs=" + GetArgumentsString(args); } } } } } return String.Empty; } /// /// Returns the silverlight parematers according to the settings. /// private string GetParameters() { // Get the extension filter string[] parameters = { // Uploader instance guid string.Format("InstanceGuid={0}", InstanceGuid), // Resize parameters string.Format("ResizeArgs={0};{1};{2}", ResizeToWidth, ResizeToHeight, ResizeToMaxSideSize), // Mode parameters GetModeParameters(), // Upload page parameters string.Format("UploadPage={0}", UploadHandlerUrl), // Filter parameters GetFilterParameters(), // Javascript event parameters GetJavascriptEventsParameters(), // Restriction parameters GetRestrictionParameters(), // Upload mode string.Format("UploadMode={0}", UploadMode), // Additional parameters GetAdditionalParameters() }; return string.Join(",", parameters); } /// /// Returns restriction parameters for the uploader. /// private string GetRestrictionParameters() { return string.Format("Multiselect={0},MaxNumberToUpload={1},MaximumTotalUpload={2},MaximumUpload={3},MaxConcurrentUploads={4},UploadChunkSize={5}", Multiselect, MaxNumberToUpload, MaximumTotalUpload, MaximumUpload, MaxConcurrentUploads, UploadChunkSize); } /// /// Returns the filter parameter. /// private string GetFilterParameters() { string filter = null; if (String.IsNullOrEmpty(AllowedExtensions)) { filter = MediaLibraryID > 0 ? SettingsKeyProvider.GetStringValue(CMSContext.CurrentSiteName + ".CMSMediaFileAllowedExtensions") : SettingsKeyProvider.GetStringValue(CMSContext.CurrentSiteName + ".CMSUploadExtensions"); } else { filter = AllowedExtensions; } if (!string.IsNullOrEmpty(filter)) { // Append hash to list of allowed extensions string hash = ValidationHelper.GetHashString(filter, false); filter = String.Format("Filter=Allowed files|*.{0}{1}Hash{1}{2}", filter.Replace(";", "; *."), PARAMETER_SEPARATOR, hash); } return filter; } /// /// Returns javascript events parameters. /// private string GetJavascriptEventsParameters() { return string.Format("OnUploadBegin={0},OnUploadCompleted={1},OnUploadProgressChanged={2},ContainerID={3}", OnUploadBegin, OnUploadCompleted, OnUploadProgressChanged, ContainerID); } #endregion }