Dateien nach "/" hochladen

This commit is contained in:
MVS-deHB committed 2026-09-24 12:38:47 +00:00
commit a50893a9b3
4 files changed
+2584

No files matched your search

+963
View File
@@ -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"
%>
<!DOCTYPE html>
<html lang="de">
<head runat="server">
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
<title>FileShare</title>
<style>
/*
============================================================
GRUNDLAYOUT
============================================================
*/
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
font-family:
"Segoe UI",
Arial,
Helvetica,
sans-serif;
background: #f3f4f6;
color: #1f2937;
}
/*
============================================================
HEADER
============================================================
*/
.header {
background: #1f2937;
color: white;
padding: 26px 20px;
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.15);
}
.header-inner {
max-width: 1050px;
margin: 0 auto;
display: flex;
align-items: center;
gap: 16px;
}
.brand-icon {
width: 54px;
height: 54px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
background: #374151;
border-radius: 12px;
color: white;
}
.brand-icon svg {
width: 29px;
height: 29px;
display: block;
}
.header-info {
min-width: 0;
}
.header-info h1 {
margin: 0;
font-size: 27px;
font-weight: 600;
}
.header-info p {
margin: 4px 0 0;
color: #d1d5db;
font-size: 14px;
}
.user {
margin-left: auto;
color: #d1d5db;
font-size: 13px;
text-align: right;
white-space: nowrap;
}
.user strong {
color: white;
}
/*
============================================================
HAUPTINHALT
============================================================
*/
.content {
max-width: 1050px;
margin: 0 auto;
padding: 38px 20px;
}
/*
============================================================
BREADCRUMB
============================================================
*/
.breadcrumb {
margin-bottom: 25px;
color: #6b7280;
font-size: 14px;
}
.breadcrumb a {
color: #374151;
text-decoration: none;
}
.breadcrumb a:hover {
text-decoration: underline;
}
.breadcrumb span {
margin: 0 6px;
color: #9ca3af;
}
.breadcrumb strong {
color: #1f2937;
}
/*
============================================================
EINLEITUNG
============================================================
*/
.intro {
margin-bottom: 25px;
}
.intro h2 {
margin: 0 0 8px;
font-size: 27px;
font-weight: 600;
}
.intro p {
margin: 0;
color: #6b7280;
font-size: 15px;
}
/*
============================================================
ROOT-ORDNER
============================================================
*/
.folder-grid {
display: grid;
grid-template-columns:
repeat(
auto-fit,
minmax(310px, 1fr)
);
gap: 18px;
}
.folder-card {
display: flex;
align-items: center;
gap: 17px;
padding: 21px;
background: white;
border:
1px solid #e5e7eb;
border-radius: 14px;
color: inherit;
text-decoration: none;
transition:
transform 0.15s ease,
box-shadow 0.15s ease,
border-color 0.15s ease;
}
.folder-card:hover {
transform: translateY(-2px);
border-color: #d1d5db;
box-shadow:
0 8px 22px
rgba(0, 0, 0, 0.08);
}
/*
============================================================
ORDNER-ICONS
============================================================
*/
.folder-icon,
.item-icon {
width: 50px;
height: 50px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 11px;
background: #f3f4f6;
color: #4b5563;
}
.folder-icon svg,
.item-icon svg {
width: 26px;
height: 26px;
display: block;
}
/*
============================================================
ORDNERINFORMATION
============================================================
*/
.folder-content {
flex: 1;
min-width: 0;
}
.folder-title {
margin-bottom: 5px;
font-size: 17px;
font-weight: 600;
overflow-wrap: anywhere;
}
.folder-description {
color: #6b7280;
font-size: 14px;
}
.folder-arrow,
.item-arrow {
color: #9ca3af;
font-size: 21px;
flex-shrink: 0;
}
/*
============================================================
ZURÜCK-BUTTON
============================================================
*/
.toolbar {
margin-bottom: 20px;
}
.back-button {
display: inline-block;
padding:
10px 15px;
background: white;
border:
1px solid #e5e7eb;
border-radius: 9px;
color: #374151;
text-decoration: none;
font-size: 14px;
}
.back-button:hover {
background: #f9fafb;
}
/*
============================================================
DATEILISTE
============================================================
*/
.item-list {
background: white;
border:
1px solid #e5e7eb;
border-radius: 12px;
overflow: hidden;
box-shadow:
0 2px 5px
rgba(0, 0, 0, 0.03);
}
/*
Eine Datei bzw. ein Ordner = genau eine Zeile.
*/
.item {
display: flex;
align-items: center;
width: 100%;
min-height: 70px;
padding:
9px 16px;
background: white;
border-bottom:
1px solid #f0f0f0;
color: inherit;
text-decoration: none;
}
.item:last-child {
border-bottom: none;
}
.item:hover {
background: #fafafa;
}
/*
============================================================
ORDNERZEILE
============================================================
*/
.item .item-name {
flex: 1;
min-width: 0;
padding-left: 15px;
font-size: 15px;
overflow-wrap: anywhere;
}
/*
============================================================
DATEIZEILE
============================================================
*/
.file-row {
display: flex;
align-items: center;
width: 100%;
min-height: 70px;
padding:
8px 16px;
background: white;
border-bottom:
1px solid #f0f0f0;
}
.file-row:last-child {
border-bottom: none;
}
.file-row:hover {
background: #fafafa;
}
/*
Der linke Bereich umfasst Icon + Dateiname +
Zusatzinformationen.
*/
.file-main {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
gap: 14px;
color: inherit;
text-decoration: none;
}
.file-main:hover {
text-decoration: none;
}
.file-main:hover .file-name {
text-decoration: underline;
}
/*
============================================================
DATEI-ICON
============================================================
*/
.file-row .item-icon {
width: 48px;
height: 48px;
flex-shrink: 0;
}
.file-row .item-icon svg {
width: 27px;
height: 27px;
}
/*
============================================================
DATEIINFORMATION
============================================================
*/
.file-info {
flex: 1;
min-width: 0;
display: flex;
align-items: baseline;
gap: 14px;
}
.file-name {
min-width: 0;
color: #1f2937;
font-size: 15px;
font-weight: 500;
overflow-wrap: anywhere;
}
.file-details {
flex-shrink: 0;
color: #9ca3af;
font-size: 12px;
white-space: nowrap;
}
/*
============================================================
DOWNLOAD-BUTTON
============================================================
*/
.download {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-left: 18px;
min-width: 95px;
padding:
8px 13px;
background: #f3f4f6;
border:
1px solid #e5e7eb;
border-radius: 8px;
color: #374151;
font-size: 13px;
text-decoration: none;
transition:
background 0.15s ease,
border-color 0.15s ease;
}
.download:hover {
background: #e5e7eb;
border-color: #d1d5db;
text-decoration: none;
}
/*
============================================================
LEERER ORDNER
============================================================
*/
.empty {
background: white;
border:
1px solid #e5e7eb;
border-radius: 12px;
padding: 30px;
color: #6b7280;
text-align: center;
}
/*
============================================================
FEHLER
============================================================
*/
.error {
background: white;
border:
1px solid #e5e7eb;
border-radius: 12px;
padding: 25px;
}
.error h3 {
margin:
0 0 7px;
font-size: 19px;
}
.error p {
margin: 0;
color: #6b7280;
font-size: 14px;
}
/*
============================================================
FOOTER
============================================================
*/
.footer {
max-width: 1050px;
margin: 0 auto;
padding:
20px;
color: #9ca3af;
font-size: 13px;
text-align: center;
}
/*
============================================================
RESPONSIVE
============================================================
*/
@media (max-width: 800px) {
.file-info {
display: block;
}
.file-details {
display: block;
margin-top: 3px;
}
}
@media (max-width: 650px) {
.header-inner {
align-items: flex-start;
}
.user {
display: none;
}
.folder-grid {
grid-template-columns: 1fr;
}
.content {
padding:
28px 15px;
}
.file-row {
min-height: 65px;
padding:
7px 11px;
}
.file-main {
gap: 10px;
}
.file-row .item-icon {
width: 42px;
height: 42px;
}
.file-row .item-icon svg {
width: 24px;
height: 24px;
}
.file-info {
display: block;
}
.file-name {
font-size: 14px;
}
.file-details {
margin-top: 3px;
font-size: 11px;
}
.download {
min-width: auto;
margin-left: 8px;
padding:
7px 9px;
font-size: 12px;
}
}
</style>
</head>
<body>
<form
id="form1"
runat="server">
<!-- ========================================================
HEADER
======================================================== -->
<header class="header">
<div class="header-inner">
<div class="brand-icon">
<svg
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true">
<path
d="M3 6.5C3 5.67 3.67 5 4.5 5H9L11 7H19.5C20.33 7 21 7.67 21 8.5V18.5C21 19.33 20.33 20 19.5 20H4.5C3.67 20 3 19.33 3 18.5V6.5Z"
fill="none"
stroke="currentColor"
stroke-width="1.8"
stroke-linejoin="round" />
</svg>
</div>
<div class="header-info">
<h1>
FileShare
</h1>
<p>
Interne Dokumentenablage
</p>
</div>
<div class="user">
Angemeldet als:
<strong>
<%= Server.HtmlEncode(CurrentUser) %>
</strong>
</div>
</div>
</header>
<!-- ========================================================
CONTENT
======================================================== -->
<main class="content">
<%= BreadcrumbHtml %>
<div class="intro">
<h2>
<%= string.IsNullOrEmpty(CurrentPath)
? "Willkommen"
: "Dateien und Ordner" %>
</h2>
<p>
<%= string.IsNullOrEmpty(CurrentPath)
? "Es werden nur Bereiche angezeigt, auf die Ihr Benutzerkonto Zugriff hat."
: "Es werden nur zugängliche Ordner und Dateien angezeigt." %>
</p>
</div>
<%= ContentHtml %>
</main>
<!-- ========================================================
FOOTER
======================================================== -->
<footer class="footer">
Interne Dokumentenablage
</footer>
</form>
</body>
</html>
+1271
View File
File diff suppressed because it is too large. Load diff
+8
View File
@@ -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"
%>
+342
View File
@@ -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
*
* <identity impersonate="true" />
*
* 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();
}
}
}