From 88a57ac79e79db66b9bcd20916dbfa2c17e8fd12 Mon Sep 17 00:00:00 2001 From: albanx Date: Sat, 21 Oct 2017 12:58:52 +0200 Subject: [PATCH] completed ASPX --- js/main.js | 1 + upload.aspx.cs | 501 +++++++++++++++++++++++-------------------------- upload.php | 149 ++++++++++++--- 3 files changed, 353 insertions(+), 298 deletions(-) diff --git a/js/main.js b/js/main.js index 28b9a8f..16f913c 100644 --- a/js/main.js +++ b/js/main.js @@ -14,6 +14,7 @@ requirejs.config({ //start our app here define(['RealUploader'], function(RealUploader) { var uploader = new RealUploader("#uploader_div", { + url: 'upload.aspx', autoStart: false, hideUploadButton: false, removeOnSuccess: true, diff --git a/upload.aspx.cs b/upload.aspx.cs index d877daf..84d098d 100644 --- a/upload.aspx.cs +++ b/upload.aspx.cs @@ -2,6 +2,7 @@ using System.Data; using System.Configuration; using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.Web; using System.Web.Security; @@ -13,249 +14,89 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; +using System.Security.Cryptography; +using System.Web.Script.Serialization; -public partial class upload : System.Web.UI.Page +public class RealUploader { - protected void Page_Load(object sender, EventArgs e) - { - /************************************************************************ - * Email configuration - * **********************************************************************/ - bool send_email = false; //enable email notification - string main_receiver = "albanx@gmail.com"; //who receive the email - string cc = ""; //other receivers in cc - string from = "from@ajaxupload.com";//who appear in the from field - /*****************************************************************************/ - - - /*********************************************************************************************************** - * RECOMMENDED CONFIGURATION HERE - * The following parameters can be changed, and is reccomended to change them from here for security reason - ***********************************************************************************************************/ - string upload_path = Server.MapPath(string.IsNullOrEmpty(Request.Params["ax-file-path"]) ? "" : Request.Params["ax-file-path"]); - string max_file_size = string.IsNullOrEmpty(Request.Params["ax-max-file-size"]) ? "10M" : Request.Params["ax-max-file-size"]; - string allow_ext_req = string.IsNullOrEmpty(Request.Params["ax-allow-ext"]) ? "" : Request.Params["ax-allow-ext"]; - string[] allow_ext = (allow_ext_req.Length > 0) ? allow_ext_req.Split('|') : new string[0]; - bool allow_delete = true; - /**********************************************************************************************************/ - - - /************************************************************************************************************ - * Settings for thumbnail generation, can be changed here or from js - ************************************************************************************************************/ - int thumb_height = string.IsNullOrEmpty(Request.Params["ax-thumbHeight"]) ? 0 : Convert.ToInt32(Request.Params["ax-thumbHeight"]); - int thumb_width = string.IsNullOrEmpty(Request.Params["ax-thumbWidth"]) ? 0 : Convert.ToInt32(Request.Params["ax-thumbWidth"]); - string thumb_post_fix = string.IsNullOrEmpty(Request.Params["ax-thumbPostfix"]) ? "_thumb" : Request.Params["ax-thumbPostfix"]; - string thumb_path = string.IsNullOrEmpty(Request.Params["ax-thumbPath"]) ? "" : Request.Params["ax-thumbPath"]; - string thumb_format = string.IsNullOrEmpty(Request.Params["ax-thumbFormat"]) ? "png" : Request.Params["ax-thumbFormat"]; - /**********************************************************************************************************/ - - /******************************************************************************************************** - * HTML5 UPLOAD PARAMETERS, NOT TO CHANGE - ********************************************************************************************************/ - string file_name = string.IsNullOrEmpty(Request.Params["ax-file-name"]) ? "" : Request.Params["ax-file-name"]; - int curr_byte = string.IsNullOrEmpty(Request.Params["ax-start-byte"]) ? 0 : Convert.ToInt32(Request.Params["ax-start-byte"]); - int full_size = string.IsNullOrEmpty(Request.Params["ax-file-size"]) ? 0 : Convert.ToInt32(Request.Params["ax-file-size"]); - string is_last = string.IsNullOrEmpty(Request.Params["ax-last-chunk"]) ? "true" : Request.Params["ax-last-chunk"]; - bool is_ajax = (!string.IsNullOrEmpty(Request.Params["ax-last-chunk"]) && !string.IsNullOrEmpty(Request.Params["ax-start-byte"])); - /**********************************************************************************************************/ - - /* - * Create upload path if do not exits - */ - if (!System.IO.File.Exists(upload_path)) - { - System.IO.Directory.CreateDirectory(upload_path); + private string fileName; + private string tempFileName; + private int fileSize = 0; + private string uploadPath; + private string tempPath; + private string[] allowExtensions = new string[0]; + private string[] denyExtensions; + private int maxFileSize = 10485760; //10M + private bool overrideFile = false; + private string allowCrossOrigin = ""; + private string clientMd5 = ""; + private bool checkMd5 = false; + private IDictionary checkSumMsg = new Dictionary(); + + HttpRequest Request = HttpContext.Current.Request; + HttpResponse Response = HttpContext.Current.Response; + + public RealUploader() + { + checkSumMsg.Add("success", "1"); + checkSumMsg.Add("message", "disabled"); + checkSumMsg.Add("serverMd5", ""); + checkSumMsg.Add("clientMd5", ""); + setUploadPath("d:/uploads"); + + if (!string.IsNullOrEmpty(Request.Params["ax-file-name"])) { + fileName = Request.Params["ax-file-name"]; } - /* - * Create thumb path if do not exits - */ - if (!System.IO.File.Exists(thumb_path) && thumb_path.Length > 0) - { - System.IO.Directory.CreateDirectory(thumb_path); - } - else - { - thumb_path = upload_path; + if (!string.IsNullOrEmpty(Request.Params["ax-temp-name"])) { + tempFileName = Request.Params["ax-temp-name"]; } - //Start upload controls - file_name = string.IsNullOrEmpty(file_name) ? Request.Files[0].FileName : file_name; - - - if( !string.IsNullOrEmpty(Request.Params["ax-check-file"]) ) - { - if(System.IO.File.Exists(upload_path + file_name)) - { - Response.Write("yes"); - } - else - { - Response.Write("no"); - } - return; - } - - if(!string.IsNullOrEmpty(Request.Params["ax-delete-file"]) && allow_delete) - { - System.IO.File.Delete(upload_path + file_name); - Response.Write("1"); - return; - } - - full_size = (full_size > 0) ? full_size : Request.Files[0].ContentLength; - //check file size - if (!checkSize(full_size, max_file_size)) - { - Response.Write(@"{""name"":""" + file_name + @""",""size"":""" + full_size.ToString() + @""",""status"":""-1"",""info"":""Max file size execced""}"); - return; + if (!string.IsNullOrEmpty(Request.Params["ax-file-size"])) { + fileSize = Convert.ToInt32(Request.Params["ax-file-size"]); } - - //check file name - string tmp_fn = file_name; - file_name = checkName(file_name); - if (file_name.Length == 0) - { - Response.Write(@"{""name"":""" + tmp_fn + @""",""size"":""" + full_size.ToString() + @""",""status"":""-1"",""info"":""File name not allowed""}"); - return; + if (!string.IsNullOrEmpty(Request.Params["ax-max-file-size"])) { + maxFileSize = Convert.ToInt32(Request.Params["ax-max-file-size"]); } - //check file ext - if (!checkExt(file_name, allow_ext)) - { - Response.Write(@"{""name"":""" + file_name + @""",""size"":""" + full_size.ToString() + @""", ""status"":""-1"", ""info"":""File extension not allowed"", ""byte"":"""+curr_byte.ToString()+@"""}"); - return; + //get the file path where to upload the file + //Hint: avoid from settings this path from JS unless in protected environment + if (!string.IsNullOrEmpty(Request.Params["ax-file-path"])) { + setUploadPath(Request.Params["ax-file-path"]); } - string full_path = ""; - if (is_ajax) - { - //calculate path and file exists only on the first chunk - full_path = (curr_byte==0)? checkFileExists(file_name, upload_path) : upload_path+file_name; - - //append data flag - FileMode flag = (curr_byte==0) ? FileMode.Create : System.IO.FileMode.Append; - FileStream fileStream = new FileStream(full_path, flag, System.IO.FileAccess.Write, System.IO.FileShare.None); - byte[] bytesInStream; - if (Request.Files.Count > 0) - { - HttpPostedFile file = Request.Files[0]; - bytesInStream = new byte[file.ContentLength]; - file.InputStream.Read(bytesInStream, 0, (int)bytesInStream.Length); - } - else - { - bytesInStream = new byte[Request.InputStream.Length]; - Request.InputStream.Read(bytesInStream, 0, (int)bytesInStream.Length); - } - - fileStream.Write(bytesInStream, 0, bytesInStream.Length); - fileStream.Close(); - if (!is_last.Equals("true")) - Response.Write(@"{""name"":""" + System.IO.Path.GetFileName(full_path) + @""",""size"":""" + full_size.ToString() + @""",""status"":""1"",""info"":""File chunk uploaded"", ""byte"":"""+curr_byte.ToString()+@"""} "); - } - else - { - is_last = "true"; - full_path = checkFileExists(file_name, upload_path); - try - { - HttpPostedFile file = Request.Files[0]; - file.SaveAs(full_path); - } - catch (Exception ex) - { - Response.Write(@"{""name"":""" + System.IO.Path.GetFileName(full_path) + @""",""size"":""" + full_size.ToString() + @""",""status"":""-1"",""info"":""Generi error:"+ex.Message+@"""}"); - return; - } + if (!string.IsNullOrEmpty(Request.Params["ax-allow-ext"])) { + string allowExtString = Request.Params["ax-allow-ext"]; + allowExtensions = (allowExtString.Length > 0) ? allowExtString.Split('|') : new string[0]; } - if (is_last.Equals("true")) - { - createThumb(full_path, thumb_path, thumb_post_fix, thumb_width, thumb_height, thumb_format); - Response.Write(@"{""name"":""" + System.IO.Path.GetFileName(full_path) + @""",""size"":""" + full_size.ToString() + @""",""status"":""1"",""info"":""File uploaded""}"); + if (!string.IsNullOrEmpty(Request.Params["ax-file-md5"])) { + clientMd5 = Request.Params["ax-file-md5"]; } + + overrideFile = !string.IsNullOrEmpty(Request.Params["ax-override"]); + checkMd5 = !string.IsNullOrEmpty(Request.Params["ax-md5checksum"]); + tempPath = System.IO.Path.GetTempPath(); + denyExtensions = new string[] {"php", "php3", "php4", "php5", "phtml", "exe", "pl", "cgi", "html", "htm", "js", "asp", "aspx", "bat", "sh", "cmd" }; } - public string createThumb(string filepath, string thumbPath, string postfix, int maxw, int maxh, string format) + /** + * Set and create the upload path + * + * @param $uploadPath + */ + public void setUploadPath(string uploadPath) { - if (maxw <= 0 && maxh <= 0) - { - return "No valid width or height given"; - } - - string[] web_formats = new string[] {"jpg", "png", "jpeg", "gif"}; - - - //get file extension to check if can do the preview - string file_ext = Path.GetExtension(filepath).Replace(".", ""); - string file_name = Path.GetFileNameWithoutExtension(filepath); - - //if format is not set then set thumbnail format as file extension - if (format.Length == 0) format = file_ext; - - - if (Array.IndexOf(web_formats, format.ToLower())<0) - { - return "No valid supported image file"; - } - - //and create thumbnail name - string thumb_name = file_name + postfix + "." + format; - - - //if I have not set any path for thumbnail generation then save same as file path - if(thumbPath.Length==0) - { - thumbPath=Path.GetDirectoryName(filepath); - } - - //add final slash to thumb path - if(!thumbPath[thumbPath.Length-1].Equals(@"\") || !thumbPath[thumbPath.Length-1].Equals("/")) - { - thumbPath+=Path.DirectorySeparatorChar; + this.uploadPath = uploadPath; + try { + if(!Directory.Exists(uploadPath)) { + DirectoryInfo di = Directory.CreateDirectory(uploadPath); + } + } catch(Exception e) { + Console.WriteLine("The process failed: {0}", e.ToString()); } - //create the preview propotionally respecting maxw and maxh - System.Drawing.Image img = System.Drawing.Image.FromFile(filepath); - - double ratioX = (double)maxw/img.Width; - double ratioY = (double)maxh/img.Height; - double ratio = (double)Math.Min(ratioX, ratioY); - ratio = (ratio==0)? (double) Math.Max(ratioX,ratioY):ratio; - - int newW = (int)(img.Width*ratio); - int newH = (int)(img.Height*ratio); - - /*Response.Write(img.Width ); - Response.Write(newW ); - Response.Write(newH );*/ - Bitmap newImg = new Bitmap(newW, newH); - Graphics graphic = Graphics.FromImage(newImg); - graphic.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphic.SmoothingMode = SmoothingMode.HighQuality; - graphic.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphic.CompositingQuality = CompositingQuality.HighQuality; - graphic.DrawImage(img, 0, 0, newW, newH); - - //System.Drawing.Image newImg = img.GetThumbnailImage(newW, newH, null, new System.IntPtr()); - switch(format) - { - case "png": - newImg.Save(thumbPath+thumb_name, System.Drawing.Imaging.ImageFormat.Png); - break; - case "gif": - newImg.Save(thumbPath+thumb_name, System.Drawing.Imaging.ImageFormat.Gif); - break; - default: - newImg.Save(thumbPath+thumb_name, System.Drawing.Imaging.ImageFormat.Jpeg); - break; - } - img.Dispose(); - newImg.Dispose(); - return "ok"; } /** @@ -264,66 +105,88 @@ public string createThumb(string filepath, string thumbPath, string postfix, int * @param unknown_type $size * @param unknown_type $max_file_size */ - public bool checkSize(int file_size, string max_file_size) + public bool checkSize() { - string mult = max_file_size.Substring(Math.Max(0, max_file_size.Length - 1)); - Int64 msize = Convert.ToInt32(max_file_size.Replace(mult, "")); - Int64 max_size; - - switch (mult) - { - case "T": - max_size = msize * 1024*1024*1024*1024;break; - case "G": - max_size = msize * 1024*1024*1024;break; - case "M": - max_size = msize * 1024*1024;break; - case "K": - max_size = msize * 1024;break; - default: - max_size = 4 * 1024 * 1024;break; - } - - if (file_size > max_size) + if (fileSize > maxFileSize) { return false; } return true; } - /** - * Check if filename is allowed - */ - public string checkName(string filename) + public bool checkName() { string[] windowsReserved = new string[] { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" }; string[] badWinChars = new string[] { "<", ">", ":", @"\", "/", "|", "?", "*" }; for (int i = 0; i < badWinChars.Length; i++) { - filename.Replace(badWinChars[i], ""); + fileName.Replace(badWinChars[i], ""); } //check if legal windows file name - if (Array.IndexOf(windowsReserved, filename) >= 0) + if (Array.IndexOf(windowsReserved, fileName) >= 0) + { + return false; + } + return true; + } + + public void checkFileExists() + { + string fileExt = System.IO.Path.GetExtension(fileName).Replace(".", ""); + string fileBase = System.IO.Path.GetFileNameWithoutExtension(fileName); + string fullPath = uploadPath + fileName; + + //avoid file override, check if file exists and generate another name + //to override file with same name just disable this while + int c = 0; + while (System.IO.File.Exists(fullPath)) { - return ""; + c++; + fileName = fileBase + "(" + c.ToString() + ")." + fileExt; + fullPath = uploadPath + fileName; } - return filename; } - public bool checkExt(string filename, string[] allow_ext) + public void finish() + { + + } + + public void doFileExists() + { + string msg = System.IO.File.Exists(uploadPath + fileName) ? "yes" : "no"; + message(1, msg); + } + + public void sendHeaders() { - string file_ext = System.IO.Path.GetExtension(filename).Replace(".", ""); - file_ext = file_ext.ToLower(); + Response.AppendHeader("Cache-Control", "no-cache, must-revalidate"); // HTTP/1.1 + Response.AppendHeader("Expires", "Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past + Response.AppendHeader("X-Content-Type-Options", "nosniff"); + Response.AppendHeader("Content-Type", "application/json"); + + //if we need to upload files across domains then enable allow origin variable with the domain value + if (allowCrossOrigin.Length > 0) { + Response.AppendHeader("Access-Control-Allow-Origin", allowCrossOrigin); + Response.AppendHeader("Access-Control-Allow-Credentials", "false"); + Response.AppendHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, PATCH, DELETE"); + Response.AppendHeader("Access-Control-Allow-Headers", "Content-Type, Content-Range, Content-Disposition"); + } + } - string[] deny_ext = new string[] {"php", "php3", "php4", "php5", "phtml", "exe", "pl", "cgi", "html", "htm", "js", "asp", "aspx", "bat", "sh", "cmd" }; - if (Array.IndexOf(deny_ext, file_ext) >= 0) + public bool checkExt() + { + string fileExt = System.IO.Path.GetExtension(fileName).Replace(".", ""); + fileExt = fileExt.ToLower(); + + if (Array.IndexOf(denyExtensions, fileExt) >= 0) { return false; } - if (Array.IndexOf(allow_ext, file_ext) < 0 && allow_ext.Length > 0) + if (Array.IndexOf(allowExtensions, fileExt) < 0 && allowExtensions.Length > 0) { return false; } @@ -331,21 +194,121 @@ public bool checkExt(string filename, string[] allow_ext) return true; } - public string checkFileExists(string filename, string upload_path) + public bool checkFile() { - string file_ext = System.IO.Path.GetExtension(filename).Replace(".", ""); - string file_base = System.IO.Path.GetFileNameWithoutExtension(filename); - string full_path = upload_path + filename; + if(!checkExt()) { + message(-1, "File extension is not allowed"); + } - //avoid file override, check if file exists and generate another name - //to override file with same name just disable this while - int c = 0; - while (System.IO.File.Exists(full_path)) + if (!checkName()) { + message(-1, "File name is not allowed"); + } + + if (!checkSize()) { + message(-1, "File size not allowed: " + maxFileSize); + } + + return true; + } + + public void uploadFile() + { + if(checkFile()) { + uploadAjax(); + } + } + + /** + * Main Upload method. Handle file uploads and checks + */ + private void uploadAjax() + { + int currByte = string.IsNullOrEmpty(Request.Params["ax-start-byte"]) ? 0 : Convert.ToInt32(Request.Params["ax-start-byte"]); + HttpPostedFile fileChunk = Request.Files[0]; + byte[] bytesInStream = new byte[fileChunk.ContentLength]; + fileChunk.InputStream.Read(bytesInStream, 0, (int)bytesInStream.Length); + + if (currByte == 0) { + tempFileName = Path.GetFileName(Path.GetTempFileName()); + } + + string tempFile = tempPath + Path.DirectorySeparatorChar + tempFileName; + string finalFile = uploadPath + Path.DirectorySeparatorChar + fileName; + try { - c++; - filename = file_base + "(" + c.ToString() + ")." + file_ext; - full_path = upload_path + filename; + FileStream fileStream = new FileStream(tempFile, FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.None); + fileStream.Write(bytesInStream, 0, bytesInStream.Length); + fileStream.Close(); + } catch(Exception e) { + message(-1, "Cannot write on file, please check permissions: " + tempFile); } - return full_path; + + long currentFileSize = new FileInfo(tempFile).Length; + + if (fileSize > currentFileSize) { + message(1, "Chunk uploaded"); + } else { + try { + checkFileExists(); + File.Move(tempFile, finalFile); + verifyMd5(finalFile); + finish(); + message(1, "File uploaded"); + } catch(IOException e) { + message(-1, "File move error: " + finalFile); + } + } + } + + private void verifyMd5(string filePath) + { + if (checkMd5 && clientMd5.Length > 0) { + var stream = File.OpenRead(filePath); + MD5 md5Hash = MD5.Create(); + string serverMd5 = BitConverter.ToString(md5Hash.ComputeHash(stream)).Replace("-","‌​").ToLower(); + if (serverMd5.Equals(clientMd5)) { + checkSumMsg.Add("success", "1"); + checkSumMsg.Add("message", "MD5 check correctly"); + checkSumMsg.Add("serverMd5", serverMd5); + checkSumMsg.Add("clientMd5", clientMd5); + } else { + checkSumMsg.Add("success", "-1"); + checkSumMsg.Add("message", "MD5 check failed"); + checkSumMsg.Add("serverMd5", serverMd5); + checkSumMsg.Add("clientMd5", clientMd5); + } + } + } + + private void message(int status, string msg) + { + sendHeaders(); + IDictionary response = new Dictionary(); + string checkSumString = new JavaScriptSerializer().Serialize(checkSumMsg); + + response.Add("name", fileName); + response.Add("temp_name", tempFileName); + response.Add("size", fileSize.ToString()); + response.Add("status", status.ToString()); + response.Add("checkSum", checkSumString); + response.Add("info", msg); + response.Add("path", uploadPath); + string responseJson = new JavaScriptSerializer().Serialize(response); + + Response.Write(responseJson); + } +} + + +public partial class upload : System.Web.UI.Page +{ + protected void Page_Load(object sender, EventArgs e) + { + RealUploader uploader = new RealUploader(); + if (!string.IsNullOrEmpty(Request.Params["ax-check-file"])) { + uploader.doFileExists(); + } else { + uploader.uploadFile(); + } } } \ No newline at end of file diff --git a/upload.php b/upload.php index e0e12ed..0b355ba 100644 --- a/upload.php +++ b/upload.php @@ -1,4 +1,5 @@ true, 'message' => 'disabled']; - public $uploadErrors = [UPLOAD_ERR_OK => "No errors.", UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini", UPLOAD_ERR_FORM_SIZE => "Larger than form maxFileSize.", UPLOAD_ERR_PARTIAL => "Partial upload.", UPLOAD_ERR_NO_FILE => "No file.", UPLOAD_ERR_NO_TMP_DIR => "No temporary directory.", UPLOAD_ERR_CANT_WRITE => "Can't write to disk.", UPLOAD_ERR_EXTENSION => "File upload stopped by extension."]; + public $uploadErrors = [ + UPLOAD_ERR_OK => "No errors.", + UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini", + UPLOAD_ERR_FORM_SIZE => "Larger than form maxFileSize.", + UPLOAD_ERR_PARTIAL => "Partial upload.", + UPLOAD_ERR_NO_FILE => "No file.", + UPLOAD_ERR_NO_TMP_DIR => "No temporary directory.", + UPLOAD_ERR_CANT_WRITE => "Can't write to disk.", + UPLOAD_ERR_EXTENSION => "File upload stopped by extension." + ]; /** * RealUploader constructor. * Get the input information from GET/POST and filters them */ - public function __construct() { + public function __construct() + { //make a sanitize to the file names to avoid any path scale ../../ if (isset($_REQUEST['ax-file-name'])) { $this->fileName = basename($_REQUEST['ax-file-name']); @@ -89,7 +100,25 @@ public function __construct() { $this->tempPath = ($iniTmpDir ? $iniTmpDir : sys_get_temp_dir()) . '/'; //set deny extensions by default - $this->denyExtensions = ['php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'pl', 'cgi', 'html', 'htm', 'js', 'asp', 'aspx', 'bat', 'sh', 'cmd', 'jsp']; + $this->denyExtensions = [ + 'php', + 'php3', + 'php4', + 'php5', + 'phtml', + 'exe', + 'pl', + 'cgi', + 'html', + 'htm', + 'js', + 'asp', + 'aspx', + 'bat', + 'sh', + 'cmd', + 'jsp' + ]; } /** @@ -97,7 +126,8 @@ public function __construct() { * * @param int $maxFileSize */ - public function setMaxFileSize($maxFileSize = 10000000) { + public function setMaxFileSize($maxFileSize = 10000000) + { $this->maxFileSize = $maxFileSize; } @@ -107,7 +137,8 @@ public function setMaxFileSize($maxFileSize = 10000000) { * * @param array $allow_ext */ - public function setAllowExt($allow_ext = []) { + public function setAllowExt($allow_ext = []) + { $this->allowExtensions = $allow_ext; } @@ -116,7 +147,8 @@ public function setAllowExt($allow_ext = []) { * * @param $uploadPath */ - public function setUploadPath($uploadPath) { + public function setUploadPath($uploadPath) + { $this->uploadPath = rtrim($uploadPath, '\\/'); $this->makeDir($this->uploadPath); } @@ -126,7 +158,8 @@ public function setUploadPath($uploadPath) { * * @param $bool */ - public function setOverride($bool) { + public function setOverride($bool) + { $this->overrideFile = $bool; } @@ -135,7 +168,8 @@ public function setOverride($bool) { * * @param $dir */ - private function makeDir($dir) { + private function makeDir($dir) + { // Create thumb path if do not exits if (!file_exists($dir) && !empty($dir)) { $done = @mkdir($dir, 0777, true); @@ -152,7 +186,8 @@ private function makeDir($dir) { * * @return bool =false if image is not supported, true if is ok */ - private function createThumbGD($quality = 75) { + private function createThumbGD($quality = 75) + { $maxHeight = isset($_REQUEST['ax-thumbHeight']) ? $_REQUEST['ax-thumbHeight'] : 0; $maxWidth = isset($_REQUEST['ax-thumbWidth']) ? $_REQUEST['ax-thumbWidth'] : 0; $postfix = isset($_REQUEST['ax-thumbPostfix']) ? $_REQUEST['ax-thumbPostfix'] : '_thumb'; @@ -222,7 +257,8 @@ private function createThumbGD($quality = 75) { * Check the maximum allowed file size * @return bool true if file size is in the current set limit */ - private function checkSize() { + private function checkSize() + { if (!empty($maxFileSize) && $this->fileSize > $this->maxFileSize) { return false; } @@ -234,8 +270,32 @@ private function checkSize() { * Check if file name is allowed and remove illegal windows chars * @return bool */ - private function checkName() { - $windowsReserved = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9']; + private function checkName() + { + $windowsReserved = [ + 'CON', + 'PRN', + 'AUX', + 'NUL', + 'COM1', + 'COM2', + 'COM3', + 'COM4', + 'COM5', + 'COM6', + 'COM7', + 'COM8', + 'COM9', + 'LPT1', + 'LPT2', + 'LPT3', + 'LPT4', + 'LPT5', + 'LPT6', + 'LPT7', + 'LPT8', + 'LPT9' + ]; $badWinChars = array_merge(array_map('chr', range(0, 31)), ["<", ">", ":", '"', "/", "\\", "|", "?", "*"]); $this->fileName = str_replace($badWinChars, '', $this->fileName); @@ -250,7 +310,8 @@ private function checkName() { /** * Check if a file exits or not and calculates a new name for not overriding other files */ - private function checkFileExists() { + private function checkFileExists() + { if (!$this->overrideFile) { //set a random stop to allow the file system to read any new file on parallel upload usleep(rand(100, 900)); @@ -280,15 +341,26 @@ private function checkFileExists() { * * @param $filePath final uploaded file */ - private function verifyMd5($filePath) { + private function verifyMd5($filePath) + { if ($this->checkMd5 && $this->clientMd5) { usleep(rand(100, 900)); $serverMd5 = md5_file($filePath); if ($serverMd5 !== $this->clientMd5) { - $this->checkSumMsg = array('success' => false, 'message' => 'MD5 check sum failed. Client MD5 is different from server MD5. - File maybe have been corrupted during upload.', 'serverMd5' => $serverMd5, 'clientMd5' => $this->clientMd5); + $this->checkSumMsg = array( + 'success' => false, + 'message' => 'MD5 check sum failed. Client MD5 is different from server MD5. + File maybe have been corrupted during upload.', + 'serverMd5' => $serverMd5, + 'clientMd5' => $this->clientMd5 + ); } else { - $this->checkSumMsg = array('success' => true, 'message' => 'MD5 check correctly.', 'serverMd5' => $serverMd5, 'clientMd5' => $this->clientMd5); + $this->checkSumMsg = array( + 'success' => true, + 'message' => 'MD5 check correctly.', + 'serverMd5' => $serverMd5, + 'clientMd5' => $this->clientMd5 + ); } } } @@ -297,7 +369,8 @@ private function verifyMd5($filePath) { * Simple check if the current file exists in the server * @return bool true if file exists, false otherwise */ - public function doFileExists() { + public function doFileExists() + { $msg = file_exists($this->uploadPath . '/' . $this->fileName) ? 'yes' : 'no'; $this->message(1, $msg); } @@ -307,7 +380,8 @@ public function doFileExists() { * @safe check 1: base name will not allow ../../ to scale in system a path * @return bool true if the file is deleted, false otherwise */ - public function deleteFile() { + public function deleteFile() + { $msg = @unlink($this->uploadPath . '/' . $this->fileName) ? 'yes' : 'no'; $this->message(1, $msg ? 'File deleted' : 'Cannot delete file'); } @@ -316,7 +390,8 @@ public function deleteFile() { * Check if file type is allowed for upload * @return bool */ - private function checkExt() { + private function checkExt() + { //get the file extension $extension = strtolower(pathinfo($this->fileName, PATHINFO_EXTENSION)); @@ -336,7 +411,8 @@ private function checkExt() { * Makes the check on the file, extension, size, name * @return bool true if file is correct, die() if there are errors */ - private function checkFile() { + private function checkFile() + { //check uploads error if (isset($_FILES['ax_file_input'])) { if ($_FILES['ax_file_input']['error'] !== UPLOAD_ERR_OK) { @@ -364,10 +440,10 @@ private function checkFile() { /** * Main Upload method. Handle file uploads and checks */ - private function uploadAjax() { + private function uploadAjax() + { $currByte = isset($_REQUEST['ax-start-byte']) ? $_REQUEST['ax-start-byte'] : 0; $fileChunk = file_get_contents($_FILES['ax_file_input']['tmp_name']); - $tempFile = $this->tempPath . '/' . $this->tempFileName; //start of the file upload, first chunk if ($currByte == 0) { @@ -375,6 +451,8 @@ private function uploadAjax() { $this->tempFileName = basename($tempFile); } + $tempFile = $this->tempPath . '/' . $this->tempFileName; + // some rare times (on very very fast connection), file_put_contents will be unable to write on the file, // so we try until it writes for a max of 5 times $try = 5; @@ -409,7 +487,8 @@ private function uploadAjax() { $extra_info = $this->finish(); $this->message(1, 'File uploaded', $extra_info); } else { - $this->message(-1, 'File move error: ' . $tempFile . ' to ' . $this->uploadPath . '/' . $this->fileName); + $this->message(-1, + 'File move error: ' . $tempFile . ' to ' . $this->uploadPath . '/' . $this->fileName); } } } @@ -418,7 +497,8 @@ private function uploadAjax() { * Public function file upload, checks every chunk of the file during upload for avoiding * js hackers */ - public function uploadFile() { + public function uploadFile() + { if ($this->checkFile()) { $this->uploadAjax(); } @@ -429,7 +509,8 @@ public function uploadFile() { * Any post file action should be inserted here, DB, file move or others * @return string eventually errors return on user functions */ - public function finish() { + public function finish() + { ob_start(); //create a thumb if data is set @@ -442,7 +523,8 @@ public function finish() { /** * Simple headers for JSON validation and others */ - public function sendHeaders() { + public function sendHeaders() + { header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past header('X-Content-Type-Options: nosniff'); @@ -465,9 +547,18 @@ public function sendHeaders() { * @param String $msg error message or success message * @param string $extraInfo more info returned by the user functions */ - private function message($status, $msg, $extraInfo = '') { + private function message($status, $msg, $extraInfo = '') + { $this->sendHeaders(); - echo json_encode(['name' => $this->fileName, 'temp_name' => $this->tempFileName, 'size' => $this->fileSize, 'status' => $status, 'info' => $msg, 'more' => $extraInfo, 'checkSum' => $this->checkSumMsg]); + echo json_encode([ + 'name' => $this->fileName, + 'temp_name' => $this->tempFileName, + 'size' => $this->fileSize, + 'status' => $status, + 'info' => $msg, + 'more' => $extraInfo, + 'checkSum' => $this->checkSumMsg + ]); die(); } }