Initialer Commit

This commit is contained in:
Adam Skotarczak 2025-03-12 22:21:30 +01:00
commit 00321817dc
38 changed files with 1793 additions and 0 deletions

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
# Build- und Cache-Ordner ignorieren
__pycache__/
upload/
logs/
build/
dist/
/pyUpload.*/
Output/
# Virtuelle Umgebung ignorieren (falls vorhanden)
.venv/
.env/
.idea/
.vscode/
*.pem
# PyInstaller-exe-Dateien ignorieren
*.spec
pyUpload.exe

35
Makefile Normal file
View File

@ -0,0 +1,35 @@
.PHONY: exe release clean
# Variablen
PYTHON = python3
SCRIPT = pyUpload.py
EXE_NAME = pyUpload
BUILD_DIR = build
DIST_DIR = release
REQ_FILE = requirements.txt
exe:
@echo "Erzeuge ausführbare Datei..."
@mkdir -p $(BUILD_DIR)
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico --name $(EXE_NAME) $(SCRIPT)
@mv dist/$(EXE_NAME) $(BUILD_DIR)/
@echo "Erstellung abgeschlossen: $(BUILD_DIR)/$(EXE_NAME)"
release: exe
@echo "Erstelle Release-Paket..."
@mkdir -p $(DIST_DIR)
@cp $(BUILD_DIR)/$(EXE_NAME) $(DIST_DIR)/
@cp $(REQ_FILE) $(DIST_DIR)/
@cp template.html success.html favicon.ico $(DIST_DIR)/
@echo "Release-Paket bereit in $(DIST_DIR)"
zip: release
@echo "Erstelle ZIP-Archiv..."
@cd $(DIST_DIR) && zip -r ../$(ZIP_NAME) $(EXE_NAME) template.html success.html favicon.ico
@echo "ZIP-Archiv erstellt: $(ZIP_NAME)"
clean:
@echo "Bereinige Projektverzeichnis..."
@rm -rf $(BUILD_DIR) $(DIST_DIR) build dist __pycache__ *.spec
@echo "Bereinigung abgeschlossen."

4
Tagebuch.md Normal file
View File

@ -0,0 +1,4 @@
# Entwicklertagebuch
## 08.03.25
Heute habe ich die mit innoSetup auf einem Rechner installiert auf dem überhaupt kein Python installiert war und dies funktionierte nicht. Klar auch, die venv Umgebung setzt eine Python Installation vorraus und arbeitet mit absoluten Pfaden. Der nächste Versuch wird mit einer portablen Python Version durchgeführt.

70
_static/Tagebuch Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Entwicklertagebuch - </title>
<meta name="description" content="08.03.25 Heute habe ich die mit innoSetup auf einem Rechner installiert auf dem überhaupt kein Python installiert war und dies funktionierte nicht. Klar…">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<style>
body{font-family:Helvetica,sans-serif;margin:0}
header,main,footer{padding:2em}
header{background:darkslategray} header a{color:white;text-decoration:none}
h1{margin-top:0} main{max-width:60em}
</style>
<link rel="canonical" href="/Tagebuch">
<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="RSS">
</head>
<body class="page page__Tagebuch">
<header><a href="/"></a></header>
<main class="content">
<h1>Entwicklertagebuch</h1>
<h2>08.03.25</h2>
<p>Heute habe ich die mit innoSetup auf einem Rechner installiert auf dem überhaupt kein Python installiert war und dies funktionierte nicht. Klar auch, die venv Umgebung setzt eine Python Installation vorraus und arbeitet mit absoluten Pfaden. Der nächste Versuch wird mit einer portablen Python Version durchgeführt. </p>
<ul class="page__list">
<li><a href="&#x2f;build-infos">
## exe erstellen:
### pyinstaller
pip install pyinstaller
pyinstaller --onefile --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
pyinstaller --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
### nuitka
python setup.py build
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
## requirements.txt:
pipreqs . --force</a></li>
<li><a href="&#x2f;info">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
<li><a href="&#x2f;dev&#x2f;README">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
</ul>
</main>
<footer><p>&copy; </footer>
</body>
</html>

BIN
_static/Tagebuch.br Normal file

Binary file not shown.

86
_static/build-infos Normal file
View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
## exe erstellen:
### pyinstaller
pip install pyinstaller
pyinstaller --onefile --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
pyinstaller --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
### nuitka
python setup.py build
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
## requirements.txt:
pipreqs . --force - </title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<style>
body{font-family:Helvetica,sans-serif;margin:0}
header,main,footer{padding:2em}
header{background:darkslategray} header a{color:white;text-decoration:none}
h1{margin-top:0} main{max-width:60em}
</style>
<link rel="canonical" href="/build-infos">
<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="RSS">
</head>
<body class="page page__build-infos">
<header><a href="/"></a></header>
<main class="content">
<h1>
## exe erstellen:
### pyinstaller
pip install pyinstaller
pyinstaller --onefile --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
pyinstaller --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
### nuitka
python setup.py build
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
## requirements.txt:
pipreqs . --force</h1>
<p></p>
<ul class="page__list">
<li><a href="&#x2f;Tagebuch">Entwicklertagebuch</a></li>
<li><a href="&#x2f;info">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
<li><a href="&#x2f;dev&#x2f;README">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
</ul>
</main>
<footer><p>&copy; </footer>
</body>
</html>

BIN
_static/build-infos.br Normal file

Binary file not shown.

177
_static/info Normal file
View File

@ -0,0 +1,177 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung - </title>
<meta name="description" content="Beschreibung pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Dieses Programm eignet sich ideal,…">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<style>
body{font-family:Helvetica,sans-serif;margin:0}
header,main,footer{padding:2em}
header{background:darkslategray} header a{color:white;text-decoration:none}
h1{margin-top:0} main{max-width:60em}
</style>
<link rel="canonical" href="/info">
<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="RSS">
</head>
<body class="page page__info">
<header><a href="/"></a></header>
<main class="content">
<h1>#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</h1>
<h3>Beschreibung</h3>
<p>pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen. </p>
<p>Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.</p>
<p>Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.</p>
<h3>Download</h3>
<ul>
<li><strong>Portabel für Windows als .zip</strong>
[download id="2323"]</li>
</ul>
<blockquote>
<p>Aktuell ist der Download der portablen und Compilierten Version gesperrt da es von diversen Virenscannern als Bedrohung eingestuft wird. Bei Interesse ist das Programm aktuell nur auf Anfrage per eMail erhältlich. In Kürze erfolgt eine Veröffentlichung inklusive Code auf GitHub.</p>
</blockquote>
<h3>Features – Die Vorteile von pyUpload auf einen Blick</h3>
<ul>
<li><strong>Sichere Dateiübertragung per HTTPS</strong> – Alle Daten werden verschlüsselt übertragen.</li>
<li><strong>Automatische Erstellung eines selbstsignierten SSL-Zertifikats</strong> – Keine zusätzliche Konfiguration notwendig.</li>
<li><strong>Intuitive, webbasierte Benutzeroberfläche</strong> – Einfach zu bedienen, keine Installation erforderlich.</li>
<li><strong>Strukturierte Speicherung</strong> – Dateien werden in client-spezifischen Verzeichnissen gespeichert.</li>
<li><strong>Zentralisierte und client-spezifische Logging-Funktion</strong> – Detaillierte Nachverfolgung aller Uploads.</li>
<li><strong>Flexible Nutzung mit oder ohne GUI</strong> – Start als Desktop-Anwendung oder reine Konsolen-Version möglich.</li>
<li><strong>Schnelle Einrichtung</strong> – Download, Entpacken und sofort loslegen!</li>
</ul>
<h3>Installationsanleitung – So startest du pyUpload</h3>
<p>Es gibt zwei Möglichkeiten, pyUpload zu nutzen: Entweder die manuelle Installation oder die Nutzung einer vorgefertigten, ausführbaren Version.</p>
<h4>1. Nutzung der fertigen Download-Version</h4>
<p>Falls du keine Python-Installation benötigst, kannst du die vorgefertigte <strong>ZIP-Version</strong> von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.</p>
<ol>
<li>Lade die neueste <strong>pyUpload.zip</strong> von der offiziellen Website herunter.</li>
<li>Entpacke die ZIP-Datei in einen beliebigen Ordner.</li>
<li>Starte die enthaltene <code>pyUpload.exe</code>.</li>
<li>Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die <code>pyUpload.exe</code> direkt in der Konsole mit <code>--nogui</code> gestartet werden:
<code>sh
pyUpload.exe --nogui
</code></li>
<li>Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
<code>sh
pyUpload.exe --help
</code></li>
</ol>
<h4>2. Manuelle Installation für Python-Nutzer</h4>
<ol>
<li>Stelle sicher, dass <strong>Python 3</strong> auf deinem System installiert ist.</li>
<li>Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
<code>sh
pip install -r requirements.txt
</code></li>
<li>Starte den Server mit:
<code>sh
python pyUpload.py
</code></li>
<li>Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
<code>sh
python pyUpload.py --nogui
</code></li>
</ol>
<h3>Zugriff auf die Weboberfläche</h3>
<ul>
<li>Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
<code>
https://&lt;server-ip&gt;:4443
</code></li>
<li>Falls die GUI-Version gestartet wurde, erscheint ein <strong>QR-Code</strong>, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.</li>
</ul>
<h3>Datei-Upload leicht gemacht – So funktioniert es</h3>
<ol>
<li>Ãffne die <strong>Weboberfläche</strong> im Browser.</li>
<li>Wähle die gewünschte <strong>Datei aus</strong> und klicke auf <strong>„Hochladen“</strong>.</li>
<li>Nach erfolgreichem Upload erscheint eine <strong>Bestätigungsseite</strong>, die den Abschluss der Übertragung bestätigt.</li>
</ol>
<h3>SSL-Zertifikatswarnung in Browsern umgehen</h3>
<p>Da pyUpload ein <strong>selbstsigniertes SSL-Zertifikat</strong> nutzt, kann es beim ersten Zugriff zu einer Warnung des Browsers kommen. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:</p>
<ul>
<li>In den meisten Browsern gibt es eine Option wie <strong>„Erweitert“</strong> oder <strong>„Trotzdem fortfahren“</strong>, um die Warnung zu übergehen.</li>
<li>Alternativ kann das Zertifikat <strong>manuell importiert und als vertrauenswürdig markiert</strong> werden, um künftige Warnmeldungen zu vermeiden.</li>
</ul>
<h3>Logging und Fehlerbehandlung – Transparenz und Kontrolle</h3>
<ul>
<li>Alle <strong>Uploads und Anfragen</strong> werden in <strong>zentralen sowie client-spezifischen Logdateien</strong> gespeichert. Diese befinden sich im <code>logs/</code>-Verzeichnis.</li>
<li>Falls während der Nutzung von pyUpload <strong>Probleme auftreten</strong>, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.</li>
</ul>
<h3>Lizenz und Autor</h3>
<ul>
<li><strong>Entwickelt von Adam Skotarczak (C) 2025</strong>.</li>
</ul>
<ul class="page__list">
<li><a href="&#x2f;Tagebuch">Entwicklertagebuch</a></li>
<li><a href="&#x2f;build-infos">
## exe erstellen:
### pyinstaller
pip install pyinstaller
pyinstaller --onefile --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
pyinstaller --add-data &quot;template.html;.&quot; --add-data &quot;success.html;.&quot; --add-data &quot;favicon.ico;.&quot; --windowed --icon favicon.ico pyUpload.py
### nuitka
python setup.py build
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
## requirements.txt:
pipreqs . --force</a></li>
<li><a href="&#x2f;dev&#x2f;README">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
</ul>
</main>
<footer><p>&copy; </footer>
</body>
</html>

BIN
_static/info.br Normal file

Binary file not shown.

BIN
assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
assets/pyUpload-Logo.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
backup/pyUpload_0.1.0.zip Normal file

Binary file not shown.

19
build-infos.md Normal file
View File

@ -0,0 +1,19 @@
## exe erstellen:
### pyinstaller
pip install pyinstaller
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
pyinstaller --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
### nuitka
python setup.py build
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
## requirements.txt:
pipreqs . --force

67
build.bat Normal file
View File

@ -0,0 +1,67 @@
@echo off
setlocal
:: Variablen
set SCRIPT=pyUpload.py
set EXE_NAME=pyUpload.exe
set BUILD_DIR=build
set DIST_DIR=release
set ZIP_NAME=pyUpload.zip
set REQ_FILE=requirements.txt
:: Liste von Dateien/Ordnern, die beim "clean" entfernt werden sollen
set DELETE_LIST=build dist __pycache__ *.spec *.zip temp_* logs\* cache\* pyUpload.build\* pyUpload.dist\* upload\* *.pem
:: Menü anzeigen
echo Wähle eine Option:
echo 1 - Erstelle ausführbare Datei (exe 1)
echo 2 - Erstelle Release-Paket (release 1+2)
echo 3 - Erstelle ZIP-Archiv (zip 1+2+3)
echo 4 - Aufraeumen (clean)
set /p CHOICE=Eingabe (1-4):
if "%CHOICE%"=="1" goto exe
if "%CHOICE%"=="2" goto release
if "%CHOICE%"=="3" goto zip
if "%CHOICE%"=="4" goto clean
echo Ungültige Eingabe!
exit /b
:exe
echo Erzeuge ausführbare Datei...
mkdir %BUILD_DIR% 2>nul
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico --name %EXE_NAME% %SCRIPT%
move dist\%EXE_NAME% %BUILD_DIR%\
echo Erstellung abgeschlossen: %BUILD_DIR%\%EXE_NAME%
exit /b
:release
call :exe
echo Erstelle Release-Paket...
mkdir %DIST_DIR% 2>nul
copy %BUILD_DIR%\%EXE_NAME% %DIST_DIR%\
copy %REQ_FILE% %DIST_DIR%\
copy template.html success.html favicon.ico %DIST_DIR%\
echo Release-Paket bereit in %DIST_DIR%
exit /b
:zip
call :release
echo Erstelle ZIP-Archiv...
powershell Compress-Archive -Path "%DIST_DIR%\%EXE_NAME%", "%DIST_DIR%\template.html", "%DIST_DIR%\success.html", "%DIST_DIR%\favicon.ico" -DestinationPath "%ZIP_NAME%"
echo ZIP-Archiv erstellt: %ZIP_NAME%
exit /b
:clean
echo Bereinige Projektverzeichnis...
:: Durchläuft alle Dateien/Ordner in DELETE_LIST
for %%F in (%DELETE_LIST%) do (
if exist %%F (
echo Entferne: %%F
rmdir /s /q %%F 2>nul || del /q %%F 2>nul
)
)
echo Bereinigung abgeschlossen.
exit /b

6
desktop.ini Normal file
View File

@ -0,0 +1,6 @@
[.ShellClassInfo]
IconResource=C:\Users\adam\Documents\Projekte\pyUpload\assets\favicon.ico,0
[ViewState]
Mode=
Vid=
FolderType=Documents

10
dev/LICENSE Normal file
View File

@ -0,0 +1,10 @@
MIT License
Copyright (c) 2025 Adam Scotarczak (adam@skotarczak.net) - ionivation.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

93
dev/README.md Normal file
View File

@ -0,0 +1,93 @@
## pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung
### Beschreibung
pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Es richtet sich an Privatnutzer, die eine schnelle Möglichkeit suchen, Dateien zwischen Geräten zu übertragen, sowie an Unternehmen oder Teams, die eine sichere Lösung für den internen Datenaustausch benötigen. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen.
Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.
Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.
### Features Die Vorteile von pyUpload auf einen Blick
- **Sichere Dateiübertragung per HTTPS** Alle Daten werden verschlüsselt übertragen.
- **Automatische Erstellung eines selbstsignierten SSL-Zertifikats** Keine zusätzliche Konfiguration notwendig.
- **Intuitive, webbasierte Benutzeroberfläche** Einfach zu bedienen, keine Installation erforderlich.
- **Strukturierte Speicherung** Dateien werden in client-spezifischen Verzeichnissen gespeichert.
- **Zentralisierte und client-spezifische Logging-Funktion** Detaillierte Nachverfolgung aller Uploads.
- **Flexible Nutzung mit oder ohne GUI** Start als Desktop-Anwendung oder reine Konsolen-Version möglich.
- **Schnelle Einrichtung** Download, Entpacken und sofort loslegen!
### Installationsanleitung So startest du pyUpload
Es gibt drei Möglichkeiten, pyUpload zu nutzen:
- **Manuelle Installation** in einer vorhandenen Python-Umgebung, in der alle notwendigen Bibliotheken manuell installiert werden.
- **Nutzung einer vorgefertigten, ausführbaren .exe (Windows) Version**, die mit pyinstaller kompiliert wurde.
- **Nutzung in einer virtuellen Python-Umgebung**, die automatisch durch `install.bat` eingerichtet wird. Anschließend kann das Programm mit `start.bat` gestartet werden.
#### 1. Manuelle Installation für Python-Nutzer
1. Stelle sicher, dass **Python 3** auf deinem System installiert ist.
2. Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
```sh
pip install -r requirements.txt
```
3. Starte den Server mit:
```sh
python pyUpload.py
```
4. Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
```sh
python pyUpload.py --nogui
```
#### 2. Nutzung der fertigen .exe Download-Version
Falls du keine Python-Installation benötigst, kannst du die vorgefertigte **ZIP-Version** von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.
1. Lade die neueste **pyUpload.zip** von der offiziellen Website herunter, inklusive virtueller Umgebung.
2. Entpacke die ZIP-Datei in einen beliebigen Ordner.
3. Starte die enthaltene `pyUpload.exe`.
4. Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die `pyUpload.exe` direkt in der Konsole mit `--nogui` gestartet werden:
```sh
pyUpload.exe --nogui
```
5. Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
```sh
pyUpload.exe --help
```
#### 3. Nutzung in virtueller Python-Umgebung
Lade die ZIP-Datei mit der virtuellen Installationsumgebung herunter und starte die `install.bat` durch Doppelklick. Es öffnet sich ein Konsolenfenster (CLI) und eine virtuelle Umgebung für pyUpload wird erstellt. Anschließend kann das Programm mit der `start.bat` gestartet werden. In der Grundeinstellung wird eine GUI mit QR-Code gestartet.
### Zugriff auf die Weboberfläche
- Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
```
https://<server-ip>:4443
```
- Falls die GUI-Version gestartet wurde, erscheint ein **QR-Code**, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.
### Datei-Upload leicht gemacht So funktioniert es
1. Öffne die **Weboberfläche** im Browser.
2. Wähle die gewünschte **Datei aus** und klicke auf **„Hochladen“**.
3. Nach erfolgreichem Upload erscheint eine **Bestätigungsseite**, die den Abschluss der Übertragung bestätigt.
### SSL-Zertifikatswarnung in Browsern umgehen
Da pyUpload ein **selbstsigniertes SSL-Zertifikat** nutzt, wird es beim ersten Zugriff zu einer Warnung des Browsers kommen. Alternativ kann ein eigenes SSL-Zertifikat hinterlegt werden, indem die Zertifikats- und Schlüsseldateien `cert.pem` und `key.pem` durch eigene, signierte Zertifikate ersetzt werden. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:
- In den meisten Browsern gibt es eine Option wie **„Erweitert“** oder **„Trotzdem fortfahren“**, um die Warnung zu übergehen.
- Alternativ kann das Zertifikat **manuell importiert und als vertrauenswürdig markiert** werden, um künftige Warnmeldungen zu vermeiden.
### Logging und Fehlerbehandlung Transparenz und Kontrolle
- Alle **Uploads und Anfragen** werden in **zentralen sowie client-spezifischen Logdateien** gespeichert. Diese befinden sich im `logs/`-Verzeichnis.
- Falls während der Nutzung von pyUpload **Probleme auftreten**, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.
### Lizenz und Autor
- **Entwickelt von Adam Skotarczak (C) 2025**.

BIN
dev/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

54
dev/install.bat Normal file
View File

@ -0,0 +1,54 @@
@echo off
setlocal
:: Prüfen, ob Python installiert ist
where python >nul 2>nul
if %ERRORLEVEL% NEQ 0 (
echo Fehler: Python ist nicht installiert oder nicht im PATH!
echo Bitte installiere Python und starte die Installation erneut.
pause
exit /b 1
)
:: Python-Version prüfen (Mindestversion 3.8)
for /f "tokens=2 delims= " %%v in ('python --version 2^>^&1') do set PYTHON_VERSION=%%v
for /f "tokens=1,2 delims=." %%a in ("%PYTHON_VERSION%") do (
if %%a LSS 3 (
echo Fehler: Python 3.8 oder höher ist erforderlich!
pause
exit /b 1
)
if %%a==3 if %%b LSS 8 (
echo Fehler: Python 3.8 oder höher ist erforderlich!
pause
exit /b 1
)
)
:: Virtuelle Umgebung erstellen, falls sie nicht existiert
if not exist venv (
echo Erstelle virtuelle Server-Umgebung ...
python -m venv --copies venv
if %ERRORLEVEL% NEQ 0 (
echo Fehler beim Erstellen der virtuellen Umgebung!
pause
exit /b 2
)
)
:: Aktivieren der virtuellen Umgebung
call venv\Scripts\activate
:: Installieren der Abhängigkeiten
echo Installiere Abhaengigkeiten aus dem Internet ...
pip install --no-warn-script-location --disable-pip-version-check -r requirements.txt
if %ERRORLEVEL% NEQ 0 (
echo Fehler beim Installieren der Abhaengigkeiten!
pause
exit /b 3
)
:: Erfolgsmeldung
echo.
echo Installation abgeschlossen.
timeout /t 3 >nul & exit /b 0

16
dev/pyUpload.bat Normal file
View File

@ -0,0 +1,16 @@
@echo off
setlocal
:: Prüfen, ob die virtuelle Umgebung existiert
if not exist venv (
echo Fehler: Die virtuelle Umgebung existiert nicht!
echo Führe zuerst "install.bat" aus.
pause
exit /b
)
:: Aktivieren der virtuellen Umgebung
call venv\Scripts\activate
:: Starte den Upload-Server
python pyUpload.py

347
dev/pyUpload.py Normal file
View File

@ -0,0 +1,347 @@
#!/usr/bin/env python3
# © 2025 Adam Skotarczak (adam@skotarczak.net)
# Dieses Softwarepaket darf nicht ohne Genehmigung weiterverbreitet werden!
# Version 1.2.2 (05.03.2025)
import os
import sys
import ssl
import logging
import socket
import argparse
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from datetime import datetime, timedelta, timezone
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
# -------------------------------------------------------------------
# Globale Konfigurationen & Verzeichnisse
# -------------------------------------------------------------------
UPLOAD_DIR = 'upload'
LOG_DIR = 'logs'
CERT_FILE = 'cert.pem'
KEY_FILE = 'key.pem'
CENTRAL_LOG_FILE = os.path.join(LOG_DIR, 'pyupload.log')
os.makedirs(UPLOAD_DIR, exist_ok=True)
os.makedirs(LOG_DIR, exist_ok=True)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(message)s",
handlers=[logging.FileHandler(CENTRAL_LOG_FILE), logging.StreamHandler()]
)
central_logger = logging.getLogger("central_logger")
client_loggers = {}
# -------------------------------------------------------------------
# HTTP-Request-Handler
# -------------------------------------------------------------------
class SecureHTTPRequestHandler(BaseHTTPRequestHandler):
def log_message(self, format, *args):
"""Sammelt Log-Einträge in Client-spezifische Dateien und die Zentrale-Logdatei."""
client_ip = self.client_address[0]
message = format % args
# Einmalig pro Client-IP einen dedizierten Logger anlegen.
if client_ip not in client_loggers:
logger = logging.getLogger(f'client_{client_ip}')
logger.setLevel(logging.INFO)
client_log_file = os.path.join(LOG_DIR, f"{client_ip}.log")
handler = logging.FileHandler(client_log_file)
handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
logger.addHandler(handler)
client_loggers[client_ip] = logger
# In den Client-spezifischen Logger und in den zentralen Logger schreiben.
client_loggers[client_ip].info(message)
central_logger.info(f"{client_ip} - {message}")
def send_html_response(self, filename):
"""Liefert eine HTML-Datei als HTTP-Response zurück."""
try:
with open(filename, "r", encoding="utf-8") as f:
content = f.read()
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(content.encode("utf-8"))
except FileNotFoundError:
self.send_error(500, "HTML-Template nicht gefunden")
def do_GET(self):
"""Ausliefern der Upload-Seite (template.html)."""
if self.path == '/':
self.send_html_response("template.html")
else:
self.send_error(404, "Seite nicht gefunden")
self.log_message('404 Not Found: %s', self.path)
def do_POST(self):
"""Behandelt Datei-Uploads (multipart/form-data) direkt als Stream."""
try:
content_type = self.headers.get('Content-Type')
content_length = int(self.headers.get('Content-Length', 0))
if not content_type or 'multipart/form-data' not in content_type:
self.send_error(400, "Ungültiger Content-Type")
self.log_message('400 Bad Request: Ungültiger Content-Type')
return
if content_length == 0:
self.send_error(400, "Leere Anfrage erhalten")
self.log_message('400 Bad Request: Leere Anfrage')
return
client_ip = self.client_address[0]
client_upload_dir = os.path.join(UPLOAD_DIR, client_ip)
os.makedirs(client_upload_dir, exist_ok=True)
boundary = content_type.split("boundary=")[-1].encode()
raw_data = self.rfile.read(content_length)
parts = raw_data.split(b"--" + boundary)
found_file = False
for part in parts:
if b"Content-Disposition" in part:
headers, file_data = part.split(b"\r\n\r\n", 1)
filename_start = headers.find(b'filename="') + 10
filename_end = headers.find(b'"', filename_start)
filename = headers[filename_start:filename_end].decode()
if filename: # Falls tatsächlich ein Dateiname vorhanden ist
file_path = os.path.join(client_upload_dir, os.path.basename(filename))
with open(file_path, "wb") as f:
# Entferne das trailing CRLF oder "--"
f.write(file_data.rstrip(b"\r\n--"))
self.log_message(f"Datei {filename} erfolgreich hochgeladen.")
found_file = True
if not found_file:
self.send_error(400, "Keine Datei im Upload enthalten")
self.log_message('400 Bad Request: Keine Datei übermittelt')
return
# Erfolgsseite senden
self.send_html_response("success.html")
except Exception as e:
self.log_message(f"Fehler: {e}")
self.send_error(500, "Interner Serverfehler")
# -------------------------------------------------------------------
# HTTPS-Server-Setup
# -------------------------------------------------------------------
def generate_self_signed_cert(cert_file, key_file):
"""Erzeugt ein selbstsigniertes SSL-Zertifikat, falls keines vorhanden ist."""
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"),
x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "ionivation.com"),
x509.NameAttribute(NameOID.COMMON_NAME, "localhost.lan"),
])
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.now(timezone.utc))
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=365))
.add_extension(
x509.SubjectAlternativeName([x509.DNSName("localhost")]),
critical=False
)
.sign(key, hashes.SHA256())
)
with open(cert_file, "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))
with open(key_file, "wb") as f:
f.write(key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
def get_server_ip():
"""Bestimmt die lokale IP-Adresse, um sie z.B. für den QR-Code zu nutzen."""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
except Exception:
ip = "127.0.0.1"
finally:
s.close()
return ip
def create_https_server(port, handler_class=SecureHTTPRequestHandler):
"""Erzeugt ein HTTPS-Serverobjekt (aber startet ihn noch nicht)."""
if not os.path.exists(CERT_FILE) or not os.path.exists(KEY_FILE):
print("SSL-Zertifikat nicht gefunden. Erstelle selbstsigniertes Zertifikat...")
generate_self_signed_cert(CERT_FILE, KEY_FILE)
print("Selbstsigniertes SSL-Zertifikat erstellt.")
server_address = ('', port)
httpd = HTTPServer(server_address, handler_class)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
return httpd
# -------------------------------------------------------------------
# Startfunktionen (GUI / no-GUI)
# -------------------------------------------------------------------
def run_server_nogui(port):
httpd = create_https_server(port)
server_ip = get_server_ip()
try:
print(f"Starte HTTPS-Server auf https://{server_ip}:{port}")
print("Drücke STRG+C, um zu beenden.")
print("warte auf Verbindungen ... \n")
print(f"Öffne im Browser: https://{server_ip}:{port}")
print("Du musst Dich im gleichen Netzwerk befinden (Lan/ Wlan)")
httpd.serve_forever()
except KeyboardInterrupt:
# Nur eine kurze Meldung ausgeben und dann sauber herunterfahren
print("\nSTRG+C erkannt. Fahre Server herunter...")
except Exception as e:
print(f"Fehler aufgetreten: {e}")
logging.error("Serverfehler", exc_info=True)
finally:
httpd.server_close()
logging.shutdown()
print("Server wurde sauber beendet.")
def run_server_with_gui(port):
# Nur für QR-Code und GUI benötigt:
import qrcode
import webbrowser
from PIL import Image, ImageTk
import tkinter as tk
"""Startet den Server in einem Hintergrund-Thread und öffnet eine tkinter-GUI mit QR-Code."""
# 1) Erzeuge den Server (aber noch kein serve_forever).
httpd = create_https_server(port)
server_ip = get_server_ip()
url = f"https://{server_ip}:{port}"
# 2) Hintergrund-Thread starten
def server_thread():
try:
print(f"Starte HTTPS-Server auf {url}")
httpd.serve_forever()
except Exception as ex:
print(f"Server-Thread-Exception: {ex}")
finally:
httpd.server_close()
logging.shutdown()
t = threading.Thread(target=server_thread, daemon=True)
t.start()
# 3) tkinter-GUI aufbauen
root = tk.Tk()
root.title("pyUpload - Secure File Upload")
# Favicon setzen (nur unter Windows direkt mit .ico möglich)
try:
root.iconbitmap("favicon.ico")
except Exception as e:
print(f"Konnte das Icon nicht setzen: {e}")
# Labels erzeugen
labels = [
tk.Label(root, text="HTTPS-Upload-Server läuft!", font=("Arial", 14)),
tk.Label(root, text=f"IP-Adresse: {server_ip}", font=("Arial", 11)),
tk.Label(root, text=f"Port: {port}", font=("Arial", 11)),
tk.Label(root, text="Scanne den QR-Code:", font=("Arial", 11))
]
# Alle Labels packen und größte Breite ermitteln
max_width = 0
total_height = 20 # Grundhöhe als Puffer für Abstände
for label in labels:
label.pack(pady=5)
label.update_idletasks() # Breite und Höhe berechnen
max_width = max(max_width, label.winfo_reqwidth())
total_height += label.winfo_reqheight() + 10 # Höhe sammeln
# QR-Code generieren
url = f"https://{server_ip}:{port}"
qr = qrcode.QRCode(version=1, box_size=8, border=2)
qr.add_data(url)
qr.make(fit=True)
img_qr = qr.make_image(fill_color="black", back_color="white")
# QR-Code als Tkinter-Image einbinden
img_tk = ImageTk.PhotoImage(img_qr)
label_qr = tk.Label(root, image=img_tk)
label_qr.pack()
total_height += img_tk.height() + 20
# Copyright-Vermerk
label_copyright = tk.Label(root, text="Adam Skotarczak (C) 2025", font=("Arial", 9), fg="gray")
label_copyright.pack(pady=5)
total_height += label_copyright.winfo_reqheight() + 10
# Funktion für klickbaren Link
def open_browser(event):
webbrowser.open("https://www.ionivation.com/pyUpload")
# Klickbarer Link unter Copyright
link_label = tk.Label(root, text="Infos: www.ionivation.com/pyUpload", font=("Arial", 10), fg="blue", cursor="hand2")
link_label.pack()
link_label.bind("<Button-1>", open_browser)
total_height += link_label.winfo_reqheight() + 10
# Funktion zum Beenden
def on_quit():
root.destroy()
# Beenden-Button
btn_quit = tk.Button(root, text="Beenden", command=on_quit, font=("Arial", 10))
btn_quit.pack(pady=10)
total_height += btn_quit.winfo_reqheight() + 20
# Endgültige Fenstergröße setzen
root.geometry(f"{max_width + 40}x{total_height + 50}")
# 4) GUI-Loop starten
root.mainloop()
# -------------------------------------------------------------------
# Hauptprogramm mit CLI
# -------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="Secure file upload server with optional GUI/QR-Code.")
parser.add_argument("--port", "-p", type=int, default=4443, help="Port, auf dem der Server lauscht (Standard: 4443)")
parser.add_argument("--nogui", "-n", action="store_true", help="Ohne GUI & QR-Code im reinen CLI-Modus starten")
args = parser.parse_args()
print(f"Gestartet mit Port {args.port}, GUI: {not args.nogui}")
if args.nogui:
run_server_nogui(args.port)
else:
run_server_with_gui(args.port)
if __name__ == "__main__":
main()

3
dev/requirements.txt Normal file
View File

@ -0,0 +1,3 @@
cryptography==44.0.2
Pillow==11.1.0
qrcode==8.0

18
dev/start.bat Normal file
View File

@ -0,0 +1,18 @@
@echo off
setlocal
:: Prüfen, ob die virtuelle Umgebung existiert
if not exist venv (
echo Virtuelle Umgebung nicht gefunden! Bitte zuerst install.bat ausführen.
pause
exit /b
)
:: Aktivieren der virtuellen Umgebung
call venv\Scripts\activate
:: Starten des Upload-Servers
python pyUpload.py
:: Nach Beenden der Anwendung
deactivate

47
dev/success.html Normal file
View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="theme-color" content="#007bff">
<meta name="robots" content="noindex, nofollow">
<title>Upload Erfolgreich</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f4f4f4;
font-family: Arial, sans-serif;
}
.success-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
a {
display: inline-block;
margin-top: 15px;
padding: 10px 20px;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 5px;
}
a:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="success-container">
<h2>Datei erfolgreich hochgeladen!</h2>
<p>Ihre Datei wurde erfolgreich auf den Server übertragen.</p>
<a href="/">Neue Datei hochladen</a>
</div>
</body>
</html>

93
dev/template.html Normal file
View File

@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="theme-color" content="#007bff">
<meta name="robots" content="noindex, nofollow">
<title>File Upload</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f4f4f4;
font-family: Arial, sans-serif;
}
.upload-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
input[type="file"] {
display: none;
}
.custom-file-upload {
display: inline-block;
background-color: #007bff;
color: white;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
.custom-file-upload:hover {
background-color: #0056b3;
}
#file-name {
display: block;
margin-top: 10px;
font-size: 14px;
color: #555;
}
button {
background-color: #28a745;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
border-radius: 5px;
font-size: 16px;
margin-top: 10px;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
button:hover:not(:disabled) {
background-color: #218838;
}
</style>
</head>
<body>
<div class="upload-container">
<h2>Datei-Upload</h2>
<form enctype="multipart/form-data" method="post" onsubmit="disableButton()">
<label for="file-upload" class="custom-file-upload">Datei auswählen</label>
<input id="file-upload" type="file" name="file" multiple onchange="updateFileName()">
<span id="file-name">Keine Datei ausgewählt</span>
<button id="upload-button" type="submit">Hochladen</button>
</form>
</div>
<script>
function updateFileName() {
const input = document.getElementById("file-upload");
const fileNameDisplay = document.getElementById("file-name");
if (input.files.length > 0) {
fileNameDisplay.textContent = Array.from(input.files).map(file => file.name).join(", ");
} else {
fileNameDisplay.textContent = "Keine Datei ausgewählt";
}
}
function disableButton() {
document.getElementById("upload-button").disabled = true;
}
</script>
</body>
</html>

10
devPyside6-test/LICENSE Normal file
View File

@ -0,0 +1,10 @@
MIT License
Copyright (c) 2025 Adam Scotarczak (adam@skotarczak.net) - ionivation.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

93
devPyside6-test/README.md Normal file
View File

@ -0,0 +1,93 @@
## pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung
### Beschreibung
pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Es richtet sich an Privatnutzer, die eine schnelle Möglichkeit suchen, Dateien zwischen Geräten zu übertragen, sowie an Unternehmen oder Teams, die eine sichere Lösung für den internen Datenaustausch benötigen. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen.
Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.
Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.
### Features Die Vorteile von pyUpload auf einen Blick
- **Sichere Dateiübertragung per HTTPS** Alle Daten werden verschlüsselt übertragen.
- **Automatische Erstellung eines selbstsignierten SSL-Zertifikats** Keine zusätzliche Konfiguration notwendig.
- **Intuitive, webbasierte Benutzeroberfläche** Einfach zu bedienen, keine Installation erforderlich.
- **Strukturierte Speicherung** Dateien werden in client-spezifischen Verzeichnissen gespeichert.
- **Zentralisierte und client-spezifische Logging-Funktion** Detaillierte Nachverfolgung aller Uploads.
- **Flexible Nutzung mit oder ohne GUI** Start als Desktop-Anwendung oder reine Konsolen-Version möglich.
- **Schnelle Einrichtung** Download, Entpacken und sofort loslegen!
### Installationsanleitung So startest du pyUpload
Es gibt drei Möglichkeiten, pyUpload zu nutzen:
- **Manuelle Installation** in einer vorhandenen Python-Umgebung, in der alle notwendigen Bibliotheken manuell installiert werden.
- **Nutzung einer vorgefertigten, ausführbaren .exe (Windows) Version**, die mit pyinstaller kompiliert wurde.
- **Nutzung in einer virtuellen Python-Umgebung**, die automatisch durch `install.bat` eingerichtet wird. Anschließend kann das Programm mit `start.bat` gestartet werden.
#### 1. Manuelle Installation für Python-Nutzer
1. Stelle sicher, dass **Python 3** auf deinem System installiert ist.
2. Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
```sh
pip install -r requirements.txt
```
3. Starte den Server mit:
```sh
python pyUpload.py
```
4. Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
```sh
python pyUpload.py --nogui
```
#### 2. Nutzung der fertigen .exe Download-Version
Falls du keine Python-Installation benötigst, kannst du die vorgefertigte **ZIP-Version** von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.
1. Lade die neueste **pyUpload.zip** von der offiziellen Website herunter, inklusive virtueller Umgebung.
2. Entpacke die ZIP-Datei in einen beliebigen Ordner.
3. Starte die enthaltene `pyUpload.exe`.
4. Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die `pyUpload.exe` direkt in der Konsole mit `--nogui` gestartet werden:
```sh
pyUpload.exe --nogui
```
5. Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
```sh
pyUpload.exe --help
```
#### 3. Nutzung in virtueller Python-Umgebung
Lade die ZIP-Datei mit der virtuellen Installationsumgebung herunter und starte die `install.bat` durch Doppelklick. Es öffnet sich ein Konsolenfenster (CLI) und eine virtuelle Umgebung für pyUpload wird erstellt. Anschließend kann das Programm mit der `start.bat` gestartet werden. In der Grundeinstellung wird eine GUI mit QR-Code gestartet.
### Zugriff auf die Weboberfläche
- Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
```
https://<server-ip>:4443
```
- Falls die GUI-Version gestartet wurde, erscheint ein **QR-Code**, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.
### Datei-Upload leicht gemacht So funktioniert es
1. Öffne die **Weboberfläche** im Browser.
2. Wähle die gewünschte **Datei aus** und klicke auf **„Hochladen“**.
3. Nach erfolgreichem Upload erscheint eine **Bestätigungsseite**, die den Abschluss der Übertragung bestätigt.
### SSL-Zertifikatswarnung in Browsern umgehen
Da pyUpload ein **selbstsigniertes SSL-Zertifikat** nutzt, wird es beim ersten Zugriff zu einer Warnung des Browsers kommen. Alternativ kann ein eigenes SSL-Zertifikat hinterlegt werden, indem die Zertifikats- und Schlüsseldateien `cert.pem` und `key.pem` durch eigene, signierte Zertifikate ersetzt werden. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:
- In den meisten Browsern gibt es eine Option wie **„Erweitert“** oder **„Trotzdem fortfahren“**, um die Warnung zu übergehen.
- Alternativ kann das Zertifikat **manuell importiert und als vertrauenswürdig markiert** werden, um künftige Warnmeldungen zu vermeiden.
### Logging und Fehlerbehandlung Transparenz und Kontrolle
- Alle **Uploads und Anfragen** werden in **zentralen sowie client-spezifischen Logdateien** gespeichert. Diese befinden sich im `logs/`-Verzeichnis.
- Falls während der Nutzung von pyUpload **Probleme auftreten**, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.
### Lizenz und Autor
- **Entwickelt von Adam Skotarczak (C) 2025**.

BIN
devPyside6-test/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@ -0,0 +1,54 @@
@echo off
setlocal
:: Prüfen, ob Python installiert ist
where python >nul 2>nul
if %ERRORLEVEL% NEQ 0 (
echo Fehler: Python ist nicht installiert oder nicht im PATH!
echo Bitte installiere Python und starte die Installation erneut.
pause
exit /b 1
)
:: Python-Version prüfen (Mindestversion 3.8)
for /f "tokens=2 delims= " %%v in ('python --version 2^>^&1') do set PYTHON_VERSION=%%v
for /f "tokens=1,2 delims=." %%a in ("%PYTHON_VERSION%") do (
if %%a LSS 3 (
echo Fehler: Python 3.8 oder höher ist erforderlich!
pause
exit /b 1
)
if %%a==3 if %%b LSS 8 (
echo Fehler: Python 3.8 oder höher ist erforderlich!
pause
exit /b 1
)
)
:: Virtuelle Umgebung erstellen, falls sie nicht existiert
if not exist venv (
echo Erstelle virtuelle Server-Umgebung ...
python -m venv --copies venv
if %ERRORLEVEL% NEQ 0 (
echo Fehler beim Erstellen der virtuellen Umgebung!
pause
exit /b 2
)
)
:: Aktivieren der virtuellen Umgebung
call venv\Scripts\activate
:: Installieren der Abhängigkeiten
echo Installiere Abhaengigkeiten aus dem Internet ...
pip install --no-warn-script-location --disable-pip-version-check -r requirements.txt
if %ERRORLEVEL% NEQ 0 (
echo Fehler beim Installieren der Abhaengigkeiten!
pause
exit /b 3
)
:: Erfolgsmeldung
echo.
echo Installation abgeschlossen.
timeout /t 3 >nul & exit /b 0

View File

@ -0,0 +1,16 @@
@echo off
setlocal
:: Prüfen, ob die virtuelle Umgebung existiert
if not exist venv (
echo Fehler: Die virtuelle Umgebung existiert nicht!
echo Führe zuerst "install.bat" aus.
pause
exit /b
)
:: Aktivieren der virtuellen Umgebung
call venv\Scripts\activate
:: Starte den Upload-Server
python pyUpload.py

118
devPyside6-test/pyUpload.py Normal file
View File

@ -0,0 +1,118 @@
import sys
import os
import threading
import socket
import ssl
import qrcode
import webbrowser
from http.server import HTTPServer, SimpleHTTPRequestHandler
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
from PySide6.QtGui import QPixmap
from PySide6.QtCore import Qt
from PIL import ImageQt
# --- HTTPS Server Klasse ---
class SecureHTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(b"<html><body><h1>pyUpload Server</h1><p>Upload-Seite</p></body></html>")
else:
self.send_error(404)
def get_local_ip():
"""Ermittelt die lokale IP-Adresse"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
except:
return "127.0.0.1"
def run_server(port):
"""Startet den HTTPS-Server in einem eigenen Thread"""
server_address = ("", port)
httpd = HTTPServer(server_address, SecureHTTPRequestHandler)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile="cert.pem", keyfile="key.pem")
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
print(f"Server läuft auf https://{get_local_ip()}:{port}")
httpd.serve_forever()
# --- PySide6 GUI ---
class UploadGUI(QWidget):
def __init__(self, server_ip, port):
super().__init__()
self.setWindowTitle("pyUpload - Secure File Upload")
self.setGeometry(100, 100, 400, 500)
# Info Label
label_info = QLabel("HTTPS-Upload-Server läuft!", self)
label_info.setAlignment(Qt.AlignCenter)
label_ip = QLabel(f"IP-Adresse: {server_ip}", self)
label_ip.setAlignment(Qt.AlignCenter)
label_port = QLabel(f"Port: {port}", self)
label_port.setAlignment(Qt.AlignCenter)
label_hint = QLabel("Scanne den QR-Code:", self)
label_hint.setAlignment(Qt.AlignCenter)
# QR-Code generieren
url = f"https://{server_ip}:{port}"
qr = qrcode.make(url)
qr = qr.convert("RGB") # FIX: Konvertiere das Bild in ein gültiges Format für ImageQt
qr_img = ImageQt.ImageQt(qr)
pixmap = QPixmap.fromImage(qr_img)
qr_label = QLabel(self)
qr_label.setPixmap(pixmap)
qr_label.setAlignment(Qt.AlignCenter)
# Link Label (klickbar)
link_label = QLabel(f'<a href="{url}">{url}</a>', self)
link_label.setOpenExternalLinks(True)
link_label.setAlignment(Qt.AlignCenter)
# Beenden Button
btn_quit = QPushButton("Beenden", self)
btn_quit.clicked.connect(self.close)
# Layout setzen
layout = QVBoxLayout()
layout.addWidget(label_info)
layout.addWidget(label_ip)
layout.addWidget(label_port)
layout.addWidget(label_hint)
layout.addWidget(qr_label)
layout.addWidget(link_label)
layout.addWidget(btn_quit)
self.setLayout(layout)
# --- Start der Anwendung ---
if __name__ == "__main__":
port = 4443
server_ip = get_local_ip()
# HTTPS-Server in eigenem Thread starten
server_thread = threading.Thread(target=run_server, args=(port,), daemon=True)
server_thread.start()
# Qt-Anwendung starten
app = QApplication(sys.argv)
window = UploadGUI(server_ip, port)
window.show()
sys.exit(app.exec())

View File

@ -0,0 +1,3 @@
PySide6
qrcode
pillow

18
devPyside6-test/start.bat Normal file
View File

@ -0,0 +1,18 @@
@echo off
setlocal
:: Prüfen, ob die virtuelle Umgebung existiert
if not exist venv (
echo Virtuelle Umgebung nicht gefunden! Bitte zuerst install.bat ausführen.
pause
exit /b
)
:: Aktivieren der virtuellen Umgebung
call venv\Scripts\activate
:: Starten des Upload-Servers
python pyUpload.py
:: Nach Beenden der Anwendung
deactivate

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="theme-color" content="#007bff">
<meta name="robots" content="noindex, nofollow">
<title>Upload Erfolgreich</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f4f4f4;
font-family: Arial, sans-serif;
}
.success-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
a {
display: inline-block;
margin-top: 15px;
padding: 10px 20px;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 5px;
}
a:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="success-container">
<h2>Datei erfolgreich hochgeladen!</h2>
<p>Ihre Datei wurde erfolgreich auf den Server übertragen.</p>
<a href="/">Neue Datei hochladen</a>
</div>
</body>
</html>

View File

@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="theme-color" content="#007bff">
<meta name="robots" content="noindex, nofollow">
<title>File Upload</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f4f4f4;
font-family: Arial, sans-serif;
}
.upload-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
input[type="file"] {
display: none;
}
.custom-file-upload {
display: inline-block;
background-color: #007bff;
color: white;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
.custom-file-upload:hover {
background-color: #0056b3;
}
#file-name {
display: block;
margin-top: 10px;
font-size: 14px;
color: #555;
}
button {
background-color: #28a745;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
border-radius: 5px;
font-size: 16px;
margin-top: 10px;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
button:hover:not(:disabled) {
background-color: #218838;
}
</style>
</head>
<body>
<div class="upload-container">
<h2>Datei-Upload</h2>
<form enctype="multipart/form-data" method="post" onsubmit="disableButton()">
<label for="file-upload" class="custom-file-upload">Datei auswählen</label>
<input id="file-upload" type="file" name="file" multiple onchange="updateFileName()">
<span id="file-name">Keine Datei ausgewählt</span>
<button id="upload-button" type="submit">Hochladen</button>
</form>
</div>
<script>
function updateFileName() {
const input = document.getElementById("file-upload");
const fileNameDisplay = document.getElementById("file-name");
if (input.files.length > 0) {
fileNameDisplay.textContent = Array.from(input.files).map(file => file.name).join(", ");
} else {
fileNameDisplay.textContent = "Keine Datei ausgewählt";
}
}
function disableButton() {
document.getElementById("upload-button").disabled = true;
}
</script>
</body>
</html>

93
info.md Normal file
View File

@ -0,0 +1,93 @@
## pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung
### Beschreibung
pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen.
Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.
Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.
### Download
- **Portabel für Windows als .zip**
[download id="2323"]
> Aktuell ist der Download der portablen und Compilierten Version gesperrt da es von diversen Virenscannern als Bedrohung eingestuft wird. Bei Interesse ist das Programm aktuell nur auf Anfrage per eMail erhältlich. In Kürze erfolgt eine Veröffentlichung inklusive Code auf GitHub.
### Features Die Vorteile von pyUpload auf einen Blick
- **Sichere Dateiübertragung per HTTPS** Alle Daten werden verschlüsselt übertragen.
- **Automatische Erstellung eines selbstsignierten SSL-Zertifikats** Keine zusätzliche Konfiguration notwendig.
- **Intuitive, webbasierte Benutzeroberfläche** Einfach zu bedienen, keine Installation erforderlich.
- **Strukturierte Speicherung** Dateien werden in client-spezifischen Verzeichnissen gespeichert.
- **Zentralisierte und client-spezifische Logging-Funktion** Detaillierte Nachverfolgung aller Uploads.
- **Flexible Nutzung mit oder ohne GUI** Start als Desktop-Anwendung oder reine Konsolen-Version möglich.
- **Schnelle Einrichtung** Download, Entpacken und sofort loslegen!
### Installationsanleitung So startest du pyUpload
Es gibt zwei Möglichkeiten, pyUpload zu nutzen: Entweder die manuelle Installation oder die Nutzung einer vorgefertigten, ausführbaren Version.
#### 1. Nutzung der fertigen Download-Version
Falls du keine Python-Installation benötigst, kannst du die vorgefertigte **ZIP-Version** von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.
1. Lade die neueste **pyUpload.zip** von der offiziellen Website herunter.
2. Entpacke die ZIP-Datei in einen beliebigen Ordner.
3. Starte die enthaltene `pyUpload.exe`.
4. Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die `pyUpload.exe` direkt in der Konsole mit `--nogui` gestartet werden:
```sh
pyUpload.exe --nogui
```
5. Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
```sh
pyUpload.exe --help
```
#### 2. Manuelle Installation für Python-Nutzer
1. Stelle sicher, dass **Python 3** auf deinem System installiert ist.
2. Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
```sh
pip install -r requirements.txt
```
3. Starte den Server mit:
```sh
python pyUpload.py
```
4. Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
```sh
python pyUpload.py --nogui
```
### Zugriff auf die Weboberfläche
- Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
```
https://<server-ip>:4443
```
- Falls die GUI-Version gestartet wurde, erscheint ein **QR-Code**, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.
### Datei-Upload leicht gemacht So funktioniert es
1. Öffne die **Weboberfläche** im Browser.
2. Wähle die gewünschte **Datei aus** und klicke auf **„Hochladen“**.
3. Nach erfolgreichem Upload erscheint eine **Bestätigungsseite**, die den Abschluss der Übertragung bestätigt.
### SSL-Zertifikatswarnung in Browsern umgehen
Da pyUpload ein **selbstsigniertes SSL-Zertifikat** nutzt, kann es beim ersten Zugriff zu einer Warnung des Browsers kommen. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:
- In den meisten Browsern gibt es eine Option wie **„Erweitert“** oder **„Trotzdem fortfahren“**, um die Warnung zu übergehen.
- Alternativ kann das Zertifikat **manuell importiert und als vertrauenswürdig markiert** werden, um künftige Warnmeldungen zu vermeiden.
### Logging und Fehlerbehandlung Transparenz und Kontrolle
- Alle **Uploads und Anfragen** werden in **zentralen sowie client-spezifischen Logdateien** gespeichert. Diese befinden sich im `logs/`-Verzeichnis.
- Falls während der Nutzung von pyUpload **Probleme auftreten**, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.
### Lizenz und Autor
- **Entwickelt von Adam Skotarczak (C) 2025**.

84
innoSetup.iss Normal file
View File

@ -0,0 +1,84 @@
; Define AppVersion as a constant
#define AppVersion "0.1.0"
#define BasePath ".\dev"
; Source: "{#BasePath}\*"; DestDir: "{app}"; Flags: ignoreversion;
[Setup]
AppId={{832B3E5D-14BC-4823-A911-00C9B79AD040}
AppName=pyUpload
AppVersion={#AppVersion}
AppVerName=pyUpload {#AppVersion} (win)
AppPublisher=Adam Skotarczak (ionivation.com)
AppPublisherURL=https://www.ionivation.com/pyupload/
AppSupportURL=https://www.ionivation.com/pyupload/
AppUpdatesURL=https://www.ionivation.com/pyupload/
DefaultDirName={userappdata}\pyUpload
DisableProgramGroupPage=yes
LicenseFile={#BasePath}\LICENSE
PrivilegesRequired=lowest
;PrivilegesRequiredOverridesAllowed=dialog
OutputBaseFilename=pyUpload-Setup-{#AppVersion}
SolidCompression=yes
WizardStyle=modern
SetupIconFile={#BasePath}\favicon.ico
DisableDirPage=yes
[Languages]
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "{#BasePath}\pyUpload.bat"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#BasePath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Dirs]
Name: "{app}\upload"; Flags: uninsalwaysuninstall
[Icons]
Name: "{autoprograms}\pyUpload"; Filename: "{app}\pyUpload.bat"; IconFilename: "{app}\favicon.ico";
Name: "{autodesktop}\pyUpload"; Filename: "{app}\pyUpload.bat"; IconFilename: "{app}\favicon.ico"; Tasks: desktopicon
Name: "{userdesktop}\pyUpload-Uploads"; Filename: "{app}\upload"; IconFilename: "{app}\favicon.ico"; Tasks: desktopicon
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Run]
Filename: "{app}\install.bat"; Parameters: ""; WorkingDir: "{app}\"; Flags: waituntilterminated
;Flags: runhidden
Filename: "{app}\pyUpload.bat"; Description: "{cm:LaunchProgram,pyUpload}"; Flags: shellexec postinstall skipifsilent
[Code]
function IsPythonInstalled(): Boolean;
var
PythonPath: String;
ResultCode: Integer;
begin
// Prüfe Registry für alle möglichen Python-Versionen (dynamisch)
if RegQueryStringValue(HKLM, 'SOFTWARE\Python\PythonCore', '', PythonPath) or
RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Python\PythonCore', '', PythonPath) then
begin
Result := True;
Exit;
end;
// Prüfe mit python --version, falls kein Registry-Eintrag gefunden wurde
Result := Exec('cmd.exe', '/c python --version', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
function InitializeSetup(): Boolean;
begin
if not IsPythonInstalled() then
begin
MsgBox('Python ist nicht installiert oder nicht erreichbar! Bitte installiere Python.', mbError, MB_OK);
Result := False; // Installation abbrechen
end
else
begin
Result := True;
end;
end;