Files
OurUmbraco/uWiki/BusinessLogic/WikiFile.cs
T

517 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic;
using umbraco.BusinessLogic;
using System.Xml;
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace uWiki.Businesslogic
{
public class WikiFile
{
public int Id { get; set; }
public string Name { get; set; }
public string Path { get; set; }
public string FileType { get; set; }
public Guid NodeVersion { get; set; }
public int CreatedBy { get; set; }
public int RemovedBy { get; set; }
public int NodeId { get; set; }
public DateTime CreateDate { get; set; }
public bool Current { get; set; }
public int Downloads { get; set; }
public bool Archived { get; set; }
public bool Verified { get; set; }
public List<UmbracoVersion> Versions { get; set; }
public UmbracoVersion Version { get; set; }
public void Delete()
{
if (File.Exists(HttpContext.Current.Server.MapPath(Path)))
File.Delete(HttpContext.Current.Server.MapPath(Path));
Application.SqlHelper.ExecuteNonQuery("DELETE FROM wikiFiles where ID = @id", Application.SqlHelper.CreateParameter("@id", Id));
}
/// <summary>
/// Gets all wiki files for all nodes
/// </summary>
/// <returns></returns>
public static Dictionary<int, IEnumerable<WikiFile>> CurrentFiles(IEnumerable<int> nodeIds)
{
var wikiFiles = new Dictionary<int, List<WikiFile>>();
//we can only have 2000 (actually 2100) SQL parameters used at once, so we need to group them
var nodeBatches = nodeIds.InGroupsOf(2000);
foreach (var nodeBatch in nodeBatches)
{
foreach (var result in ApplicationContext.Current.DatabaseContext.Database.Query<dynamic>("SELECT * FROM wikiFiles WHERE nodeId IN (@nodeIds)", new { nodeIds = nodeBatch }))
{
var file = new WikiFile
{
Id = result.id,
Path = result.path,
Name = result.name,
FileType = result.type,
RemovedBy = result.removedBy,
CreatedBy = result.createdBy,
NodeVersion = result.version,
NodeId = result.nodeId,
CreateDate = result.createDate,
DotNetVersion = result.dotNetVersion,
Downloads = result.downloads,
Archived = result.archived,
Verified = result.verified,
Versions = GetVersionsFromString(result.umbracoVersion)
};
file.Version = file.Versions.Any()
? GetVersionsFromString(result.umbracoVersion)[0]
: UmbracoVersion.DefaultVersion();
if (wikiFiles.ContainsKey(result.nodeId))
{
var list = wikiFiles[result.nodeId];
list.Add(file);
}
else
{
wikiFiles.Add(result.nodeId, new List<WikiFile>(new[] { file }));
}
}
}
return wikiFiles.ToDictionary(x => x.Key, x => (IEnumerable<WikiFile>)x.Value);
}
public string DotNetVersion { get; set; }
public static List<WikiFile> CurrentFiles(int nodeId)
{
var wikiFiles = new List<WikiFile>();
using (var reader = Application.SqlHelper.ExecuteReader("SELECT id FROM wikiFiles WHERE nodeId = @nodeid", Application.SqlHelper.CreateParameter("@nodeId", nodeId)))
{
while (reader.Read())
wikiFiles.Add(new WikiFile(reader.GetInt("id")));
return wikiFiles;
}
}
private readonly Events _events = new Events();
private WikiFile() { }
public static WikiFile Create(string name, Guid node, Guid memberGuid, HttpPostedFile file, string filetype, List<UmbracoVersion> versions)
{
try
{
var filename = file.FileName;
var extension = filename.Substring(filename.LastIndexOf('.') + 1);
if (ExtensionNotAllowed(extension))
return null;
var content = Content.GetContentFromVersion(node);
var member = new Member(memberGuid);
if (content != null)
{
var wikiFile = new WikiFile
{
Name = name,
NodeId = content.Id,
NodeVersion = content.Version,
FileType = filetype,
CreatedBy = member.Id,
Downloads = 0,
Archived = false,
Versions = versions,
Version = versions[0],
Verified = false
};
var path = string.Format("/media/wiki/{0}", content.Id);
if (Directory.Exists(HttpContext.Current.Server.MapPath(path)) == false)
Directory.CreateDirectory(HttpContext.Current.Server.MapPath(path));
path = string.Format("{0}/{1}_{2}.{3}", path, DateTime.Now.Ticks, umbraco.cms.helpers.url.FormatUrl(filename), extension);
file.SaveAs(HttpContext.Current.Server.MapPath(path));
wikiFile.Path = path;
wikiFile.Save();
return wikiFile;
}
}
catch (Exception ex)
{
Log.Add(LogTypes.Debug, -1, ex.ToString());
}
return null;
}
private static bool ExtensionNotAllowed(string extension)
{
return UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Contains(extension.ToLowerInvariant());
}
public static WikiFile Create(string fileName, string extension, Guid node, Guid memberGuid, byte[] file, string filetype, List<UmbracoVersion> versions)
{
try
{
if (ExtensionNotAllowed(extension))
return null;
var content = Content.GetContentFromVersion(node);
var member = new Member(memberGuid);
if (content != null)
{
var wikiFile = new WikiFile
{
Name = fileName,
NodeId = content.Id,
NodeVersion = content.Version,
FileType = filetype,
CreatedBy = member.Id,
Downloads = 0,
Archived = false,
Versions = versions,
Version = versions[0],
Verified = false
};
var path = string.Format("/media/wiki/{0}", content.Id);
if (Directory.Exists(HttpContext.Current.Server.MapPath(path)) == false)
Directory.CreateDirectory(HttpContext.Current.Server.MapPath(path));
fileName = fileName.Substring(0, fileName.LastIndexOf('.') + 1);
path = string.Format("{0}/{1}_{2}.{3}", path, DateTime.Now.Ticks, umbraco.cms.helpers.url.FormatUrl(fileName), extension);
using (var fileStream = new FileStream(HttpContext.Current.Server.MapPath(path), FileMode.Create))
fileStream.Write(file, 0, file.Length);
wikiFile.Path = path;
wikiFile.Save();
return wikiFile;
}
}
catch (Exception ex)
{
Log.Add(LogTypes.Debug, -1, ex.ToString());
}
return null;
}
public void Save()
{
if (Id == 0)
{
var e = new FileCreateEventArgs();
FireBeforeCreate(e);
if (e.Cancel)
return;
Application.SqlHelper.ExecuteNonQuery(
"INSERT INTO wikiFiles (path, name, createdBy, nodeId, version, type, downloads, archived, umbracoVersion, verified) VALUES(@path, @name, @createdBy, @nodeId, @nodeVersion, @type, @downloads, @archived, @umbracoVersion, @verified)",
Application.SqlHelper.CreateParameter("@path", Path),
Application.SqlHelper.CreateParameter("@name", Name),
Application.SqlHelper.CreateParameter("@createdBy", CreatedBy),
Application.SqlHelper.CreateParameter("@nodeId", NodeId),
Application.SqlHelper.CreateParameter("@type", FileType),
Application.SqlHelper.CreateParameter("@nodeVersion", NodeVersion),
Application.SqlHelper.CreateParameter("@downloads", Downloads),
Application.SqlHelper.CreateParameter("@archived", Archived),
Application.SqlHelper.CreateParameter("@umbracoVersion", ToVersionString(Versions)),
Application.SqlHelper.CreateParameter("@verified", Verified)
);
CreateDate = DateTime.Now;
Id = Application.SqlHelper.ExecuteScalar<int>("SELECT MAX(id) FROM wikiFiles WHERE createdBy = @createdBy", Application.SqlHelper.CreateParameter("@createdBy", CreatedBy));
FireAfterCreate(e);
}
else
{
var e = new FileUpdateEventArgs();
FireBeforeUpdate(e);
if (e.Cancel)
return;
Application.SqlHelper.ExecuteNonQuery(
"UPDATE wikiFiles SET path = @path, name = @name, type = @type, [current] = @current, removedBy = @removedBy, version = @version, downloads = @downloads, archived = @archived, umbracoVersion = @umbracoVersion, verified = @verified WHERE id = @id",
Application.SqlHelper.CreateParameter("@path", Path),
Application.SqlHelper.CreateParameter("@name", Name),
Application.SqlHelper.CreateParameter("@type", FileType),
Application.SqlHelper.CreateParameter("@current", Current),
Application.SqlHelper.CreateParameter("@removedBy", RemovedBy),
Application.SqlHelper.CreateParameter("@version", NodeVersion),
Application.SqlHelper.CreateParameter("@id", Id),
Application.SqlHelper.CreateParameter("@downloads", Downloads),
Application.SqlHelper.CreateParameter("@archived", Archived),
Application.SqlHelper.CreateParameter("@umbracoVersion", ToVersionString(Versions)),
Application.SqlHelper.CreateParameter("@verified", Verified)
);
FireAfterUpdate(e);
}
}
//available umbraco version strings: v4, v45, v3
public static WikiFile FindPackageForUmbracoVersion(int nodeid, string umbracoVersion)
{
return FindRelatedFileForUmbracoVersion(nodeid, umbracoVersion, "package");
}
public static WikiFile FindPackageDocumentationForUmbracoVersion(int nodeid, string umbracoVersion)
{
return FindRelatedFileForUmbracoVersion(nodeid, umbracoVersion, "docs");
}
private static WikiFile FindRelatedFileForUmbracoVersion(int nodeid, string umbracoVersion, string fileType)
{
try
{
//try find one based on the specific version first
var id = Application.SqlHelper.ExecuteScalar<int>(
"Select TOP 1 id from wikiFiles where nodeId = @nodeid and type = @packageType and (umbracoVersion like @umbracoVersion) ORDER BY createDate DESC",
Application.SqlHelper.CreateParameter("@nodeid", nodeid),
Application.SqlHelper.CreateParameter("@packageType", fileType),
Application.SqlHelper.CreateParameter("@umbracoVersion", "%" + umbracoVersion + "%")
);
if (id > 0)
return new WikiFile(id);
//if a version specific file wasnt found try and find one based on nan
id = Application.SqlHelper.ExecuteScalar<int>(
"Select TOP 1 id from wikiFiles where nodeId = @nodeid and type = @packageType and (umbracoVersion like '%nan%') ORDER BY createDate DESC",
Application.SqlHelper.CreateParameter("@nodeid", nodeid),
Application.SqlHelper.CreateParameter("@packageType", fileType)
);
if (id > 0)
return new WikiFile(id);
}
catch
{
return null;
}
return null;
}
public WikiFile(int id)
{
using (var reader = Application.SqlHelper.ExecuteReader("SELECT * FROM wikiFiles WHERE id = @fileId",
Application.SqlHelper.CreateParameter("@fileId", id)))
{
if (reader.Read())
{
Id = reader.GetInt("id");
Path = reader.GetString("path");
Name = reader.GetString("name");
FileType = reader.GetString("type");
RemovedBy = reader.GetInt("removedBy");
CreatedBy = reader.GetInt("createdBy");
NodeVersion = reader.GetGuid("version");
NodeId = reader.GetInt("nodeId");
CreateDate = reader.GetDateTime("createDate");
Current = reader.GetBoolean("current");
Downloads = reader.GetInt("downloads");
Archived = reader.GetBoolean("archived");
Verified = reader.GetBoolean("verified");
DotNetVersion = reader.GetString("dotNetVersion");
Versions = GetVersionsFromString(reader.GetString("umbracoVersion"));
Version = Versions.Any()
? GetVersionsFromString(reader.GetString("umbracoVersion"))[0]
: UmbracoVersion.DefaultVersion();
}
else
{
throw new ArgumentException(string.Format("No node exists with id '{0}'", Id));
}
}
}
public void UpdateDownloadCounter()
{
UpdateDownloadCount(this.Id, false, true);
}
public void UpdateDownloadCounter(bool ignoreCookies, bool isPackage)
{
UpdateDownloadCount(this.Id, ignoreCookies, isPackage);
}
public static List<UmbracoVersion> GetVersionsFromString(string p)
{
var umbracoVersions = new List<UmbracoVersion>();
foreach (var ver in p.Split(','))
{
if (UmbracoVersion.AvailableVersions().ContainsKey(ver))
umbracoVersions.Add(UmbracoVersion.AvailableVersions()[ver]);
}
return umbracoVersions;
}
public static string ToVersionString(List<UmbracoVersion> versions)
{
var umbracoVersions = string.Empty;
foreach (var ver in versions)
umbracoVersions += string.Format("{0},", ver.Version);
return umbracoVersions.TrimEnd(',');
}
public void UpdateDownloadCount(int fileId, bool ignoreCookies, bool isPackage)
{
var cookie = HttpContext.Current.Request.Cookies["ProjectFileDownload" + fileId];
if (cookie != null && ignoreCookies == false)
return;
var downloads = 0;
var projectId = 0;
var reader = Application.SqlHelper.ExecuteReader("Select downloads, nodeId from wikiFiles where id = @id;", Application.SqlHelper.CreateParameter("@id", fileId));
if (reader.Read())
{
downloads = reader.GetInt("downloads");
projectId = reader.GetInt("nodeId");
}
downloads = downloads + 1;
Application.SqlHelper.ExecuteNonQuery(
"update wikiFiles set downloads = @downloads where id = @id;",
Application.SqlHelper.CreateParameter("@id", fileId),
Application.SqlHelper.CreateParameter("@downloads", downloads));
var totalDownloads = Application.SqlHelper.ExecuteScalar<int>("Select SUM(downloads) from wikiFiles where nodeId = @projectId;", Application.SqlHelper.CreateParameter("@projectId", projectId));
if (isPackage)
{
var currentMember = 0;
var member = Member.GetCurrentMember();
if (member != null)
currentMember = member.Id;
//update download count update
Application.SqlHelper.ExecuteNonQuery(
@"insert into projectDownload(projectId,memberId,timestamp)
values((select nodeId from wikiFiles where id = @id) ,@memberId, getdate())",
Application.SqlHelper.CreateParameter("@id", fileId),
Application.SqlHelper.CreateParameter("@memberId", currentMember));
}
var e = new FileDownloadUpdateEventArgs { ProjectId = projectId, Downloads = totalDownloads };
FireAfterDownloadUpdate(e);
cookie = new HttpCookie("ProjectFileDownload" + fileId) { Expires = DateTime.Now.AddHours(1) };
HttpContext.Current.Response.Cookies.Add(cookie);
}
public byte[] ToByteArray()
{
var path = HttpContext.Current.Server.MapPath(this.Path);
byte[] packageByteArray;
using (var fileStream = File.Open(path, FileMode.Open, FileAccess.Read))
{
packageByteArray = new byte[fileStream.Length];
fileStream.Read(packageByteArray, 0, (int)fileStream.Length);
}
return packageByteArray;
}
public XmlNode ToXml(XmlDocument d)
{
XmlNode toXml = d.CreateElement("wikiFile");
toXml.Attributes.Append(umbraco.xmlHelper.addAttribute(d, "id", Id.ToString()));
toXml.Attributes.Append(umbraco.xmlHelper.addAttribute(d, "name", Name));
toXml.Attributes.Append(umbraco.xmlHelper.addAttribute(d, "created", CreateDate.ToString()));
toXml.AppendChild(umbraco.xmlHelper.addCDataNode(d, "path", Path));
toXml.AppendChild(umbraco.xmlHelper.addCDataNode(d, "verified", Verified.ToString()));
return toXml;
}
/* EVENTS */
public static event EventHandler<FileCreateEventArgs> BeforeCreate;
protected virtual void FireBeforeCreate(FileCreateEventArgs e)
{
_events.FireCancelableEvent(BeforeCreate, this, e);
}
public static event EventHandler<FileCreateEventArgs> AfterCreate;
protected virtual void FireAfterCreate(FileCreateEventArgs e)
{
if (AfterCreate != null)
AfterCreate(this, e);
}
public static event EventHandler<FileRemoveEventArgs> BeforeRemove;
protected virtual void FireBeforeDelete(FileRemoveEventArgs e)
{
_events.FireCancelableEvent(BeforeRemove, this, e);
}
public static event EventHandler<FileRemoveEventArgs> AfterRemove;
protected virtual void FireAfterDelete(FileRemoveEventArgs e)
{
if (AfterRemove != null)
AfterRemove(this, e);
}
public static event EventHandler<FileUpdateEventArgs> BeforeUpdate;
protected virtual void FireBeforeUpdate(FileUpdateEventArgs e)
{
_events.FireCancelableEvent(BeforeUpdate, this, e);
}
public static event EventHandler<FileUpdateEventArgs> AfterUpdate;
protected virtual void FireAfterUpdate(FileUpdateEventArgs e)
{
if (AfterUpdate != null)
AfterUpdate(this, e);
}
public static event EventHandler<FileDownloadUpdateEventArgs> AfterDownloadUpdate;
protected virtual void FireAfterDownloadUpdate(FileDownloadUpdateEventArgs e)
{
if (AfterDownloadUpdate != null)
AfterDownloadUpdate(this, e);
}
}
}