commit a50893a9b3d182da6b06267b7af5e55bed49854a Author: MVS-deHB Date: Thu Sep 24 12:38:47 2026 +0000 Dateien nach "/" hochladen diff --git a/Default.aspx b/Default.aspx new file mode 100644 index 0000000..a921975 --- /dev/null +++ b/Default.aspx @@ -0,0 +1,963 @@ +<%@ Page + Language="C#" + ResponseEncoding="utf-8" + ContentType="text/html; charset=utf-8" + AutoEventWireup="true" + CodeFile="Default.aspx.cs" + Inherits="FileSharePortal.Default" +%> + + + + + + + + + + + + FileShare + + + + + + + + + +
+ + + + +
+ +
+ + +
+ + + +
+ + +
+ +

+ FileShare +

+ +

+ Interne Dokumentenablage +

+ +
+ + +
+ + Angemeldet als: + + + <%= Server.HtmlEncode(CurrentUser) %> + + +
+ + +
+ +
+ + + + +
+ + + <%= BreadcrumbHtml %> + + +
+ +

+ <%= string.IsNullOrEmpty(CurrentPath) + ? "Willkommen" + : "Dateien und Ordner" %> +

+ + +

+ + <%= string.IsNullOrEmpty(CurrentPath) + ? "Es werden nur Bereiche angezeigt, auf die Ihr Benutzerkonto Zugriff hat." + : "Es werden nur zugängliche Ordner und Dateien angezeigt." %> + +

+ +
+ + + <%= ContentHtml %> + + +
+ + + + +
+ + Interne Dokumentenablage + +
+ + +
+ + + + \ No newline at end of file diff --git a/Default.aspx.cs b/Default.aspx.cs new file mode 100644 index 0000000..c7c654d --- /dev/null +++ b/Default.aspx.cs @@ -0,0 +1,1271 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Security; +using System.Security.Principal; +using System.Text; +using System.Web; +using System.Web.UI; + +namespace FileSharePortal +{ + public partial class Default : Page + { + private const string ShareRoot = + @"\\LAN-DC1\Fileshare"; + + + private static readonly Dictionary RootFolders = + new Dictionary( + StringComparer.OrdinalIgnoreCase) + { + { + "Free Trial Documents", + "Dokumente rund um Free Trials" + }, + + { + "Sales Ordner", + "Dokumente für den Vertrieb" + }, + + { + "Technical User Folder", + "Technische Dokumente und Unterlagen" + } + }; + + + public string CurrentUser + { + get; + private set; + } + + + public string CurrentPath + { + get; + private set; + } + + + public string BreadcrumbHtml + { + get; + private set; + } + + + public string ContentHtml + { + get; + private set; + } + + + protected void Page_Load( + object sender, + EventArgs e) + { + Response.Cache.SetCacheability( + HttpCacheability.NoCache); + + Response.Cache.SetNoStore(); + + + CurrentUser = + WindowsIdentity.GetCurrent().Name; + + + string relativePath = + Request.QueryString["path"] ?? ""; + + + try + { + string physicalPath = + GetSafePhysicalPath( + relativePath); + + + CurrentPath = + relativePath; + + + BreadcrumbHtml = + BuildBreadcrumb( + relativePath); + + + if ( + string.IsNullOrEmpty( + relativePath)) + { + ContentHtml = + BuildRootFolderList(); + } + else + { + ContentHtml = + BuildDirectoryContents( + physicalPath, + relativePath); + } + } + catch (UnauthorizedAccessException) + { + ContentHtml = + BuildError( + "Zugriff verweigert", + "Sie haben keine Berechtigung auf diesen Bereich zuzugreifen."); + } + catch (DirectoryNotFoundException) + { + ContentHtml = + BuildError( + "Ordner nicht gefunden", + "Der angeforderte Ordner existiert nicht."); + } + catch (SecurityException) + { + ContentHtml = + BuildError( + "Ungültiger Pfad", + "Der angeforderte Pfad ist nicht zulässig."); + } + catch + { + ContentHtml = + BuildError( + "Fehler", + "Der angeforderte Bereich konnte nicht geladen werden."); + } + } + + + /* + * ======================================================== + * ORDNER-ICON + * ======================================================== + */ + + private string FolderIconSvg() + { + return @" + + + + + "; + } + + + /* + * ======================================================== + * DATEI-ICON + * ======================================================== + */ + + private string FileIconSvg( + string extension) + { + string label = + "FILE"; + + string fill = + "#6b7280"; + + switch (extension) + { + case ".pdf": + + label = "PDF"; + fill = "#dc2626"; + + break; + + + case ".doc": + case ".docx": + + label = "WORD"; + fill = "#2563eb"; + + break; + + + case ".xls": + case ".xlsx": + case ".xlsm": + + label = "XLS"; + fill = "#16a34a"; + + break; + + + case ".ppt": + case ".pptx": + + label = "PPT"; + fill = "#ea580c"; + + break; + + + case ".zip": + case ".7z": + case ".rar": + case ".tar": + case ".gz": + + label = "ZIP"; + fill = "#7c3aed"; + + break; + + + case ".jpg": + case ".jpeg": + case ".png": + case ".gif": + case ".webp": + case ".bmp": + + label = "IMG"; + fill = "#0891b2"; + + break; + + + case ".mp3": + case ".wav": + case ".ogg": + + label = "AUDIO"; + fill = "#c026d3"; + + break; + + + case ".mp4": + case ".webm": + case ".ogv": + + label = "VIDEO"; + fill = "#9333ea"; + + break; + + + case ".txt": + case ".log": + case ".csv": + case ".json": + case ".xml": + + label = "TXT"; + fill = "#64748b"; + + break; + + + case ".exe": + case ".msi": + + label = "APP"; + fill = "#475569"; + + break; + + + default: + + label = "FILE"; + fill = "#6b7280"; + + break; + } + + + return + "" + + + "" + + + "" + + + "" + + + "" + + + HttpUtility.HtmlEncode(label) + + + "" + + + ""; + } + + + /* + * ======================================================== + * STARTSEITE + * ======================================================== + */ + + private string BuildRootFolderList() + { + var html = + new StringBuilder(); + + + html.Append( + "
" + ); + + + int visibleFolders = 0; + + + foreach ( + KeyValuePair folder + in RootFolders) + { + string folderName = + folder.Key; + + + string path = + Path.Combine( + ShareRoot, + folderName); + + + if (!Directory.Exists(path)) + continue; + + + if (!CanBrowseDirectory(path)) + continue; + + + visibleFolders++; + + + string encodedPath = + HttpUtility.UrlEncode( + folderName); + + + html.Append( + "" + ); + + + html.Append( + "
" + ); + + + html.Append( + FolderIconSvg() + ); + + + html.Append( + "
" + ); + + + html.Append( + "
" + ); + + + html.Append( + "
" + + HttpUtility.HtmlEncode( + folderName) + + "
" + ); + + + html.Append( + "
" + + HttpUtility.HtmlEncode( + folder.Value) + + "
" + ); + + + html.Append( + "
" + ); + + + html.Append( + "
→
" + ); + + + html.Append( + "
" + ); + } + + + html.Append( + "
" + ); + + + if (visibleFolders == 0) + { + return BuildError( + "Keine Bereiche verfügbar", + "Für Ihr Benutzerkonto wurden keine zugänglichen Bereiche gefunden."); + } + + + return html.ToString(); + } + + + /* + * ======================================================== + * VERZEICHNISINHALT + * ======================================================== + */ + + private string BuildDirectoryContents( + string physicalPath, + string relativePath) + { + var html = + new StringBuilder(); + + + /* + * ZURÜCK + */ + html.Append( + "
" + ); + + + string parentPath = + GetParentRelativePath( + relativePath); + + + if (parentPath != null) + { + if ( + string.IsNullOrEmpty( + parentPath)) + { + html.Append( + "" + + "← Startseite" + + "" + ); + } + else + { + html.Append( + "" + + "← Zurück" + + "" + ); + } + } + + + html.Append( + "
" + ); + + + var itemHtml = + new StringBuilder(); + + + /* + * ==================================================== + * UNTERORDNER + * ==================================================== + */ + + string[] directories = + Directory.GetDirectories( + physicalPath); + + + foreach ( + string directory + in directories) + { + if (!CanBrowseDirectory(directory)) + continue; + + + string directoryName = + Path.GetFileName(directory); + + + string childRelativePath = + CombineRelativePath( + relativePath, + directoryName); + + + itemHtml.Append( + "" + ); + + + itemHtml.Append( + "
" + ); + + + itemHtml.Append( + FolderIconSvg() + ); + + + itemHtml.Append( + "
" + ); + + + itemHtml.Append( + "
" + + HttpUtility.HtmlEncode( + directoryName) + + "
" + ); + + + itemHtml.Append( + "
→
" + ); + + + itemHtml.Append( + "
" + ); + } + + + /* + * ==================================================== + * DATEIEN + * ==================================================== + */ + + string[] files = + Directory.GetFiles( + physicalPath); + + + foreach ( + string file + in files) + { + /* + * Eine Datei muss tatsächlich gelesen werden + * können. So erscheinen keine Dateien, auf die + * der Benutzer keine Leseberechtigung hat. + */ + if (!CanReadFile(file)) + continue; + + + string fileName = + Path.GetFileName(file); + + + string extension = + Path.GetExtension(file) + .ToLowerInvariant(); + + + FileInfo info = + new FileInfo(file); + + + string fileRelativePath = + CombineRelativePath( + relativePath, + fileName); + + + string viewUrl = + "View.aspx?path=" + + HttpUtility.UrlEncode( + fileRelativePath); + + + string downloadUrl = + "Download.aspx?path=" + + HttpUtility.UrlEncode( + fileRelativePath); + + + /* + * Dateizeile + */ + itemHtml.Append( + "" + ); + } + + + if (itemHtml.Length == 0) + { + html.Append( + "
" + + "Dieser Ordner enthält keine für Sie sichtbaren Dateien oder Ordner." + + "
" + ); + + return html.ToString(); + } + + + html.Append( + "
" + ); + + + html.Append( + itemHtml.ToString() + ); + + + html.Append( + "
" + ); + + + return html.ToString(); + } + + + /* + * ======================================================== + * DATEILESEBERECHTIGUNG + * ======================================================== + */ + + private bool CanReadFile( + string path) + { + try + { + using ( + FileStream stream = + new FileStream( + path, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite | + FileShare.Delete)) + { + } + + + return true; + } + catch + { + return false; + } + } + + + /* + * ======================================================== + * DATEITYP BESCHREIBUNG + * ======================================================== + */ + + private string GetFileTypeDescription( + string extension) + { + switch (extension) + { + case ".pdf": + return "PDF-Dokument"; + + + case ".doc": + case ".docx": + return "Word-Dokument"; + + + case ".xls": + case ".xlsx": + case ".xlsm": + return "Excel-Tabelle"; + + + case ".ppt": + case ".pptx": + return "PowerPoint-Präsentation"; + + + case ".jpg": + case ".jpeg": + case ".png": + case ".gif": + case ".webp": + case ".bmp": + return "Bild"; + + + case ".mp3": + case ".wav": + case ".ogg": + return "Audiodatei"; + + + case ".mp4": + case ".webm": + case ".ogv": + return "Videodatei"; + + + case ".txt": + return "Textdatei"; + + + case ".csv": + return "CSV-Datei"; + + + case ".json": + return "JSON-Datei"; + + + case ".xml": + return "XML-Datei"; + + + case ".log": + return "Logdatei"; + + + case ".zip": + case ".7z": + case ".rar": + case ".tar": + case ".gz": + return "Archiv"; + + + case ".exe": + return "Anwendung"; + + + case ".msi": + return "Installationspaket"; + + + default: + + if ( + string.IsNullOrEmpty( + extension)) + { + return "Datei"; + } + + + return + extension + .TrimStart('.') + .ToUpperInvariant(); + } + } + + + /* + * ======================================================== + * BREADCRUMB + * ======================================================== + */ + + private string BuildBreadcrumb( + string relativePath) + { + var html = + new StringBuilder(); + + + html.Append( + "
" + ); + + + html.Append( + "FileShare" + ); + + + if ( + !string.IsNullOrEmpty( + relativePath)) + { + string[] parts = + relativePath.Split( + new[] { '\\' }, + StringSplitOptions.RemoveEmptyEntries); + + + string accumulated = + ""; + + + for ( + int i = 0; + i < parts.Length; + i++) + { + accumulated = + CombineRelativePath( + accumulated, + parts[i]); + + + html.Append( + "/" + ); + + + if ( + i == + parts.Length - 1) + { + html.Append( + "" + + HttpUtility.HtmlEncode( + parts[i]) + + "" + ); + } + else + { + html.Append( + "" + + HttpUtility.HtmlEncode( + parts[i]) + + "" + ); + } + } + } + + + html.Append( + "
" + ); + + + return html.ToString(); + } + + + /* + * ======================================================== + * BERECHTIGUNG ORDNERVERZEICHNIS + * ======================================================== + */ + + private bool CanBrowseDirectory( + string path) + { + try + { + using ( + var enumerator = + Directory + .EnumerateFileSystemEntries( + path) + .GetEnumerator()) + { + enumerator.MoveNext(); + } + + + return true; + } + catch + { + return false; + } + } + + + /* + * ======================================================== + * SICHEREN ORDNERPFAD ERMITTELN + * ======================================================== + */ + + private string GetSafePhysicalPath( + string relativePath) + { + if ( + string.IsNullOrWhiteSpace( + relativePath)) + { + return ShareRoot; + } + + + string decoded = + HttpUtility.UrlDecode( + relativePath); + + + decoded = + decoded.Replace( + '/', + '\\'); + + + if ( + decoded.StartsWith("\\") || + decoded.Contains(":")) + { + throw new SecurityException(); + } + + + string[] parts = + decoded.Split( + new[] { '\\' }, + StringSplitOptions.RemoveEmptyEntries); + + + foreach ( + string part + in parts) + { + if ( + part == "." || + part == "..") + { + throw new SecurityException(); + } + } + + + string fullPath = + Path.GetFullPath( + Path.Combine( + ShareRoot, + decoded)); + + + string normalizedRoot = + Path.GetFullPath( + ShareRoot) + .TrimEnd('\\') + + "\\"; + + + if ( + !fullPath.StartsWith( + normalizedRoot, + StringComparison.OrdinalIgnoreCase)) + { + throw new SecurityException(); + } + + + if ( + !Directory.Exists( + fullPath)) + { + throw new DirectoryNotFoundException(); + } + + + if (!CanBrowseDirectory(fullPath)) + { + throw new UnauthorizedAccessException(); + } + + + return fullPath; + } + + + /* + * ======================================================== + * PARENT + * ======================================================== + */ + + private string GetParentRelativePath( + string path) + { + if ( + string.IsNullOrEmpty( + path)) + { + return null; + } + + + int position = + path.LastIndexOf('\\'); + + + if (position < 0) + { + return ""; + } + + + return path.Substring( + 0, + position); + } + + + /* + * ======================================================== + * RELATIVEN PFAD ZUSAMMENBAUEN + * ======================================================== + */ + + private string CombineRelativePath( + string parent, + string child) + { + if ( + string.IsNullOrEmpty( + parent)) + { + return child; + } + + + return + parent.TrimEnd('\\') + + "\\" + + child; + } + + + /* + * ======================================================== + * DATEIGRÖSSE + * ======================================================== + */ + + private string FormatFileSize( + long bytes) + { + if (bytes < 1024) + { + return bytes + " B"; + } + + + if (bytes < 1024 * 1024) + { + return + (bytes / 1024.0) + .ToString("0.0") + + " KB"; + } + + + if ( + bytes < + 1024L * 1024L * 1024L) + { + return + (bytes / + 1024.0 / + 1024.0) + .ToString("0.0") + + " MB"; + } + + + return + (bytes / + 1024.0 / + 1024.0 / + 1024.0) + .ToString("0.0") + + " GB"; + } + + + /* + * ======================================================== + * FEHLER + * ======================================================== + */ + + private string BuildError( + string title, + string message) + { + return + "
" + + + "

" + + HttpUtility.HtmlEncode( + title) + + "

" + + + "

" + + HttpUtility.HtmlEncode( + message) + + "

" + + + "
"; + } + } +} \ No newline at end of file diff --git a/Download.aspx b/Download.aspx new file mode 100644 index 0000000..103690e --- /dev/null +++ b/Download.aspx @@ -0,0 +1,8 @@ +<%@ Page + Language="C#" + ResponseEncoding="utf-8" + ContentType="text/html; charset=utf-8" + AutoEventWireup="true" + CodeFile="Download.aspx.cs" + Inherits="FileSharePortal.Download" +%> \ No newline at end of file diff --git a/Download.aspx.cs b/Download.aspx.cs new file mode 100644 index 0000000..c72946e --- /dev/null +++ b/Download.aspx.cs @@ -0,0 +1,342 @@ +using System; +using System.IO; +using System.Security; +using System.Web; +using System.Web.UI; + +namespace FileSharePortal +{ + public partial class Download : Page + { + private const string ShareRoot = + @"\\LAN-DC1\Fileshare"; + + + protected void Page_Load( + object sender, + EventArgs e) + { + /* + * Kein Caching. + */ + Response.Cache.SetCacheability( + HttpCacheability.NoCache); + + Response.Cache.SetNoStore(); + + + string relativePath = + Request.QueryString["path"]; + + + if (string.IsNullOrWhiteSpace(relativePath)) + { + Response.StatusCode = 400; + CompleteResponse(); + + return; + } + + + string physicalPath; + + + try + { + physicalPath = + GetSafePhysicalFilePath( + relativePath); + } + catch (UnauthorizedAccessException) + { + Response.StatusCode = 403; + CompleteResponse(); + + return; + } + catch (SecurityException) + { + Response.StatusCode = 403; + CompleteResponse(); + + return; + } + catch (FileNotFoundException) + { + Response.StatusCode = 404; + CompleteResponse(); + + return; + } + catch (DirectoryNotFoundException) + { + Response.StatusCode = 404; + CompleteResponse(); + + return; + } + catch + { + Response.StatusCode = 400; + CompleteResponse(); + + return; + } + + + /* + * Die Datei muss existieren. + */ + if (!File.Exists(physicalPath)) + { + Response.StatusCode = 404; + CompleteResponse(); + + return; + } + + + /* + * ==================================================== + * ZUGRIFF DES AKTUELL ANGEMELDETEN BENUTZERS PRÜFEN + * ==================================================== + * + * Wegen + * + * + * + * läuft dieser Zugriff unter dem angemeldeten + * AD-Benutzer. + */ + try + { + using ( + FileStream stream = + new FileStream( + physicalPath, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite | + FileShare.Delete)) + { + /* + * Datei erfolgreich geöffnet. + * + * Es wird hier absichtlich nichts gelesen. + * Das Öffnen reicht als Berechtigungsprüfung. + */ + } + } + catch (UnauthorizedAccessException) + { + Response.StatusCode = 403; + CompleteResponse(); + + return; + } + catch (IOException) + { + Response.StatusCode = 403; + CompleteResponse(); + + return; + } + + + /* + * ==================================================== + * DOWNLOAD AUSLIEFERN + * ==================================================== + */ + + string fileName = + Path.GetFileName( + physicalPath); + + + string encodedFileName = + Uri.EscapeDataString( + fileName); + + + string contentType = + MimeMapping.GetMimeMapping( + physicalPath); + + + Response.Clear(); + + Response.Buffer = true; + + Response.ContentType = + contentType; + + + /* + * UTF-8-Dateiname. + * + * Funktioniert auch für: + * + * Müller.pdf + * Änderungen.docx + * Köln.xlsx + * Rechnung März 2026.pdf + */ + Response.AddHeader( + "Content-Disposition", + "attachment; filename*=UTF-8''" + + encodedFileName + ); + + + /* + * Dateigröße setzen. + */ + FileInfo fileInfo = + new FileInfo( + physicalPath); + + + Response.AddHeader( + "Content-Length", + fileInfo.Length.ToString() + ); + + + /* + * Datei übertragen. + */ + Response.TransmitFile( + physicalPath); + + + CompleteResponse(); + } + + + /* + * ======================================================== + * SICHEREN DATEIPFAD ERMITTELN + * ======================================================== + */ + + private string GetSafePhysicalFilePath( + string relativePath) + { + /* + * URL-Decoding. + */ + string decoded = + HttpUtility.UrlDecode( + relativePath); + + + /* + * URL-Pfade in Windows-Pfade umwandeln. + */ + decoded = + decoded.Replace( + '/', + '\\'); + + + /* + * Keine absoluten Pfade erlauben. + * + * Verboten wären z.B.: + * + * \Windows\System32 + * C:\... + * \\Server\Share + */ + if ( + decoded.StartsWith("\\") || + decoded.Contains(":")) + { + throw new SecurityException(); + } + + + /* + * Path Traversal verhindern. + */ + string[] parts = + decoded.Split( + new[] { '\\' }, + StringSplitOptions.RemoveEmptyEntries); + + + foreach ( + string part + in parts) + { + if ( + part == "." || + part == "..") + { + throw new SecurityException(); + } + } + + + /* + * Vollständigen Dateipfad erzeugen. + */ + string fullPath = + Path.GetFullPath( + Path.Combine( + ShareRoot, + decoded)); + + + /* + * Root normalisieren. + */ + string normalizedRoot = + Path.GetFullPath( + ShareRoot) + .TrimEnd('\\') + + "\\"; + + + /* + * Der Pfad MUSS unterhalb von + * \\LAN-DC1\Fileshare bleiben. + */ + if ( + !fullPath.StartsWith( + normalizedRoot, + StringComparison.OrdinalIgnoreCase)) + { + throw new SecurityException(); + } + + + /* + * Datei muss existieren. + */ + if (!File.Exists(fullPath)) + { + throw new FileNotFoundException(); + } + + + return fullPath; + } + + + /* + * ======================================================== + * RESPONSE BEENDEN + * ======================================================== + * + * Kleine Hilfsmethode, damit Response.End() + * nicht unnötig in mehreren Stellen steht. + */ + private void CompleteResponse() + { + HttpContext.Current.ApplicationInstance + .CompleteRequest(); + } + } +} \ No newline at end of file