From 25aceeba6232fd4d1776ae662407b067b63d3cde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Janis=20Daniel=20Da=CC=88hne?=
 <janis.daehne2@student.uni-halle.de>
Date: Sun, 9 Jun 2019 14:29:06 +0200
Subject: [PATCH] - limited file upload size to default 5MB

---
 src/ClientServer/Config/AppConfiguration.cs | 15 ++++++++++++++
 src/ClientServer/Config/Constants.cs        |  3 +++
 src/ClientServer/Helpers/Files.cs           | 23 +++++++++++++++++++++
 src/ClientServer/Startup.cs                 | 23 +++++++++++++++++++--
 src/ClientServer/appsettings.json           |  3 ++-
 5 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/src/ClientServer/Config/AppConfiguration.cs b/src/ClientServer/Config/AppConfiguration.cs
index 7ed50c4..0638679 100644
--- a/src/ClientServer/Config/AppConfiguration.cs
+++ b/src/ClientServer/Config/AppConfiguration.cs
@@ -144,6 +144,9 @@ namespace ClientServer.Helpers
         /// </summary>
         public static List<string> DeployOriginUrls = new List<string>();
 
+
+        //5 mb?
+        public static long MaxUploadFileSizeInByte = 1024 * 1024 * 5;
         
         
         //--- methods ---
@@ -351,6 +354,18 @@ namespace ClientServer.Helpers
                     overwriteCount++;
                 }
             }
+            
+            if (string.IsNullOrWhiteSpace(ConfigurationRoot[Constants.MaxUploadFileSizeInByteKey]) == false)
+            {
+                var temp = ConfigurationRoot[Constants.MaxUploadFileSizeInByteKey];
+                long tempValue;
+                if (long.TryParse(temp, out tempValue))
+                {
+                    //keep the setting
+                    AppConfiguration.MaxUploadFileSizeInByte = tempValue;
+                    overwriteCount++;
+                }
+            }
 
             Console.WriteLine($"[INFO] {overwriteCount} app settings overwritten by appsettings.json");
         }
diff --git a/src/ClientServer/Config/Constants.cs b/src/ClientServer/Config/Constants.cs
index c5f3314..3acea41 100644
--- a/src/ClientServer/Config/Constants.cs
+++ b/src/ClientServer/Config/Constants.cs
@@ -189,6 +189,9 @@ namespace ClientServer.Helpers
         public static string DeployOriginUrlsKey = "DeployOriginUrls";
         
         
+        public static string MaxUploadFileSizeInByteKey = "MaxUploadFileSizeInByte";
+        
+        
         
         
         //--- some core constants ---
diff --git a/src/ClientServer/Helpers/Files.cs b/src/ClientServer/Helpers/Files.cs
index 080eeda..0626930 100644
--- a/src/ClientServer/Helpers/Files.cs
+++ b/src/ClientServer/Helpers/Files.cs
@@ -305,6 +305,29 @@ namespace ClientServer.Helpers
 
             return fileDict;
         }
+
+        const int k_base = 1024;
+        private static readonly string[] sizesBases = new[] {"Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
+        
+        //from http://stackoverflow.com/questions/15900485/correct-way-to-convert-size-in-bytes-to-kb-mb-gb-in-javascript
+        /// <summary>
+        /// converts the given size to a more human readable size
+        /// </summary>
+        /// <param name="sizeInBytes"></param>
+        public static string GetHumanReadableSize(long sizeInBytes, int decimalPlaces = 2)
+        {
+            if (sizeInBytes == 0) return "0 Byte";
+            
+            //e.g. 1024^x = sizeInBytes (
+            //how often can we fit in 1024? this is the size base 
+            int sizeBaseIndex = (int)Math.Floor(Math.Log(sizeInBytes, k_base));
+
+            //get the remainder e.g. 1025/1024 --> 1.0009765625
+            double value = sizeInBytes / Math.Pow(k_base, sizeBaseIndex);
+            
+
+            return $"{Math.Round(value, decimalPlaces)} {sizesBases[sizeBaseIndex]}";
+        }
         
         
     }
diff --git a/src/ClientServer/Startup.cs b/src/ClientServer/Startup.cs
index 89c618e..03bae7d 100644
--- a/src/ClientServer/Startup.cs
+++ b/src/ClientServer/Startup.cs
@@ -126,7 +126,10 @@ namespace ClientServer
             //});
 
 
-            //IDataAccessProvider
+            services.Configure<FormOptions>(o =>
+            {
+                o.MultipartBodyLengthLimit = AppConfiguration.MaxUploadFileSizeInByte;
+            });
 
             // Add framework services.
             services.AddMvc(options =>
@@ -215,7 +218,23 @@ namespace ClientServer
                     context.Response.ContentType = "application/json";
                 }
 
-                await next.Invoke();
+                try
+                {
+                    await next.Invoke();
+                }
+                catch (InvalidDataException e) //only catches this exception type
+                {
+//                    Console.WriteLine(e);
+                    context.Response.ContentType = "application/json";
+                    context.Response.StatusCode = 200;
+                    await
+                        context.Response.WriteAsync(
+                            Jc.Serialize(
+                                new BasicResponse(ResponseCode.ServerError, $"file content size (multipart body) exceeded the limit of " +
+                                                                            $"{AppConfiguration.MaxUploadFileSizeInByte} Bytes (~{Files.GetHumanReadableSize(AppConfiguration.MaxUploadFileSizeInByte)})")));
+                    return;
+                }
+               
                 // Do logging or other work that doesn't write to the Response.
             });
 
diff --git a/src/ClientServer/appsettings.json b/src/ClientServer/appsettings.json
index 53a31a7..52d6736 100644
--- a/src/ClientServer/appsettings.json
+++ b/src/ClientServer/appsettings.json
@@ -22,6 +22,7 @@
   "IsSlave": false,
   "EnsureFileUploadDirStructure": false,
   "OnlySecureFlaggedCookies": false,
-  "IsInitControllerEnabled": true
+  "IsInitControllerEnabled": true,
+  "MaxUploadFileSizeInByte": "1048576"
 }
 
-- 
GitLab