Update: Plugin Updating

Updating plugins from the plugin catalogue, and automatic updating of
plugins after a newer version of Disco is installed.
This commit is contained in:
Gary Sharp
2013-02-14 19:00:01 +11:00
parent 734b02fa1d
commit 8f769809c2
53 changed files with 3795 additions and 2975 deletions
@@ -1,134 +1,135 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Disco.Web.Extensions.MvcExtensions.Bundles
{
public class Bundle
{
private DateTime? _FileLastModified { get; set; }
private string _FileHash { get; set; }
private string _VersionUrl { get; set; }
public string Url { get; private set; }
public string File { get; private set; }
public string FileHash
{
get
{
#if DEBUG
UpdateFileHash();
#endif
return _FileHash;
}
}
public string ContentType { get; private set; }
public string VersionUrl
{
get
{
#if DEBUG
return string.Format("{0}?v={1}", this.Url, this.FileHash);
#else
return _VersionUrl;
#endif
}
}
public Bundle(string Url, string File)
{
if (string.IsNullOrWhiteSpace(Url))
throw new ArgumentNullException("Url");
if (string.IsNullOrWhiteSpace(File))
throw new ArgumentNullException("File");
Uri fileUri;
if (!Uri.TryCreate(File, UriKind.Absolute, out fileUri))
{
File = HttpContext.Current.Server.MapPath(File);
}
var fileInfo = new FileInfo(File);
if (!fileInfo.Exists)
throw new FileNotFoundException(string.Format("Not Found: {0}", File), File);
this.Url = Url;
this.File = File;
switch (fileInfo.Extension.ToLower())
{
case ".css":
this.ContentType = "text/css";
break;
case ".js":
this.ContentType = "text/javascript";
break;
default:
throw new ArgumentException("Unsupported Bundle File Extension");
}
// Write File Hash
if (fileInfo.Length > 0)
UpdateFileHash();
else
this._FileHash = string.Empty;
//this.Version = fileInfo.LastWriteTimeUtc.Ticks;
this._VersionUrl = string.Format("{0}?v={1}", this.Url, this.FileHash);
}
private void UpdateFileHash()
{
if (System.IO.File.Exists(this.File))
{
var fileLastModified = System.IO.File.GetLastWriteTimeUtc(this.File);
if (!this._FileLastModified.HasValue || this._FileLastModified.Value != fileLastModified)
{
this._FileLastModified = fileLastModified;
var fileBytes = System.IO.File.ReadAllBytes(this.File);
if (fileBytes.Length > 0)
{
using (SHA256 sha = SHA256.Create())
{
byte[] hash = sha.ComputeHash(fileBytes);
this._FileHash = HttpServerUtility.UrlTokenEncode(hash);
return;
}
}
}
else
{
// Already Updated
return;
}
}
this._FileHash = string.Empty;
}
internal void ProcessRequest(HttpContext context)
{
// Write Content Type
context.Response.ContentType = this.ContentType;
// Write Headers
var cache = context.Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetOmitVaryStar(true);
cache.SetExpires(DateTime.Now.AddYears(1));
cache.SetValidUntilExpires(true);
cache.SetLastModified(DateTime.Now);
cache.VaryByHeaders["User-Agent"] = true;
// Write File
context.Response.WriteFile(this.File);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Disco.Web.Extensions.MvcExtensions.Bundles
{
public class Bundle
{
private DateTime? _FileLastModified { get; set; }
private string _FileHash { get; set; }
private string _VersionUrl { get; set; }
public string Url { get; private set; }
public string File { get; private set; }
public string FileHash
{
get
{
#if DEBUG
UpdateFileHash();
#endif
return _FileHash;
}
}
public string ContentType { get; private set; }
public string VersionUrl
{
get
{
#if DEBUG
return string.Format("{0}?v={1}", this.Url, this.FileHash);
#else
return _VersionUrl;
#endif
}
}
public Bundle(string Url, string File)
{
if (string.IsNullOrWhiteSpace(Url))
throw new ArgumentNullException("Url");
if (string.IsNullOrWhiteSpace(File))
throw new ArgumentNullException("File");
Uri fileUri;
if (!Uri.TryCreate(File, UriKind.Absolute, out fileUri))
{
File = HttpContext.Current.Server.MapPath(File);
}
var fileInfo = new FileInfo(File);
if (!fileInfo.Exists)
throw new FileNotFoundException(string.Format("Not Found: {0}", File), File);
this.Url = Url;
this.File = File;
switch (fileInfo.Extension.ToLower())
{
case ".css":
this.ContentType = "text/css";
break;
case ".js":
this.ContentType = "text/javascript";
break;
default:
throw new ArgumentException("Unsupported Bundle File Extension");
}
// Write File Hash
if (fileInfo.Length > 0)
UpdateFileHash();
else
this._FileHash = string.Empty;
//this.Version = fileInfo.LastWriteTimeUtc.Ticks;
this._VersionUrl = string.Format("{0}?v={1}", this.Url, this.FileHash);
}
private void UpdateFileHash()
{
if (System.IO.File.Exists(this.File))
{
var fileLastModified = System.IO.File.GetLastWriteTimeUtc(this.File);
if (!this._FileLastModified.HasValue || this._FileLastModified.Value != fileLastModified)
{
this._FileLastModified = fileLastModified;
var fileBytes = System.IO.File.ReadAllBytes(this.File);
if (fileBytes.Length > 0)
{
using (SHA256 sha = SHA256.Create())
{
byte[] hash = sha.ComputeHash(fileBytes);
this._FileHash = HttpServerUtility.UrlTokenEncode(hash);
return;
}
}
}
else
{
// Already Updated
return;
}
}
this._FileHash = string.Empty;
}
internal void ProcessRequest(HttpContext context)
{
// Write Content Type
context.Response.ContentType = this.ContentType;
// Write Headers
var cache = context.Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetOmitVaryStar(true);
cache.SetExpires(DateTime.Now.AddYears(1));
cache.SetValidUntilExpires(true);
cache.SetMaxAge(TimeSpan.FromDays(365));
cache.SetLastModified(DateTime.Now);
cache.VaryByHeaders["User-Agent"] = true;
// Write File
context.Response.WriteFile(this.File);
}
}
}
@@ -1,52 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Disco.Web.Extensions.MvcExtensions.Bundles
{
internal sealed class BundleHandler : IHttpHandler
{
public Bundle RequestBundle { get; private set; }
public string BundleVirtualPath { get; private set; }
public BundleHandler(Bundle requestBundle, string bundleVirtualPath)
{
this.RequestBundle = requestBundle;
this.BundleVirtualPath = bundleVirtualPath;
}
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.Clear();
if (!string.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
context.Response.StatusCode = 0x130;
else
this.RequestBundle.ProcessRequest(context);
}
internal static bool RemapHandlerForBundleRequests(HttpApplication app)
{
var context = app.Context;
string bundleUrlFromContext = context.Request.AppRelativeCurrentExecutionFilePath + context.Request.PathInfo;
var bundle = BundleTable.GetBundleFor(bundleUrlFromContext);
if (bundle != null)
{
context.RemapHandler(new BundleHandler(bundle, bundleUrlFromContext));
return true;
}
return false;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Disco.Web.Extensions.MvcExtensions.Bundles
{
internal sealed class BundleHandler : IHttpHandler
{
public Bundle RequestBundle { get; private set; }
public string BundleVirtualPath { get; private set; }
public BundleHandler(Bundle requestBundle, string bundleVirtualPath)
{
this.RequestBundle = requestBundle;
this.BundleVirtualPath = bundleVirtualPath;
}
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.Clear();
if (!string.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
context.Response.StatusCode = 304;
else
this.RequestBundle.ProcessRequest(context);
}
internal static bool RemapHandlerForBundleRequests(HttpApplication app)
{
var context = app.Context;
string bundleUrlFromContext = context.Request.AppRelativeCurrentExecutionFilePath + context.Request.PathInfo;
var bundle = BundleTable.GetBundleFor(bundleUrlFromContext);
if (bundle != null)
{
context.RemapHandler(new BundleHandler(bundle, bundleUrlFromContext));
return true;
}
return false;
}
}
}
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")]
[assembly: AssemblyFileVersion("1.2.0212.1702")]
[assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0214.1848")]