|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Web;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using Web.Core;
|
|
|
|
|
|
|
|
|
|
namespace Web.IISUploadHandler {
|
|
|
|
|
class UploadHandler : IHttpHandler {
|
|
|
|
|
|
|
|
|
|
public bool IsReusable {
|
|
|
|
|
get {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ProcessRequest(HttpContext httpcontext) {
|
|
|
|
|
if(httpcontext.Request.Path.ToLower() == "/upload/") {
|
|
|
|
|
this.ProcessUpload(httpcontext);
|
|
|
|
|
} else if(httpcontext.Request.Path.ToLower().StartsWith("/data/")) {
|
|
|
|
|
this.ProcessRetrieve(httpcontext);
|
|
|
|
|
} else {
|
|
|
|
|
throw new HttpException(403, "wrong url");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string getFilePath(string md5, string extension) {
|
|
|
|
|
foreach(char chr in (md5 + extension)) {
|
|
|
|
|
if(!Char.IsLetterOrDigit(chr)) throw new HttpException(403, "wrong md5 or extension");
|
|
|
|
|
}
|
|
|
|
|
return Config.instance.storageDir + md5.PHPSubstring(0, 2) + Path.DirectorySeparatorChar + md5.PHPSubstring(2, 2) + Path.DirectorySeparatorChar + md5.PHPSubstring(4) + "." + extension;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void CreateDirectoryIfNotExists(DirectoryInfo directoryInfo) {
|
|
|
|
|
if(!directoryInfo.Exists) {
|
|
|
|
|
CreateDirectoryIfNotExists(directoryInfo.Parent);
|
|
|
|
|
directoryInfo.Create();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ProcessUpload(HttpContext context) {
|
|
|
|
|
byte[] data = new byte[context.Request.InputStream.Length];
|
|
|
|
|
if(context.Request.InputStream.Read(data, 0, (int)context.Request.InputStream.Length) != context.Request.InputStream.Length) {
|
|
|
|
|
throw new FLocalException("File is not uploaded correctly");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string file_md5 = Util.md5(context.Request.InputStream);
|
|
|
|
|
|
|
|
|
|
string md5 = Util.md5(file_md5 + " " + Config.instance.salt);
|
|
|
|
|
if(md5 != context.Request.QueryString["signature"]) {
|
|
|
|
|
throw new HttpException(403, "signature mismatch");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string filePath = getFilePath(file_md5, context.Request.QueryString["extension"]);
|
|
|
|
|
CreateDirectoryIfNotExists((new FileInfo(filePath)).Directory);
|
|
|
|
|
using(FileStream stream = new FileStream(filePath, FileMode.CreateNew)) {
|
|
|
|
|
stream.Write(data, 0, data.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context.Response.Write("OK");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ProcessRetrieve(HttpContext context) {
|
|
|
|
|
string[] requestParts = context.Request.Path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
if(requestParts.Length != 2) throw new HttpException(403, "wrong url");
|
|
|
|
|
|
|
|
|
|
string[] fileParts = requestParts[1].Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
if(fileParts.Length != 2) throw new HttpException(403, "wrong url");
|
|
|
|
|
|
|
|
|
|
string mime = Util.getMimeByExtension(fileParts[1]);
|
|
|
|
|
if(mime == null) throw new FLocalException("unknown extension '" + fileParts[1] + "'");
|
|
|
|
|
context.Response.ContentType = mime;
|
|
|
|
|
|
|
|
|
|
context.Response.Cache.SetExpires(DateTime.Now.AddDays(10));
|
|
|
|
|
context.Response.Cache.SetLastModified(DateTime.Now.AddYears(-1));
|
|
|
|
|
context.Response.Cache.SetCacheability(HttpCacheability.Public);
|
|
|
|
|
|
|
|
|
|
context.Response.TransmitFile(getFilePath(fileParts[0], fileParts[1]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|