Privates MODX und LINUX BLOG, User Registrierung ist deaktiviert! Fragen oder Tipps? Bitte per Matrix: @jolichter:tchncs.de
kate ~/.local/share/plasma/plasmoids/org.kde.thermalMonitor/contents/ui/main.qml
kate ~/.bash_profile
diese 2 Zeilen hinzufügen: QT_LOGGING_RULES='*.debug=false'
export QT_LOGGING_RULES
kate /etc/samba/smb.conf
und fügt dort diese Zeile ein:client min protocol = NT1
chmod +x ./*.AppImage
rm -rf ~/.config/'Jitsi Meet'
sudo systemctl disable systemd-resolved.service
sudo systemctl stop systemd-resolved.service
sudo systemctl enable avahi-daemon.service
sudo systemctl start avahi-daemon.service
yay -Syyuu && sudo paccache -rk2 && sudo pacman -Qdtq
sudo pacman -S python python-pycups
wget https://raw.githubusercontent.com/tjfontaine/airprint-generate/master/airprint-generate.py
sudo python airprint-generate.py -d /etc/avahi/services
<?xml version="1.0" ?>
<!DOCTYPE service-group SYSTEM 'avahi-service.dtd'>
<service-group>
<name replace-wildcards="yes">AirPrint Hewlett-Packard-HP-Color-LaserJet-CP2025dn @ %h</name>
<service>
<type>_ipp._tcp</type>
<subtype>_universal._sub._ipp._tcp</subtype>
<port>631</port>
<txt-record>txtvers=1</txt-record>
<txt-record>qtotal=1</txt-record>
<txt-record>Transparent=T</txt-record>
<txt-record>URF=none</txt-record>
<txt-record>rp=printers/Hewlett-Packard-HP-Color-LaserJet-CP2025dn</txt-record>
<txt-record>note=Hewlett-Packard-HP-Color-LaserJet-CP2025dn</txt-record>
<txt-record>product=(GPL Ghostscript)</txt-record>
<txt-record>printer-state=3</txt-record>
<txt-record>printer-type=0x82905c</txt-record>
<txt-record>pdl=application/octet-stream,application/pdf,application/postscript,application/vnd.cups-raster,image/gif,image/jpeg,image/png,image/tiff,image/urf,text/html,text/plain,application/vnd.adobe-reader-postscript,application/vnd.cups-command</txt-record>
</service>
</service-group>
rm airprint-generate.py
./bin/master-pdf-editor/masterpdfeditor4.sh
systemctl list-unit-files --state=enabled --no-pager
sudo fdisk -l
(bei mir ist das "/dev/sde1")sudo umount /dev/sde1
sudo dd bs=4M if=~/Downloads/manjaro-kde-21.2.0-minimal-211220-linux510.iso of=/dev/sde status=progress oflag=sync
sudo pacman -S kded pamac-tray-icon-plasma
pamac upgrade -a
Sicherer Weg um alte Paket-Cache-Dateien zu entfernen, mit Ausnahme der letzten zwei Paketversionen:pamac clean --keep 2
in einer Zeile:pamac upgrade -a && sudo pamac clean --keep 2
Vorbereitung...
Synchronisiere Paketdatenbanken...
Kann Datenbank nicht sperren
Fehler beim Synchronisieren der Datenbanken
Es gibt nichts zu tun.
Vorgang erfolgreich abgeschlossen.
Lösung:sudo rm /var/tmp/pamac/dbs/db.lck
kate /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT=2
GRUB_TIMEOUT_STYLE=menu
GRUB_DISTRIBUTOR="Manjaro"
GRUB_CMDLINE_LINUX_DEFAULT="noplymouth resume=UUID=xxxxxxxxxxxxxxx udev.log_priority=3"
GRUB_CMDLINE_LINUX=""
GRUB_SAVEDEFAULT="false"
sudo update-grub
sudo truncate -s 0 /swapfile
sudo chattr +C /swapfile
sudo btrfs property set /swapfile compression none
sudo fallocate -l 8G /swapfile
sudo mkswap /swapfile
sudo chmod 600 /swapfile
sudo swapon /swapfile
sudo bash -c "echo /swapfile none swap defaults 0 0 >> /etc/fstab"
Eintrag in der fstab kontrollieren:kate /etc/fstab
PC neu starten und prüfen:swapon -s
Tipp: Das KDE-Infozentrum zeigt die Speicherbelegung und viele andere Information zum System grafisch an.sudo swapoff /swapfile
sudo rm -f /swapfile
Eintrag aus der fstab entfernen oder ausklammern:kate /etc/fstab
PC neu starten.sudo pacman-mirrors --country Germany,France,Austria && sudo pacman -Syyuu && sudo paccache -rk2
(das synchronisiert die Spiegelserver aus 3 Ländern, Update und aufräumen in nur einer Zeile)sudo pacman -Syyuu && sudo paccache -rk2
wenn alles fertig ist wieder raus aus der Shell mit ALT+STRG+F7 oder besser den PC neu starten, besonders nach einem Kernel Update:sudo reboot
sudo pacman -Scc
(alle Pakete im Pacman Cache werden vollständig entfernt - die 2 Fragen mit "j" bestätigen)lsb_release -a
oderneofetch
inxi -Fz
(der Schalter -z blendet persönliche Infos wie z.B. MAC oder IP aus, also Forum geeignet)inxi -v8
per KDE-Infozentrumsudo pacman -Syyuu
wenn Pakete aus dem AUR installiert wurden (benötigt yay, siehe Punkt 10 ):yay -Syyuu
Manjaro sauber halten (lässt zwei Versionen der Pakete für den Fall, dass ein Downgrade durchgeführt werden muss):sudo paccache -rk2
(siehe auch Automatische Cache-Wartung)sudo pacman -Syyuu && sudo paccache -rk2 && sudo pacman -Qdtq
yay -Syyuu && sudo paccache -rk2 && sudo pacman -Qdtq
("Failed to parse JSON" erscheint wenn kein AUR genutzt wird)sudo pacman -Rsn $(pacman -Qdtq)
sudo pacman -Scc
(alle Pakete im Pacman Cache werden vollständig entfernt - die 2 Fragen mit "j" bestätigen)sudo pacman-mirrors --country Germany,France,Austria && sudo pacman -Syyuu
(Mirrorliste wrd hier gespeichert: /etc/pacman.d/mirrorlist)systemctl list-timers
(oder Systemeinstellungen -> Systemverwaltung -> Systemd -> Timers)sudo systemctl enable pamac-cleancache.timer
sudo systemctl start pamac-cleancache.timer
systemctl | grep pkgfile
Wenn ja, können wir nach allem suchen, was sich auf pkgfile verlässt:pacman -Qi pkgfile | grep Required
Wenn niemand die pkgfile Datenbank benötigt, kann Systemd Service pkgfile-update.timer deaktiviert werden (oder nutzt diesen Workaround):sudo systemctl disable pkgfile-update.timer
(wieder aktivieren: sudo systemctl enable pkgfile-update.timer)sudo pacman -Rns yakuake
mkdir ~/.config/firejail/
dann mit einem Editor öffnen:kate ~/.config/firejail/firefox.local
und folgendes Eintragen:# Quellen:
# /etc/firejail/firefox.profile
# /etc/firejail/firefox-common.profile
#
# ~/.config/firejail/firefox.local
#
#
# Add the next lines to your firefox.local for plasma-browser-integration.
dbus-user.own org.mpris.MediaPlayer2.plasma-browser-integration
dbus-user.talk org.kde.JobViewServer
dbus-user.talk org.kde.kuiserver
#
# Add the next line to your firefox-common.local to allow access to common programs/addons/plugins.
include firefox-common-addons.profile
sudo pacman -S palemoon
sudo firecfg
Rückgängig machen:sudo firecfg --clean
sudo sed -i 's/# browser-allow-drm no/browser-allow-drm yes/' /etc/firejail/firejail.config
pamac install brave-browser
Mehr ist nicht notwendig, Brave Shields und Tor ist enthalten. Ich nutze dazu nur die Erweiterung Tabs to the Front v2 um neue Tabs sofort und nicht mehr im Hintergrund zu öffnen.sudo pacman -S --needed yay base-devel hunspell-de manjaro-printer system-config-printer cups-pdf libimobiledevice backintime-qt kolourpaint lame fdkaac audacity easytag mencoder frei0r-plugins devede vlc elisa gimp kfind kdf kwave mediainfo handbrake gthumb firejail pingus kmahjongg aisleriot libreoffice zip unzip unrar doublecmd plasma-vault cryfs encfs gocryptfs imagemagick dconf-editor geany htop meld kdialog imagewriter mintstick kompare ncdu gparted net-tools arp-scan dnsutils cifs-utils sqlite
sudo pacman -S --needed qt6ct qt6-wayland qt6-translations
Nachdem du die notwendigen Pakete installiert hast, kannst du die Qt6-Einstellungen (qt6ct) anpassen. Achte darauf, die passende Konfigurationsvariable für Qt6 festzulegen, und füge diese Zeile ans Ende deiner ".bashrc" oder ".zshrc" Datei hinzu (je nachdem, welche du verwendest), damit sie bei jedem Start deiner Shell automatisch geladen wird:# Set the Qt6 platform theme
export QT_QPA_PLATFORMTHEME=qt6ct
Lade anschließend die ".bashrc" oder ".zshrc" Datei neu, damit die Änderungen wirksam werden. Das kannst du tun, indem du den folgenden Befehl in deinem Terminal eingibst:source ~/.zshrc
odersource ~/.bashrc
Nun sollte `qt6ct` korrekt konfiguriert sein und das Erscheinungsbild von Qt6-Anwendungen anpassen. Überprüfe, ob die Umgebungsvariable korrekt gesetzt ist:echo $QT_QPA_PLATFORMTHEME
sudo pacman -S timeshift timeshift-autosnap-manjaro grub-btrfs
sudo update-grub
timeshift deinstallieren:sudo pacman -Rsn timeshift timeshift-autosnap-manjaro grub-btrfs
sudo update-grub
sudo pacman -S solaar
sudo pacman -S steam
Cool, der Weltraumsimulator Universe Sandbox rennt damit unter Manjaro, hat jedoch eine hohe Systemanforderungen! Demos z.B. auf YouTube.sudo pacman -S ifuse
sudo pacman -S samba smbclient kdenetwork-filesharing manjaro-settings-samba kio-fuse
Ein Samba-Passwort für euer Benutzerkonto erstellen: 'sudo smbpasswd -a $USER' (-a = add user | -x = delete user)sudo pacman -Rsn samba smbclient kdenetwork-filesharing manjaro-settings-samba kio-fuse
$ testparm
Load smb config files from /etc/samba/smb.conf
Loaded services file OK.
Weak crypto is allowed
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions
yay -S ttf-ms-fonts
(von Microsoft freigegebenen Kern-Schriftarten für Windows)sudo pacman -S base-devel
rm -r ~/.local/share/kactivitymanagerd
kactivitymanagerd stop; killall plasmashell; kactivitymanagerd start; plasmashell &
Das löscht alle Aktivitäten und Favoriten! Dann die Favoriten neu anlegen.yay -S babl-git gegl-git gimp-plugin-registry
sudo pacman -S k3b dvd+rw-tools emovix cdrdao transcode cdparanoia sox
Benutzer der Gruppe optical hinzufügen:sudo gpasswd -a $USER optical
PC neu starten, im K3b Programm die Einstellungen prüfen (K3b einrichten...), z.B. Temporärer Ordner habe ich auf "/tmp" festgelegt.sudo pacman -S avidemux-qt
sudo pacman -S kdenlive
(Sollte es noch nicht geschehen sein, installiere auch qt6ct. Da Kdenlive nun auf Qt6 basiert, wird dies benötigt, damit z.B. der Color Picker funktioniert)sudo systemctl enable --now cups.service
PC neu starten oder manuell die Druckfunktion starten:sudo systemctl start cups.service
(cups deaktivieren mit disable)sudo sh -c "echo 'A4' > /etc/papersize"
sudo systemctl disable --now cups.service
sudo pacman -Rsn manjaro-printer
pacman -Qi cups
sudo pacman -Rsn cups cups-pdf
sudo systemctl disable --now org.cups.cupsd.socket
sudo systemctl disable --now org.cups.cupsd.service
sudo systemctl disable --now org.cups.cupsd.path
sudo systemctl enable --now cups.service
sudo systemctl enable --now cups.socket
sudo systemctl enable --now cups.path
(der Dienst wurde vor einiger Zeit in nur cups umgemannt)sudo systemctl status cups.service
sudo pacman -S yay kontact kmail kaddressbook korganizer knotes akregator aspell-de kgpg
sudo pacman -S evolution gnome-keyring seahorse gnupg kgpg
(anstatt kgpg könnt ihr auch gpa installieren)kgpg -k
die Warnung "unsafe permissions on homedir ~/.gnupg" oder ähnlich erscheint, die Zugriffsrechte der Ordner auf 700 setzen:sudo find ~/.gnupg \( -type d -exec chmod 700 {} + \);
kate /etc/pam.d/sddm
Habe diese 2 Zeilen ans Ende der jeweiligen Sektion eingefügt:auth optional pam_gnome_keyring.so
session optional pam_gnome_keyring.so auto_start
evolution --force-shutdown
rm -rf ~/.local/share/evolution
rm -rf ~/.cache/evolution
rm -rf ~/.config/evolution
dconf reset -f /org/gnome/evolution/
dconf reset -f /org/gnome/evolution-data-server
sudo pacman -Rns evolution
sudo pacman -S bauh flatpak
sudo pacman -S yay pulseaudio pulseaudio-alsa
yay -S librm libcapi
yay -S roger-router
Start mitroger
lpadmin -p Roger-Router-Fax -m drv:///sample.drv/generic.ppd -v socket://localhost:9100/ -E -o PageSize=A4
rm ~/.local/share/rm/[deinProfilname]/journal.csv
dconf reset -f /org/tabos/
sudo pacman -S flatpak
Roger-Router über flathub installieren:flatpak install flathub org.tabos.roger
flatpak install flathub org.freedesktop.Platform/x86_64/19.08
flatpak update
flatpak run org.tabos.roger
rm ~/.var/app/org.tabos.roger/data/rm/[deinProfilname]/journal.csv
kate ~/.var/app/org.tabos.roger/config/glib-2.0/settings/keyfile
flatpak update
flatpak list
flatpak uninstall org.tabos.roger
flatpak uninstall --unused
rm -r ~/.var/app/org.tabos.roger/
~/.var/app/org.tabos.roger/config/glib-2.0/settings/
~/.var/app/org.tabos.roger/data/rm/[deinProfilName]/
sudo pacman -S gambas3 rpm-tools base-devel
debhelper installieren (nur nötig wenn Debian Installationspakete erstellt werden sollen):yay -S debhelper
Wenn ein Gambas Programm unter Arch installiert wird, werden benötigte Pakete wie z.B. der Runtime-Interpreter (gambas3-runtime) automatisch mit installiert (IDE nicht notwendig).kate /etc/profile.d/editor.sh
und diese 2 Zeilen eintragen:export EDITOR=/usr/bin/kate
export VISUAL=/usr/bin/kate
(test mit: echo $EDITOR)sudo pacman -S python python-pip tk pycharm-community-edition
pip check
Dadurch wird festgestellt, ob es irgendwelche Inkonsistenzen in installierten Paketen gibt.pip list
pip list --user
sudo pacman -Syyuu
python -c "from PyQt5.QtCore import QT_VERSION_STR; print(QT_VERSION_STR)"
sudo pacman -S python-pyqt6
Überprüfe die PyQt6 Installation:python -c "from PyQt6.QtCore import PYQT_VERSION_STR; print(PYQT_VERSION_STR)"
UUID=xxxx-xxxx /boot/efi vfat umask=0077 0 2
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / btrfs subvol=/@,defaults,noatime,ssd 0 1
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /home btrfs defaults,noatime,ssd 0 2
lsblk --discard
DISC-GRAN und DISC-MAX Werte ungleich Null zeigen die TRIM-Unterstützung an. Manuelles trimmen:sudo fstrim -a -v
sudo systemctl enable fstrim.timer
(kann mit 'disable' wieder deaktiviert werden)systemctl cat fstrim.timer
Logdatei einsehen:journalctl | grep fstrim
sudo systemctl status tmp.mount
kate /etc/fstab
# dynamic RAMDisk
tmpfs /tmp tmpfs defaults,noatime,size=50%,mode=1777 0 0
tmpfs /var/tmp tmpfs defaults,noatime,size=5%,mode=0777 0 0
(noatime = Dateizugriffszeiten nicht speichern und die /tmp Verzeichnisse benutzen ein Sticky Bit, daher das "mode=1777")cat /run/systemd/generator/tmp.mount
df -h
tmpfs 794M 1,2M 792M 1% /tmp
tmpfs 199M 0 199M 0% /var/tmp
(ohne SWAP-Speicher könnte es trotz genug Arbeitsspeicher zu Problemen kommen)sudo pacman -S nvme-cli
listen:sudo nvme list
Infos lesen:sudo nvme --smart-log /dev/nvme0n1
systemd-analyze blame
(mit Q beenden)systemctl disable ModemManager.service
systemctl disable NetworkManager-wait-online.service
Sollte dann etwas nicht mehr funktionieren, lässt sich ein service mit enable einfach wieder aktivieren.sudo pacman -Syyuu
sudo mkinitcpio -P
(mkinitcpio ist ein Programm zur initramfs-Erstellung)su
manjaro-chroot -a
pacman-mirrors --country Germany,France,Austria && pacman -Syu grub
update-grub
exit
dann den PC ohne USB-Stick neu starten.systemctl --failed
grep -i upgraded /var/log/pacman.log
journalctl -p err --since yesterday
(kernel: proc: Bad value for 'hidepid', kann ignoriert werden, siehe github systemd 16896)journalctl -b -1 | grep -A999 "System is rebooting.\|System is powering down."
journalctl --since "20:00:40" --until "20:01:00"
sudo journalctl --rotate
sudo journalctl --vacuum-time=1s
Der erste Befehl dreht die Protokoll-Dateien und erstellt neue. Der zweite Befehl löscht alle Protokolldaten, die älter als eine Sekunde sind. Du kannst die Zeitspanne nach Bedarf anpassen.ncdu
uname -r
(Ausgabe z.B. "6.6.30-2-MANJARO")sudo pacman -S virtualbox
und wählt den eben entsprechenden Kernel aus, in dem Fall "linux66-virtualbox-host-modules"sudo modprobe vboxdrv
sudo gpasswd -a $USER vboxusers
(entfernen mit: sudo gpasswd -d $USER vboxusers)VBoxManage list extpacks
wenn vorhanden altes Erweiterungspaket löschen, z.B. (Name evtl. anpassen, siehe "Pack no."):sudo VBoxManage extpack uninstall "Oracle VM VirtualBox Extension Pack"
dann das neue Erweiterungspaket installieren, z.B.:sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-7.0.18.vbox-extpack
oder in einem Befehl wenn die Datei im Ordner Downloads ist:sudo VBoxManage extpack install --replace ~/Downloads/Oracle_VM_VirtualBox_Extension_Pack-7.0.18.vbox-extpack
GRUB_CMDLINE_LINUX="ibt=off"
sudo pacman -S mariadb php php-apache phpmyadmin php-gd php-imagick
sudo ls -all /var/lib/mysql/
dann:sudo chattr +C /var/lib/mysql
sudo systemctl stop mysqld
mv /var/lib/mysql /var/lib/mysql_old
mkdir /var/lib/mysql
chattr +C /var/lib/mysql
cp -a /var/lib/mysql_old/* /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
sudo systemctl restart mysqld
wenn das funktioniert hat:rm -rf /var/lib/mysql_old
sudo mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
sudo systemctl start mysqld
sudo systemctl enable mysqld
MariaDB Status prüfen:systemctl status mysqld
(Abbruch mit Strg & C )sudo mysql
MariaDB [(none)]> USE mysql;
MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MeinPASSWORT';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit
mysql_secure_installation
(Abbruch mit Strg & C )sudo mysqld_safe --skip-grant-tables &
sudo mysql -u root
dann:MariaDB [(none)]> use mysql;
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MeinPASSWORT';
MariaDB [(none)]> exit
Prüfen, reparieren und optimieren der Tabellen:sudo killall -9 mysqld
sudo mysqlcheck -A --auto-repair -u root -p
sudo mysqlcheck -A --auto-repair -f -o -u root -p
mysql_secure_installation
Als erstes werdet ihr nach den MySQL root Passwort gefragt.sudo su
systemctl restart mariadb.service && mariadb-upgrade -u root -p
exit
(Wichtig, obigen Befehl als root ausführen, sonst gibt es diesen Fehler: Could not create the upgrade info file '/var/lib/mysql/mysql_upgrade_info' in the MariaDB Servers)kate /etc/httpd/conf/httpd.conf
Listen 127.0.0.1:80
Diese Zeilen mit einer Raute (#) auskommentieren:#LoadModule unique_id_module modules/mod_unique_id.so
#LoadModule authn_file_module modules/mod_authn_file.so
#LoadModule mpm_event_module modules/mod_mpm_event.so
Diese Zeile aktivieren (Raute entfernen):LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
Diese Zeilen am Ende hinzufügen:LoadModule php_module modules/libphp.so
AddHandler php-script .php
Include conf/extra/php_module.conf
Include conf/extra/phpmyadmin.conf
und prüfen ob diese Module aktiviert sind:LoadModule userdir_module modules/mod_userdir.so
LoadModule rewrite_module modules/mod_rewrite.so
kate /etc/httpd/conf/extra/phpmyadmin.conf
Alias /phpmyadmin "/usr/share/webapps/phpMyAdmin"
<Directory "/usr/share/webapps/phpMyAdmin">
DirectoryIndex index.php
AllowOverride All
Options FollowSymlinks
Require local
</Directory>
Info "Require all granted" nur wenn nicht Lokal!kate /etc/php/php.ini
Diese Zeilen prüfen/anpassen/aktivieren:date.timezone = Europe/Berlin
extension=gd
extension=exif
extension=iconv
extension=pdo_mysql
extension=mysqli
open_basedir = /srv/http/:/var/www/:/home/:/tmp/:/var/tmp/:/var/cache/:/usr/share/pear/:/usr/share/webapps/:/etc/webapps/
session.gc_probability = 1
upload_max_filesize = 20M
max_file_uploads = 40
kate /etc/webapps/phpmyadmin/config.inc.php
Hier ein 32 stelliges Passwort zur Cookie-Authentifizierung setzen, z.B.:$cfg['blowfish_secret'] = 'seit_phpMyAdmin504istdasPflicht'; /* This is needed for cookie based authentication to encrypt password in cookie. Needs to be 32 chars long. */
sudo systemctl restart httpd
sudo systemctl enable httpd
systemctl status httpd
(Abbruch mit Strg & C )php -m
kate /var/log/httpd/error_log
kate /srv/http/phpinfo.php
<?php
phpinfo();
?>
dann im Browser http://localhost/phpinfo.php öffnen, PHP Version und Konfiguration sollte angezeigt werden.sudo mkdir /usr/share/webapps/phpMyAdmin/tmp/
sudo chown -R http:http /usr/share/webapps/phpMyAdmin/tmp/
kate /etc/httpd/conf/extra/httpd-userdir.conf
Dieser Bereich sollte so aussehen:UserDir public_html
#
# Control access to UserDir directories. The following is an example
# for a site where these directories are restricted to read-only.
#
<Directory "/home/*/public_html">
DirectoryIndex index.php index.html
AllowOverride All
Options MultiViews SymLinksIfOwnerMatch IncludesNoExec
Require method GET POST OPTIONS
</Directory>
Habe das "Directory Listing" des Apache-Webservers deaktiviert, also "Indexes" entfernt (Zugriff auf alle Unterverzeichnisse werden verwehrt).mkdir ~/public_html
chmod 775 ~/public_html
chmod 755 ~
Apache neustarten:sudo systemctl restart httpd
kate ~/public_html/phpinfo.php
<?php
phpinfo();
?>
dann im Browser "http://localhost/~BENUTZERNAME/phpinfo.php" öffnen, PHP Version und Konfiguration sollte angezeigt werden.sudo gpasswd -a $USER http
(entfernen mit: sudo gpasswd -d $USER http)sudo chown -R $USER:$USER ~/
find ~/ \( -type d -exec chmod 755 {} + \) -or \( -type f -exec chmod 644 {} + \)
find ~/public_html/ \( -type d -exec chmod 775 {} + \) -or \( -type f -exec chmod 664 {} + \)
sudo chown -R http:http ~/public_html
AppImage und ShellScript ausführbar machen:chmod +x ./*.AppImage
chmod +x ./*.sh
prüfen:find ~ ! -user $USER -ls
das sollte nur Dateien aus dem Ordner public_html auflisten.less /var/log/pacman.log
oder mit einem Filter, z.B.:grep "ALPM] installed" /var/log/pacman.log
oder per pamac-gui im Menü -> "Chronik anzeigen", zeigt dann die Pamac Historie in einem Fenster.pacman -Qeqt > paketliste.txt
pacman -S $(cat paketliste.txt)
find ~ ! -user $USER -ls
(Ausgabe sollte leer sein)sudo chown -R $USER:$USER ~/
(Alle Dateien in /home/[Benutzer] gehören dann euch)find ~/ \( -type d -exec chmod 755 {} + \) -or \( -type f -exec chmod 644 {} + \)
AppImage und ShellScript ausführbar machen:chmod +x ./*.AppImage
chmod +x ./*.sh
sudo chown $USER:$USER /run/media/jo/Backup_ext4
sudo chmod 755 /run/media/jo/Backup_ext4
cp -arv ~/* /run/media/jo/Backup_ext4
Hinweis: Wenn ihr Plasma Vault nutzt und diese(n) Ordner geöffnet habt, werden Dateien unverschlüsselt auf die Backup Festplatte geschrieben. Verschlüsselte Dateien liegen im versteckten Ordner "~/.local/share/plasma-vault/". Daher halte ich Plasma Vault beim Backup erstellen geschlossen (Settings: ~/.config/plasmavaultrc).sudo rm -r ~/.cache/
cp -arv ~/.[!.]* /run/media/jo/Backup_ext4/
Dann die Backup Festplatte aushängen und sicher verwahren bis nach der Neuinstallation.rm -r ~/.local/share/kwalletd/
yes | cp -rv /run/media/jo/Backup_ext4/* ~/
Daten werden ohne Rückfrage überschrieben!yes | cp -rv /run/media/jo/Backup_ext4/.[!.]* ~/
Daten werden ohne Rückfrage überschrieben!sudo pacman -Syyuu
sudo pacman-key --refresh-keys
sudo pacman-key --populate archlinux manjaro
Vergewissert euch, dass die Systemzeit richtig eingestellt ist! Die drei Befehle sollten die meisten Probleme mit dem Schlüsselbund lösen, mehr siehe wiki.manjaro.org.rm ~/.config/Trolltech.conf
kbuildsycoca5 --noincremental
~/.config/plasma-org.kde.plasma.desktop-appletsrc
~/.local/share/plasma_notes/
kquitapp5 plasmashell
rm ~/.config/plasma-org.kde.plasma.desktop-appletsrc
rm ~/.config/plasmashellrc
rm ~/.config/plasmarc
plasmashell & disown
Der KDE-Desktop startet mit den Standardeinstellungen und die gelöschten Dateien werden neu angelegt.backintime-qt
kquitapp5 plasmashell
rm -r ~/.config
Danach den .config Ordner aus dem Backup per BackInTime wieder herstellen und den KDE-Desktop wieder starten:plasmashell & disown
kate ~/.config/mimeapps.list
Wenn das nicht hilft, kann man diese aus einem Backup wieder herstellen oder einfach löschen. Standard-Anwendungen müssen dann evtl. wieder angepasst werden.Configuration file "var/lib/sddm/.config/sddm-greeterrc" not writeable
Grund: Nicht alle Dateien hatten dem User sddm gehört, Lösung:sudo chown -R sddm:sddm /var/lib/sddm/
sudo rm -R /var/tmp/pamac-build-jo/packages-meta-ext-v1.json.gz
pamac update --force-refresh
pamac upgrade -a
sudo pacman -S plasma-wayland-session
echo $PATH
chmod +x ./*.AppImage
chmod +x ./*.sh
sudo pacman -S gtkglext
wenn in der Konsole der Fehler "error while loading shared libraries: libpangox-1.0.so.0" kommt, Paket pangox-compat aus dem AUR installieren:yay -S pangox-compat
(siehe auch Missing Libraries)sudo apt install libgtkglext1
./bin/anydesk/anydesk.sh
(obligatorische Bibliotheken die evtl. fehlen, siehe README)whitelist ${HOME}/.anydesk
diese Zeile einwhitelist ${HOME}/bin/anydesk
firejail --profile=~/bin/anydesk/anydesk.profile ~/bin/anydesk/anydesk.sh
(modifiziertes anydesk.profile im Anhang)sudo -i
wget -qO - https://keys.anydesk.com/repos/DEB-GPG-KEY | apt-key add -
echo "deb http://deb.anydesk.com/ all main" > /etc/apt/sources.list.d/anydesk-stable.list
apt update; sudo apt upgrade; sudo apt full-upgrade
apt install anydesk
sudo apt --purge remove anydesk
sudo rm /etc/apt/sources.list.d/anydesk-stable.list
dann mit "apt-key list" den Key suchen und auch entfernen, z.B. "sudo apt-key del 47A11ABC"CREATE TABLE `modx_custom_comment`(
`id` int(10) NOT NULL auto_increment,
`ctResource` int(10) NOT NULL default '0',
`ctIp` varchar(50) NOT NULL default '0:0:0:0:0:0:0:0',
`ctName` varchar(50) NOT NULL default '',
`ctEmail` varchar(60) NOT NULL default '',
`ctEmailshow` tinyint(1) NOT NULL default '0',
`ctHome` varchar(50) NOT NULL default '',
`ctVote` int(1) NOT NULL default '0',
`ctText` text NOT NULL,
`ctDate` timestamp NOT NULL default CURRENT_TIMESTAMP,
`ctActive` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`id`)
);
Hinweis: Der PREFIX 'modx_' ist Standard, wenn nicht muss das angepasst werden.<?php
# e.g.: <a href="[[~42? &resId=`[[+id]]`]]">Edit resource</a>
$prefix=$scriptProperties['prefix'];
$packageName = $scriptProperties['packageName'];
$tablename = $scriptProperties['tablename'];
$restrictPrefix = true;
$packagepath = $modx->getOption('core_path') . 'components/'.$packageName.'/';
$modelpath = $packagepath.'model/';
$schemapath = $modelpath.'schema/';
$schemafile = $schemapath.$packageName.'.mysql.schema.xml';
$manager= $modx->getManager();
$generator= $manager->getGenerator();
if (!file_exists($schemafile)){
if (!is_dir($packagepath)) {
mkdir($packagepath, 0755);
}
if (!is_dir($modelpath)) {
mkdir($modelpath, 0755);
}
if (!is_dir($schemapath)) {
mkdir($schemapath, 0755);
}
//Use this to create a schema from an existing database
$xml= $generator->writeSchema($schemafile, $packageName, 'xPDOObject', $prefix, $restrictPrefix);
//Use this to generate classes and maps from your schema
//NOTE: by default, only maps are overwritten; delete class files if you want to regenerate classes
$generator->parseSchema($schemafile, $modelpath);
}
$modx->addPackage($packageName,$modelpath,$prefix);
$classname = $generator->getClassName($tablename);
if (isset($_GET['resId'])){
if ($dataobject=$modx->getObject($classname,array('id'=>$_GET['resId']))){
if (!is_object($dataobject) || !($dataobject instanceof xPDOObject)) {
$errorMsg='Failed to create object of type: ' . $classname;
$hook->addError('error_message',$errorMsg);
return false;
}
# only if
if ($modx->user->isMember(array('Administrator'))){
# or
# if ($modx->user->get('id') == '1'){
$hook->setValues($dataobject->toArray());
}
}
}
return true;
<?php
$prefix=$scriptProperties['prefix'];
$packageName = $scriptProperties['packageName'];
$tablename = $scriptProperties['tablename'];
$packagepath = $modx->getOption('core_path') . 'components/'.$packageName.'/';
$modelpath = $packagepath.'model/';
$modx->addPackage($packageName,$modelpath,$prefix);
$manager= $modx->getManager();
$generator= $manager->getGenerator();
$classname = $generator->getClassName($tablename);
$dataobject=$modx->getObject($classname,array('id'=>$hook->getValue('resource_id')));
if (empty($dataobject)){
$dataobject = $modx->newObject($classname);
}
else{
// kein neuen DS anlegen (also update)
}
if (!is_object($dataobject) || !($dataobject instanceof xPDOObject)) {
$errorMsg='Failed to create object of type: ' . $classname;
$hook->addError('error_message',$errorMsg);
return false;
}
$allFormFields = $hook->getValues();
foreach ($allFormFields as $field=>$value){
if ($field !== 'spam' && $field !== 'resource_id'){
$dataobject->set($field,$value);
}
}
$dataobject->save();
return true;
<?php
# löscht alle deaktivierte Kommentare
$table = 'modx_custom_comment';
$where = 'ctActive=0';
$count = $modx->exec("DELETE FROM $table WHERE $where");
return $count. ' Kommentar(e) wurde(n) gelöscht!';
<?php
# zähle aktivierte Einträge der aktuellen Ressource [[!commentQty?active=`1`]]
# Anzahl Platzhalter [[+ctQTY]]
$id = $modx->resource->get('id');
$stmt = $modx->query('SELECT * FROM `modx_custom_comment` WHERE `ctActive`='.$active.' AND `ctResource`='.$id);
$count=0;
$count = $stmt->rowCount();
$modx->setPlaceholder('ctQTY', $count);
return $count;
<?php
# email-Adressen vor bots durch Maskierung verbergen
$hiddenEmail = '';
$length = strlen($input);
for($i = 0;$i<$length;$i++){
$hiddenEmail .= '&#'.ord($input[$i]).';';
}
return $hiddenEmail;
<?php
//Example
//[[!getGravatar? &email=`[[+gbemail:htmlent]]` &size=`40` &default=`[[++site_url]]/assets/content/images/Gravatar_40x40.jpg`]]
//or
//[[!getGravatar? &email=`[[+gbemail:htmlent]]` &size=`40` &default=``]]
$grav_url="https://www.gravatar.com/avatar/".md5(strtolower(trim($email)))."?d=".urlencode($default)."&s=".$size;
return '<img src="'.$grav_url.'" class="img-polaroid" alt="" title="Gravatar" />';
<?php
# Output-Filter zur Darstellung der Smilies in den Kommentaren
# Z.B.:
# [[$smilieChunk:smilies]]
# oder
# [[+ctText:nl2br:smilies]]
// Path where the smilies are stored
$basepath = $modx->config['site_url'].'assets/content/images/';
// Mapping of text to imagename
$smilies = array(':biggrin:' => 'biggrin.gif',':-)' => 'smile.gif',':-(' => 'mad.gif',':eek:' => 'bigeek.gif',':-P' => 'razz.gif',':oops:' => 'upset.gif',':cry:' => 'cry.gif',':evil:' => 'sigh.gif',':dead:' => 'dead.gif',':roll:' => 'rolleyes.gif',';-)' => 'wink.gif','8-)' => 'cool.gif',':-?' => 'confused.gif',':sleep:' => 'sleep.gif');
// Convert imagenames to html tags here, just to keep the structure above
// easy to maintain, especially when I want to change the generated HTML.
foreach ($smilies as $key => $value)
{
$smilies[$key] = "<img src='".$basepath.$value."' class='smilie' alt='$key' />";
}
return str_replace(array_keys($smilies), array_values($smilies), $input);
<?php
# Output-Filter zur Darstellung der Vote-Icons in den Kommentaren
# Z.B.:
# [[+ctVote:vote]]
$vote = '';
for ($i = 1; $i <= $input; $i++) {
$vote .= '<img src="assets/content/images/vote-16x18.png" class="vote" alt="Bewertung" />';
}
return $vote;
<?php
# Output-Filter zur Darstellung von BBCode in den Kommentaren
# Z.B.: [[+ctText:bbcode]]
# erlaubt ist:
# [b]fett[/b] [i]kursiv[/i] [u]unterstrichen[/u] [center]zentriert[/center]
# [link]https://jolichter.de[/link] oder [url]jolichter.de[/url]
#
$string = preg_replace("/&(#[0-9]+|[a-z]+);/i", "&$1;", htmlspecialchars($input));
$string = preg_replace('~\[b\](.+?)\[/b\]~is', '<b>\1</b>', $string);
$string = preg_replace('~\[i\](.+?)\[/i\]~is', '<i>\1</i>', $string);
$string = preg_replace('~\[u\](.+?)\[/u\]~is', '<span style="text-decoration: underline;">\1</span>', $string);
$string = preg_replace('~\[center\](.+?)\[/center\]~is', '<div style="text-align:center;">\1</div>', $string);
$string = preg_replace('~\[link\]www.(.+?)\[/link\]~is', '<a href="https://www.\1" target="_blank">www.\1</a>', $string);
$string = preg_replace('~\[link\](.+?)\[/link\]~is', '<a href="\1" target="_blank">\1</a>', $string);
$string = preg_replace('~\[link=(.+?)\](.+?)\[/link\]~is', '<a href="\1" target="_blank">\2</a>', $string);
$string = preg_replace('~\[url\]www.(.+?)\[/url\]~is', '<a href="https://www.\1" target="_blank">www.\1</a>', $string);
$string = preg_replace('~\[url\](.+?)\[/url\]~is', '<a href="\1" target="_blank">\1</a>', $string);
$string = preg_replace('~\[url=(.+?)\](.+?)\[/url\]~is', '<a href="\1" target="_blank">\2</a>', $string);
$string = str_replace(array("[","]","`"),array("[","]","`"),$string);
return $string;
<hr>
<div class="span10">
<div class="comment">
Die eMail Adresse wird nur auf Wunsch angezeigt und Avatar Bilder werden verschlüsselt über <a href="https://de.gravatar.com/" target="_blank">Gravatar</a> bezogen.
</div>
<p>[[!$commentForm]]</p>
[[+ctQTY:gt=`0`:then=`<h3>[[!commentQty?active=`1`]] [[+ctQTY:eq=`1`:then=`Kommentar`:else=`Kommentare`]]</h3>`:else=``]]
[[!$commentEntry]]
</div>
diesen Chunk z.B. im Seitentemplate hinter [[*content]] per TV uncached einbinden......
......
[[*content]]
[[*tvComment:is=`ja`:then=`[[!$modxComment]]`:else=``]]
......
......
<div class="smilies">
<div class="smilieSelect"><img src="assets/content/icons/biggrin.gif" alt="biggrin" onclick="AddSmile(':biggrin:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/smile.gif" alt=":-)" onclick="AddSmile(':-)')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/mad.gif" alt=":-(" onclick="AddSmile(':-(')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/smilies2/bigeek.gif" alt=":eek:" onclick="AddSmile(':eek:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/razz.gif" alt=":-P" onclick="AddSmile(':-P')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/upset.gif" alt=":oops:" onclick="AddSmile(':oops:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/cry.gif" alt=":cry:" onclick="AddSmile(':cry:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/sigh.gif" alt=":evil:" onclick="AddSmile(':evil:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/dead.gif" alt="dead" onclick="AddSmile(':dead:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/rolleyes.gif" alt=":roll:" onclick="AddSmile(':roll:')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/wink.gif" alt=";-)" onclick="AddSmile(';-)')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/cool.gif" alt="8-)" onclick="AddSmile('8-)')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/confused.gif" alt=":-?" onclick="AddSmile(':-?')" /></div>
<div class="smilieSelect"><img src="assets/content/icons/sleep.gif" alt=":sleep:" onclick="AddSmile(':sleep:')" /></div>
</div>
<script>
function AddSmile(x,D,F){D=document;F=D.getElementById('ctText');D.selection?(F.focus(),D.selection.createRange().text=x):(F.selectionStart||F.selectionStart===0)?F.value=F.value.substring(0,F.selectionStart)+x+F.value.substring(F.selectionEnd,F.value.length):F.value+=x}
</script>
Neuer Kommentar gesendet von [[++site_url]] <br />
<br />[[+ctName:htmlent]] ([[+ctEmail:htmlent]]) hat als Kommentar geschrieben: <br /><br />
[[+ctText:htmlent:nl2br]]
<br /><br />
Bewertung: [[+ctVote]]<br />
Ort: [[+ctHome:htmlent]]<br />
Datenschutzerklärung akzeptiert: [[+datenschutz:is=`1`:then=`Ja`:else=`Nein`]]<br />
<div class="row"><div class="span12">
<span class="label">Seite [[+page]] von [[+pageCount]]</span>
</div></div>
[[!getPage:default=`Noch kein Eintrag vorhanden`?
&element=`Rowboat`
&table=`modx_custom_comment`
&sortBy=`id`
&sortDir=`DESC`
&where=`[[!+modx.user.id:eq=`1`:then=`{"ctResource:=":"[[*id]]","ctActive:>=":"0"}`:else=`{"ctResource:=":"[[*id]]","ctActive:=":"1"}`]]`
&totalVar=`rowboat.total`
&cacheResults=`0`
&tpl=`tplCommentEntry`
&limit=`5`
&pageFirstTpl=`<li class="control"><a[[+classes]][[+title]] href="[[+href]]">Erste</a></li>`
&pageLastTpl=`<li class="control"><a[[+classes]][[+title]] href="[[+href]]">Letzte</a></li>`
]]
[[!+page.nav:notempty=`
<div class="pagination">
<ul>
[[!+page.nav]]
</ul>
</div>
`]]
<hr>
[[!FormIt?
&preHooks=`StupidQuestion,db2formit`
&hooks=`StupidQuestion,spam,email,formit2db,redirect`
&prefix=`modx_custom_`
&tablename=`comment`
&packageName=`comment`
&emailTpl=`commentEmail`
&emailFrom=`deine-e-mail@server.tld`
&emailTo=`deine-e-mail@server.tld`
&redirectTo=`4711`
&emailUseFieldForSubject=`1`
&emailSubject=`Neuer Kommentar`
&validationErrorMessage=`<p class="text-error">Die eingegebenen Daten waren nicht richtig: [[+errors]]</p>`
&validate=`ctName:required:maxLength=`50`,
ctEmail:email:required:maxLength=`60`,
ctHome:required:maxLength=`50`,
ctText:required:stripTags:maxLength=`1000`,
ctVote:required,
datenschutz:required,
name2:blank`
]]
[[$commentAddSmile]]
<script>
$(function(){
function runEffect() {
var options = {};
$("#effect").toggle("blind", options, 500);
};
$('#ctEinblenden').click(function() {
$('#ctAusblenden').slideToggle("slow");
$(this).toggleClass("ct");
if($(this).hasClass("ct")){
$(this).html("<i class='icon-comment'></i> Eintrag ausblenden");
}else{
$(this).html("<i class='icon-comment icon-white'></i> Eintrag hinzufügen");
}
runEffect();
return false;
});
});
</script>
<div class="row"><div class="span4">
<button id="ctEinblenden" class="btn btn-primary" type="button"><i class="icon-comment icon-white"></i> Eintrag hinzufügen</button>
<div id="ctAusblenden" style="display:none;">
<h2>Kommentar Eintrag</h2>
[[!+fi.error.error_message:notempty=`<p>[[!+fi.error.error_message]]</p>`]]
<form action="[[~[[*id]]]]" method="post" class="form">
<input type="hidden" name="name2" value="" />
<input name="resource_id" type="hidden" value="[[+fi.id]]" />
[[- IP aktiviere ich nur kurzeitig bei Bedarf, z.B. bei DDoS-Attacken um diese dann zu sperren]]
[[- !+modx.user.id:eq=`1`:then=``:else=`<input type="hidden" name="ctIp" value="[[!myIP?]]" />`]]
<input type="hidden" name="ctResource" value="[[*id]]" />
<table class="table table-hover table-condensed">
[[!+modx.user.id:eq=`1`:then=`
<tr><th>Aktiv:</th>
<th>
<input type="hidden" name="ctActive[]" value="0" />
<input type="checkbox" name="ctActive[]" id="ctActive" value="1" [[!+fi.ctActive:FormItIsChecked=`1`]] />
Kommentar veröffentlichen? <br /><br />
</th></tr>
`:else=``]]
<tr><th><label for="ctName">Name:</label></th>
<th><input required type="text" name="ctName" id="ctName" maxlength="50" value="[[!+fi.ctName:htmlent]]" />
<img src="assets/content/images/text-x-vcard.png" alt="icon" width="16" height="16" />
<span class="text-error">[[+fi.error.ctName]]</span>
</th></tr>
<tr><th><label for="ctHome">Wohnort:</label></th>
<th><input required type="text" name="ctHome" id="ctHome" maxlength="50" value="[[!+fi.ctHome:htmlent]]" />
<img src="assets/content/images/user-home.png" alt="icon" width="16" height="16" />
<span class="text-error">[[+fi.error.ctHome]]</span>
</th></tr>
<tr><th><label for="ctEmail">eMail:</label></th>
<th><input required type="email" name="ctEmail" id="ctEmail" maxlength="50" value="[[!+fi.ctEmail:htmlent]]" />
<img src="assets/content/images/mail-message.png" alt="icon" width="16" height="16" />
<span class="text-error">[[+fi.error.ctEmail]]</span><div class="smallfont">
<input type="hidden" name="ctEmailshow[]" value="0" />
<input type="checkbox" name="ctEmailshow[]" id="ctEmailshow" value="1" [[!+fi.ctEmailshow:FormItIsChecked=`1`]] /> eMail wird veröffentlicht!<br /><br /></div>
</th></tr>
<tr><th><label for="ctVote">Bericht Bewertung:</label></th>
<th>
<select required tabindex="0" name="ctVote" id="ctVote">
<option value="[[+fi.ctVote]]">Bitte bewerten</option>
<option value="5">5 Sterne</option>
<option value="4">4 Sterne</option>
<option value="3">3 Sterne</option>
<option value="2">2 Sterne</option>
<option value="1">1 Sterne</option>
</select>
<img src="assets/content/images/vote-16x18.png" alt="vote" width="16" height="16" />
<span class="text-error">[[+fi.error.ctVote]]</span>
</th></tr>
<tr><th></th>
<th class="smallfont"><br/>Mit <a href="[[~[[*id]]]]#" data-rel="popover-top" class="btn-min btn-success" data-content="
erlaubt ist:<br />
[b]fett[/b]<br />
[i]kursiv[/i]<br />
[u]unterstrichen[/u]<br />
[center]zentriert[/center]" data-original-title="BBCode">BBCode</a> könnt ihr euren Text strukturieren<br />
</th></tr>
<tr><th><label for="ctText">Kommentar:<br />
<span class="smallfont">(max. 1000 Zeichen)</span></label>
<img src="assets/content/images/text-x-generic.png" alt="icon" width="24" height="24" /></th>
<th><textarea required class="span5" name="ctText" id="ctText" cols="50" rows="6">[[!+fi.ctText:htmlent]]</textarea>
<span class="text-error">[[+fi.error.ctText]]</span>
</th></tr>
<tr><th></th>
<th>[[$commentSmilies]]
</th></tr>
<tr><th><label for="datenschutz">Datenschutz:</label></th>
<th><input type="hidden" name="datenschutz[]" value="0" />
<input required type="checkbox" name="datenschutz[]" id="datenschutz" value="1" [[!+fi.datenschutz:FormItIsChecked=`1`]] /> Ich bin damit einverstanden, dass mein Kommentar veröffentlicht wird und habe die Datenschutzerklärung im <a href="[[~666]]" target="_blank">Datenschutz</a> gelesen und akzeptiert.
<span class="text-error">[[+fi.error.datenschutz]]</span>
</th></tr>
<tr><th></th>
<th>[[!+formit.stupidquestion_html]]
</th></tr>
<tr><th></th>
<th>
[[!+modx.user.id:eq=`1`:then=`
<button type="submit" class="btn btn-large btn-success">
<i class="icon-play icon-white"></i> Eintrag hinzufügen ([[+fi.id]])</button>
`:else=`
<button type="submit" class="btn btn-large btn-success">
<i class="icon-play icon-white"></i> Eintrag hinzufügen</button>
` ]]
</th></tr>
</table>
</form>
</div>
</div></div>
<h3 style="text-align: center;">Vielen Dank für deinen Kommentar</h3>
<br />
Solltest du deinen Beitrag löschen oder korrigieren wollen, melde dich bitte per Kontaktformular und wir werden das schnellstmöglich korrigieren.
<br /><br />
<script>
document.write('<a href="' + document.referrer + '"><div class="back">Zurück zum Bericht</div></a>');
</script>
<div class="comment_top">
<span class="comment_big">
[[+ctName:htmlent]]
</span>
<span class="comment_small">
am [[+ctDate:strtotime:date=`%d-%m-%Y, %H:%M Uhr`]] aus [[+ctHome:htmlent]]
</span>
<span class="comment_vote">
[[+ctVote:vote]]
</span>
</div>
<div [[+_alt:is=`0`:then=`class="comment_content"`:else=`class="comment_content_b"`]]>
<span class="ctEmail">
[[+ctEmailshow:eq=`1`:then=`<a href="[[emailMask? &input=`mailto:[[+ctEmail:htmlent]]`]]"><i class="icon-envelope" title="eMail"></i></a>`:else=``]]
[[!+modx.user.id:eq=`1`:then=`<br />[[+ctEmail:htmlent:emailMask]]`:else=``]]
</span>
<p class="gbavatar">[[!getGravatar? &email=`[[+ctEmail:htmlent]]` &size=`40` &default=``]]</p>
[[+ctText:htmlent:bbcode:nl2br:smilies]]
[[!+modx.user.id:eq=`1`:then=`
<br /><a href="[[~[[*id]]? &resId=`[[+id]]`]] ">Eintrag ändern</a><br />
[[+ctActive:eq=`1`:then=``:else=`<font color=#990000>Kommentar ist deaktiviert || <a href="[[~815]]">alle deaktivierte löschen!</a></font>`]]
`:else=``]]
</div>
<h2 style="text-align: center;">Warnung!</h2>
<p style="text-align: center;">Hier werden alle deaktivierte Kommentare gelöscht!</p>
[[!+modx.user.id:memberof=`Administrator`:then=`
<div class="back"><a href="[[~4711]]"><font color=#990000>Achtung! Jetzt diese Kommentare löschen?</font></a></div>
`:else=`Sorry, du bist kein Admin!`]]
<div class="back"><a href="[[~[[++site_start]]]]">Abrechen!</a></div>
[[!getPage:default=`Es ist kein deaktivierter Eintrag vorhanden!`?
&element=`Rowboat`
&table=`modx_custom_comment`
&sortBy=`id`
&sortDir=`DESC`
&where=`[[!+modx.user.id:memberof=`Administrator`:then=`{"ctActive":"0"}`:else=`{"ctActive":"9"}`]]`
&totalVar=`rowboat.total`
&cacheResults=`0`
&tpl=`tplCommentEntryDel`
&limit=`10`
&pageFirstTpl=`<li class="control"><a[[+classes]][[+title]] href="[[+href]]">Erste</a></li>`
&pageLastTpl=`<li class="control"><a[[+classes]][[+title]] href="[[+href]]">Letzte</a></li>`
]]
[[!+page.nav:notempty=`
<div class="pagination">
<ul>
[[!+page.nav]]
</ul>
</div>
`]]
[[!+modx.user.id:memberof=`Administrator`:then=`[[!commentEntryDel]]`:else=`keine Berechtigung!`]]
<div class="back"><a href="[[~[[++site_start]]]]">Zur Startseite</a></div>
/* Comments */
#ctText, #ctName, #ctHome, #ctEmail {padding: 2px; clear: right}
#ctEinblenden, #ctAusblenden {text-align: center; font-size: 14px; font-weight: bold; margin: 0; padding: 2px 5px 2px 5px}
#ctAusblenden label {margin-right: 50px}
.smilie {vertical-align: sub}
.smilies {margin: 5px 2px 40px 0px}
.smilieSelect {float: left; margin-right: 5px}
.comment_top {background-color: #123; height: 26px; color: #fff; margin-right: 10px; padding: 2px 5px 2px 5px}
.comment_big {float: left; font-size: 16px; font-weight: bold; margin-right: 10px; padding-top: 4px}
.comment_small {float: left; font-size: 10px; font-weight: bold; padding: 6px 0 0 0}
.ctAvatar {float:left; padding-right: 5px; margin-left: -60px}
.comment_content {min-height: 80px; margin: 0 10px 20px 0; padding: 5px 30px 0 40px; clear: right; background: #fff; border-width: 1px; border-style: solid; border-color: #123}
.comment_content_b {min-height: 80px; margin: 0 10px 20px 0; padding: 5px 30px 0 40px; clear: right; background: #f4f4f4; border-width: 1px; border-style: solid; border-color: #123}
.comment_content .ctEmail, .comment_content_b .ctEmail {float: right; margin: 0 -20px 0 20px; color: green; font-size: 10px}
.comment_vote {float: right; padding: 3px 5px 3px 0; width: 100px}
.comment_vote .vote {float: right; padding: 0px 1px 0; width: 16px; height: 16px}
<?php
#
# DWD Wettervorhersage MODX Snippet | MODX Weather Forecast V 22.10.045
#
# Entgeltfreie Versorgung mit DWD-Geodaten über dem Serverdienst https://opendata.dwd.de
# https://opendata.dwd.de/README.txt
#
# MOSMIX-Dateien werden in dem xml-ähnlichen kml-Format ausgeliefert, die Dateien sind als kmz-Dateien komprimiert
# DWD Stationskatalog (oder besser Vorhersagepunkte!): https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.cfg?view=nasPublication&nn=16102
# z.B.: ID 10609 = Trier, ID 10513 = Koeln/Bonn, ID K428 = Bitburg, usw.
#
# Beispiele für Snippet-Aufrufe
# ohne Uhrzeit:
# [[!dwdWeather? &STATION=`K428` &TPL=`dwdWetterTPL`]]
# [[+dwdWeather]]
# (als Standard wird 12:00 Uhr genommen)
#
# alle Vorhersagen stündlich:
# [[!dwdWeather? &STATION=`K428` &fcAll=`true` &TPL=`dwdWetterTPL`]]
# [[+dwdWeather]]
#
# mit 4 Uhrzeiten pro Tag (T1 -T4) bei 12 Vorhersagen (QTY), also Vorhersage 3 Tage:
# [[!dwdWeather?
# &STATION=`K428`
# &TPL=`dwdWetterTPL`
# &QTY=`12`
# &T1=`06:00`
# &T2=`12:00`
# &T3=`18:00`
# &T4=`00:00`
# ]]
# [[+dwdWeather]]
#
# eine definierte Zeit pro Tag:
# [[!dwdWeather?
# &STATION=`K428`
# &TPL=`dwdWetterTPL`
# &T1=`18:00`
# ]]
# [[+dwdWeather]]
#
# oder
#
# im Dokument ein Chunk "chunkWeather" aufrufen: [[$chunkWeather? &STATION=`K428` &TPL=`dwdWetterTPL` &QTY=`QTY` &T1=`06:00` &T2=`12:00` &T3=`18:00` &T4=`00:00`]] [[+dwdWeather]]
# dann in dem Chunk das Snippet aufrufen: [[!dwdWeather? &STATION=`[[+STATION]]` &TPL=`[[+TPL]]` &QTY=`16` &T1=`[[+T1]]` &T2=`[[+T2]]` &T3=`[[+T3]]` &T4=`[[+T4]]`]]
# und ein eigenes HTML-Gerüst mit den Platzhalter erstellen
#
# Platzhalter für Chunks:
# -> Ort und Vorhersagedatum: [[+location]] [[+pubDate]] [[+pubDateDay]]
# -> Sonnenaufgang: [[+sunrise]], Sonnenuntergang: [[+sunset]], Tageslänge: [[+dayduration]], Luftdrucktendenz: [[+pTendenz]] [[+pDelta]]
#
# Beispiel für ein Chunk Template (z.B. dwdWetterTPL) welches per Platzhalter [[+dwdWeather]] dann platziert wird:
# <div>
# <div>
# <h4>[[+fc0]] [[+fc2]] [[+fc1]]</h4>
# <img src='[[+fc17]]' title='[[+fc16]]' alt='' >
# </div>
# [[+fc5:gte=`0.1`:then=`<span class="label blue">[[+fc5]]</span>`:else=`<span class="label red">[[+fc5]]</span>`]]
# <br />
# <small>Sonnenschein: [[+fc14]]</small><br />
# <small>Wolkendecke: [[+fc10]]</small><br />
# <small>Niederschlag: [[+fc13]]</small><br />
# <small>Wind (Richtung): [[+fc8]] ([[+fc7]])</small><br />
# <small>Max. Windböe: [[+fc9]]</small><br />
# <small>Luftdruck: [[+fc11]]</small><br />
# <small>Luftfeuchte: [[+fc18]]</small><br />
# <small>Sichtweite: [[+fc15]]</small><br />
# </div>
#
# Vorhersage Platzhalter z.B. für Kalender
# -> 20 Vorhersagen (10 Tage): [[+fc_V_E]] (V = Vorhersage Nr (0-19) | E = Elemente (0-18), z.B. [[+fc_0_5]]
#
# 19 Elemente: 0 Date | 1 Time | 2 Day | 3 minT | 4 maxT | 5 2mT | 6 dewPoint | 7 windDir | 8 windSpeed | 9 windGust | 10 cloud |
# 11 hPa | 12 rainKg24h | 13 rainKg6h | 14 sun | 15 vis | 16 sigW | 17 picName | 18 hu |
#
#
#
# Variablen -Start------------------->
# Chunk Template(default ist ohne)
$strTPL = $modx->getOption('TPL',$scriptProperties,'');
# Anzahl der Vorhersagen (default ist 40, bei 4 pro Tag sind das dann 10 Tage)
$intQTY = $modx->getOption('QTY',$scriptProperties, 40);
$strTMP = MODX_ASSETS_PATH.'dwd_temp/';
$strURL = 'https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_L/single_stations/';
$strStation = $modx->getOption('STATION',$scriptProperties,'10609'); # Trier (älteste Stadt Deutschlands)
$strURL .= $strStation . '/kml/MOSMIX_L_LATEST_' . $strStation . '.kmz';
# Icons Bilder Pfad
$strURLIcon = $modx->config['base_url'].'assets/dwd_img/'; # Wetter-Icons
# z.B. Forecast 10 Tage = 24*10
$MAX_COUNT = 24*10;
# Forecast
$fcAll = $modx->getOption('fcAll',$scriptProperties,'false'); # default all-Forecast false
$time1 = $modx->getOption('T1',$scriptProperties,'12:00'); # default 12:00
$time2 = $modx->getOption('T2',$scriptProperties,'');
$time3 = $modx->getOption('T3',$scriptProperties,'');
$time4 = $modx->getOption('T4',$scriptProperties,'');
# Luftdruck gilt als stabil, wenn hPa Delta nicht grösser als
$intPStable = 4;
# Wetter Icons mit oder ohne Sonne (SunD3) anzeigen, ab x %
$intSun = 30;
# Hitzewelle gilt ab wie viel Grad? Wetter Icon Sonne 0h.png (TX)
$valMaxT = 35.0; # ab x Grad Celsius (z.B. 35.0)
# wenn Winter-Sommerzeit angepasst werden muss
$bolTimeOffset = false;
$timeOffset = '0';
# Variablen -Ende-------------------<
if ($bolTimeOffset) {
# Sommerzeit/Winterzeit
# daylight timeOffset to UTC)
# 1 bei Sommerzeit, ansonsten 0
if(date('I') == 1) {
$timeOffset = '7200';
}
else{
$timeOffset = '3600';
}
}
# Ordner anlegen, wenn fehlt
if(!file_exists($strTMP)) {
mkdir($strTMP, 0755, true);
}
# relative Luftfeuchtigkeit berechnen
# calculate relative humidity (TTT(K), Td(K))
if (!function_exists('getHumidity')) {
function getHumidity($T, $TD) {
if (is_numeric($T) && is_numeric($TD)) {
$T = round($T - 273.15, 1);
$TD = round($TD - 273.15, 1);
$RH=round(100*(exp((17.625*$TD)/(243.04+$TD)) / exp((17.625*$T)/(243.04+$T))));
} else {
$RH = '---';
}
return $RH;
}
}
if (!function_exists('xml2array')) {
function xml2array ( $xmlObject, $out = array () ) {
foreach ( (array) $xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) ) ? xml2array ( $node ) : $node;
return $out;
}
}
if (!function_exists('getParamArray')) {
function getParamArray($rootObj, $id) {
foreach ($rootObj as $param) {
if ((string) $param['elementName'] == $id) {
$output = preg_replace('!\s+!', ';', (string) $param->value);
$output = explode(';', $output);
array_shift($output);
return $output;
}
}
}
}
# function direction in N/E/S/W instead of Grad (Windrichtung)
if (!function_exists('getWindDirection')) {
function getWindDirection($degree = 0) {
$direction = array('N', 'NNO', 'NO', 'ONO', 'O', 'OSO', 'SO', 'SSO', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW');
$step = 360 / (count($direction));
$b = floor(($degree + ($step/2)) / $step);
return $direction[$b % count($direction)];
}
}
# ww-Code - Hashs mit deutschen Konditionen (Code/Description), Quellen:
# https://wetterkanal.kachelmannwetter.com/was-ist-der-ww-code-in-der-meteorologie/
# https://www.dwd.de/DE/leistungen/opendata/help/schluessel_datenformate/kml/mosmix_element_weather_xls.html
# es werden nicht alle benötigt, aber wer weiss... ;-)
$strConditions_de = array(
// Bewölkung
'0' => 'Effektive Wolkendecke weniger als 2/8',
'1' => 'Effektive Wolkendecke zwischen 2/8 und 5/8',
'2' => 'Effektive Wolkendecke zwischen 5/8 und 6/8',
'3' => 'Effektive Wolkendecke mindestens 6/8',
// Dunst, Rauch, Staub oder Sand
'4' => 'Sicht durch Rauch oder Asche vermindert',
'5' => 'trockener Dunst (relative Feuchte < 80 %)',
'6' => 'verbreiteter Schwebstaub, nicht vom Wind herangeführt',
'7' => 'Staub oder Sand bzw. Gischt, vom Wind herangeführt',
'8' => 'gut entwickelte Staub- oder Sandwirbel',
'9' => 'Staub- oder Sandsturm im Gesichtskreis, aber nicht an der Station',
// Trockenereignisse
'10' => 'feuchter Dunst (relative Feuchte > 80 %)',
'11' => 'Schwaden von Bodennebel',
'12' => 'durchgehender Bodennebel',
'13' => 'Wetterleuchten sichtbar, kein Donner gehört',
'14' => 'Niederschlag im Gesichtskreis, nicht den Boden erreichend',
'15' => 'Niederschlag in der Ferne (> 5 km), aber nicht an der Station',
'16' => 'Niederschlag in der Nähe (< 5 km), aber nicht an der Station',
'17' => 'Gewitter (Donner hörbar), aber kein Niederschlag an der Station',
'18' => 'Markante Böen im Gesichtskreis, aber kein Niederschlag an der Station',
'19' => 'Tromben (trichterförmige Wolkenschläuche) im Gesichtskreis',
// Ereignisse der letzten Stunde, aber nicht zur Beobachtungszeit
'20' => 'nach Sprühregen oder Schneegriesel',
'21' => 'nach Regen',
'22' => 'nach Schneefall',
'23' => 'nach Schneeregen oder Eiskörnern',
'24' => 'nach gefrierendem Regen',
'25' => 'nach Regenschauer',
'26' => 'nach Schneeschauer',
'27' => 'nach Graupel- oder Hagelschauer',
'28' => 'nach Nebel',
'29' => 'nach Gewitter',
// Staubsturm, Sandsturm, Schneefegen oder -treiben
'30' => 'leichter oder mäßiger Sandsturm, an Intensität abnehmend',
'31' => 'leichter oder mäßiger Sandsturm, unveränderte Intensität',
'32' => 'leichter oder mäßiger Sandsturm, an Intensität zunehmend',
'33' => 'schwerer Sandsturm, an Intensität abnehmen',
'34' => 'schwerer Sandsturm, unveränderte Intensität',
'35' => 'schwerer Sandsturm, an Intensität zunehmend',
'36' => 'leichtes oder mäßiges Schneefegen, unter Augenhöhe',
'37' => 'starkes Schneefegen, unter Augenhöhe',
'38' => 'leichtes oder mäßiges Schneetreiben, über Augenhöhe',
'39' => 'starkes Schneetreiben, über Augenhöhe',
// Nebel oder Eisnebel
'40' => 'Nebel in einiger Entfernung',
'41' => 'Nebel in Schwaden oder Bänken',
'42' => 'Nebel, Himmel erkennbar, dünner werdend',
'43' => 'Nebel, Himmel nicht erkennbar, dünner werdend',
'44' => 'Nebel, Himmel erkennbar, unverändert',
'45' => 'Nebel, Himmel nicht erkennbar, unverändert',
'46' => 'Nebel, Himmel erkennbar, dichter werdend',
'47' => 'Nebel, Himmel nicht erkennbar, dichter werdend',
'48' => 'Nebel mit Reifansatz, Himmel erkennbar',
'49' => 'Nebel mit Reifansatz, Himmel nicht erkennbar',
// Sprühregen
'50' => 'unterbrochener leichter Sprühregen',
'51' => 'durchgehend leichter Sprühregen',
'52' => 'unterbrochener mäßiger Sprühregen',
'53' => 'durchgehend mäßiger Sprühregen',
'54' => 'unterbrochener starker Sprühregen',
'55' => 'durchgehend starker Sprühregen',
'56' => 'leichter gefrierender Sprühregen',
'57' => 'mäßiger oder starker gefrierender Sprühregen',
'58' => 'leichter Sprühregen mit Regen',
'59' => 'mäßiger oder starker Sprühregen mit Regen',
// Regen
'60' => 'unterbrochener leichter Regen oder einzelne Regentropfen',
'61' => 'durchgehend leichter Regen',
'62' => 'unterbrochener mäßiger Regen',
'63' => 'durchgehend mäßiger Regen',
'64' => 'unterbrochener starker Regen',
'65' => 'durchgehend starker Regen',
'66' => 'leichter gefrierender Regen',
'67' => 'mäßiger oder starker gefrierender Regen',
'68' => 'leichter Schneeregen',
'69' => 'mäßiger oder starker Schneeregen',
// Schnee
'70' => 'unterbrochener leichter Schneefall oder einzelne Schneeflocken',
'71' => 'durchgehend leichter Schneefall',
'72' => 'unterbrochener mäßiger Schneefall',
'73' => 'durchgehend mäßiger Schneefall',
'74' => 'unterbrochener starker Schneefall',
'75' => 'durchgehend starker Schneefall',
'76' => 'Eisnadeln (Polarschnee)',
'77' => 'Schneegriesel',
'78' => 'Schneekristalle',
'79' => 'Eiskörner (gefrorene Regentropfen)',
// Schauer
'80' => 'leichter Regenschauer',
'81' => 'mäßiger oder starker Regenschauer',
'82' => 'äußerst heftiger Regenschauer',
'83' => 'leichter Schneeregenschauer',
'84' => 'mäßiger oder starker Schneeregenschauer',
'85' => 'leichter Schneeschauer',
'86' => 'mäßiger oder starker Schneeschauer',
'87' => 'leichter Graupelschauer',
'88' => 'mäßiger oder starker Graupelschauer',
'89' => 'leichter Hagelschauer',
'90' => 'mäßiger oder starker Hagelschauer',
// Gewitter
'91' => 'Gewitter in der letzten Stunde, zurzeit leichter Regen',
'92' => 'Gewitter in der letzten Stunde, zurzeit mäßiger oder starker Regen',
'93' => 'Gewitter in der letzten Stunde, zurzeit leichter Schneefall/Schneeregen/Graupel/Hagel',
'94' => 'Gewitter in der letzten Stunde, zurzeit mäßiger oder starker Schneefall/Schneeregen/Graupel/Hagel',
'95' => 'leichtes oder mäßiges Gewitter mit Regen oder Schnee',
'96' => 'leichtes oder mäßiges Gewitter mit Graupel oder Hagel',
'97' => 'starkes Gewitter mit Regen oder Schnee',
'98' => 'starkes Gewitter mit Sandsturm',
'99' => 'starkes Gewitter mit Graupel oder Hagel',
'100' => 'not available'
);
# Wetter Icons
if (!function_exists('wwPic')) {
function wwPic($Code, $bolSun, $intTagBeginn, $intTagEnde, $WT, $bolMaxT) {
# $intHour = date('H');
$intHour = $WT;
$bolDay = ($intHour > $intTagBeginn && $intHour < $intTagEnde);
switch ($Code) {
case 0:
# wenn Tag und heiss: 0h | wenn Tag: 0d | wenn Nacht: 0n
if ($bolDay == true and $bolMaxT == true) {
$icon = '0h';
} elseif ($bolDay == true) {
$icon = '0d';
} else {
$icon = '0n';
}
break;
case 1:
# wenn sonniger Tag: 1s | wenn Tag: 1d | wenn Nacht: 1n
if ($bolDay == true and $bolSun == true) {
$icon = '1s';
} elseif ($bolDay == true) {
$icon = '1d';
} else {
$icon = '1n';
}
break;
case 2:
# wenn sonniger Tag: 2s | wenn Tag: 2d | wenn Nacht: 2n
if ($bolDay == true and $bolSun == true) {
$icon = '2s';
} elseif ($bolDay == true) {
$icon = '2d';
} else {
$icon = '2n';
}
break;
case 3:
# wenn Tag: 3d | wenn Nacht: 3n
$icon = ($bolDay) ? '3d' : '3n';
break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
$icon = '4-9';
break;
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
$icon = '10-16';
break;
case 17:
$icon = '17';
break;
case 18:
$icon = '18';
break;
case 19:
$icon = '19';
break;
case 20:
$icon = '20';
break;
case 21:
$icon = '21';
break;
case 22:
$icon = '22';
break;
case 23:
case 24:
$icon = '23-24';
break;
case 25:
$icon = '25';
break;
case 26:
$icon = '26';
break;
case 27:
$icon = '27';
break;
case 28:
$icon = '28';
break;
case 29:
$icon = '29';
break;
case 30:
case 31:
case 32:
$icon = '30-32';
break;
case 33:
case 34:
case 35:
$icon = '33-35';
break;
case 36:
case 37:
case 38:
case 39:
$icon = '36-39';
break;
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 48:
case 49:
$icon = '40-49';
break;
case 50:
case 51:
case 52:
case 53:
$icon = '50-53';
break;
case 54:
case 55:
case 56:
case 57:
case 58:
case 59:
$icon = '55-59';
break;
case 60:
case 61:
case 62:
case 63:
case 64:
case 65:
$icon = '60-65';
break;
case 66:
case 67:
$icon = '66-67';
break;
case 68:
case 69:
$icon = '68-69';
break;
case 70:
case 71:
case 72:
case 73:
case 74:
case 75:
case 76:
case 77:
case 78:
case 79:
$icon = '70-79';
break;
case 80:
# wenn sonniger Tag: 80s | wenn Tag: 80d | wenn Nacht: 80n
if ($bolDay == true and $bolSun == true) {
$icon = '80s';
} elseif ($bolDay == true) {
$icon = '80d';
} else {
$icon = '80n';
}
break;
case 81:
$icon = '81';
break;
case 82:
$icon = '82';
break;
case 83:
case 84:
$icon = '83-84';
break;
case 85:
case 86:
case 87:
case 88:
$icon = '85-88';
break;
case 89:
case 90:
$icon = '89-90';
break;
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 97:
case 98:
case 99:
$icon = '91-99';
break;
// default
default:
$icon = 'unknown';
break;
}
return $icon.'.png';
}
}
# max. stündlich eine neue Datei ([Station]_[ISO-Datum]_[h]_dwdWeather.kmz) erstellen und alle alte [Station].* löschen
# Start------------------->
$strDatumStunde = date('Y-m-d_G');
$strZieldatei = $strTMP.$strStation.'_'.$strDatumStunde.'_dwdWeather.kmz';
if(!file_exists($strZieldatei)) {
array_map('unlink', glob($strTMP.$strStation.'*'));
# Datei per CURL abholen -Start------------------->
if (function_exists('curl_version')) {
$ch = curl_init($strURL);
$zieldatei = fopen($strZieldatei, 'w');
# deaktiviere SSL Überprüfung
# curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
# curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_FILE, $zieldatei);
curl_setopt($ch, CURLOPT_TIMEOUT, 3600);
curl_exec($ch);
$intReturnCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
fclose($zieldatei);
# prüfe ob die Seite erreichbar ist!
if ($intReturnCode != 200 && $intReturnCode != 302 && $intReturnCode != 304) {return 'ERROR: Page not available!';};
}
# Datei per CURL abholen -Ende--------------------<
} # max. stündlich -Ende-------------------<
# lösche Datei wenn die Dateigrösse 0 ist
clearstatcache();
if(0 == filesize($strZieldatei)) {
array_map('unlink', glob($strTMP.$strStation.'*'));
return 'ERROR: File is empty and due that deleted!';
}
# downloaded source data (*.kmz)
$fn = $strZieldatei;
$za = new ZipArchive();
$za->open($fn);
# Header-Infos
$stat = $za->statIndex(0);
$data = file_get_contents('zip://'.$strZieldatei.'#'.$stat['name']);
# Ort, Ausgabezeit und Lokation (für Sonnenaufgang und Sonnenuntergang Berechnung)
$xml2 = simplexml_load_string($data);
$xmlDocument = $xml2->children('kml', true)->Document;
$location = (string) $xmlDocument->Placemark->description;
$coordinates = (string) $xmlDocument->Placemark->Point->coordinates; # Bitburg "6.53,49.98,359.0"
$coordinates = explode(',', $coordinates);
$now = time();
# PHP 8.1: date_sunrise, date_sunset functions are deprecated (in PHP 9.0 will be removed) and replaced with date_sun_info
# $zenith = 90+50/60;
# $sunset = date_sunset($now, SUNFUNCS_RET_TIMESTAMP, $coordinates[1], $coordinates[0], $zenith);
# $sunrise = date_sunrise($now, SUNFUNCS_RET_TIMESTAMP, $coordinates[1], $coordinates[0], $zenith);
$suninfo = date_sun_info($now, $coordinates[1], $coordinates[0]);
$sunrise = $suninfo['sunrise'];
$sunset = $suninfo['sunset'];
$mycoordinates = $coordinates[1] .', '. $coordinates[0];
$dayduration = $sunset - $sunrise;
$sunrise = date('H:i',$sunrise);
$sunset = date('H:i',$sunset);
$dayduration = round($dayduration/60/60, 2);
$dayduration = str_replace(',', '.', $dayduration);
# Platzhalter Sonnenaufgang, Sonnenuntergang, Tageslänge und Koordinaten
$modx->setPlaceholder('sunrise', $sunrise);
$modx->setPlaceholder('sunset', $sunset);
$modx->setPlaceholder('dayduration', $dayduration);
$modx->setPlaceholder('coordinates', $mycoordinates);
$pubDate = (string) $xmlDocument->ExtendedData->children('dwd', true)->ProductDefinition->IssueTime;
$pubDate = strtotime($pubDate) + $timeOffset;
$pubDateDay = date('w', $pubDate);
$pubDate = date('Y-m-d H:i', $pubDate);
$wochentag = array('So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.');
$pubDateDay = $wochentag[$pubDateDay];
# Platzhalter Ort, Koordinaten und Veröffentlichungsdatum
$modx->setPlaceholder('location', $location);
$modx->setPlaceholder('pubDate', $pubDate);
$modx->setPlaceholder('pubDateDay', $pubDateDay);
# short name / long name (for header)
# RR6c not available for all hours! 6am, 12am, 6pm and 12pm - if needed for all hours: change all RR6c to RR1c
# RR6c = better precipitation forecasts
$alias = array(
'TN' => 'minT', // Minimum temperature - within the last 12 hours (Kelvin) | nur 06:00 und 18:00 Uhr!
'TX' => 'maxT', // Maximum temperature - within the last 12 hours (Kelvin) | nur 06:00 und 18:00 Uhr!
'TTT' => '2mT', // Temperature 2m above surface (Kelvin)
'Td' => 'dewPoint', // Dewpoint 2m above surface (Kelvin)
'DD' => 'windDir', // 0°..360°, Wind direction
'FF' => 'windSpeed', // Wind speed (m/s) | m/s * 3.6 = km/h
'FX3' => 'windGust', // Wind speed (m/s) | m/s * 3.6 = km/h
'Neff' => 'cloud', // Effective cloud cover (%)
'PPPP' => 'hPA', // Surface pressure, reduced | hPA (mBAR)= Pa/1000
'RRdc' => 'rainKG24h', // Total precipitation last 24 hour consistent with significant weather | Niederschlag 1 Ltr pro kg/m2 = 1 mm
'RR6c' => 'rainKg6h', // Total precipitation last 6 hour consistent with significant weather | Niederschlag 1 Ltr pro kg/m2 = 1 mm
'SunD3' => 'sun', // Sunshine duration during the last three hours (s)
'VV' => 'vis', // Visibility (m) | wird in km umgerechnet
'ww' => 'sigW' // Significant Weather (ID)
);
$ids = array_keys($alias);
for($i=0; $i<$za->numFiles; $i++) {
$stat = $za->statIndex($i);
$data = file_get_contents('zip://'.$strZieldatei.'#'.$stat['name']);
$data = str_replace(
array("kml:", "dwd:"),
array("", ""),
$data
);
$xml = simplexml_load_string($data);
$timeSteps = xml2array($xml->Document->ExtendedData->ProductDefinition->ForecastTimeSteps->TimeStep);
$lines = array_fill(0, count($timeSteps), array());
# Datum (ISO) | Zeit | Wochentag
foreach ($timeSteps as $key => $value) {
$date = new DateTime($value);
array_push($lines[$key], $date->format('Y-m-d'));
array_push($lines[$key], $date->format('H:i'));
array_push($lines[$key], $wochentag[$date->format('w')]);
} // $timeSteps
$fnode = $xml->Document->Placemark->ExtendedData->Forecast;
foreach ($ids as $id) {
$param = getParamArray($fnode, $id);
if(is_array($param)){
if (count($param) === 0) {
$param = array_fill(0, count($timeSteps), '---');
}
} else {
# PHP7.2 prevents warning: "Parameter must be an array or an object that implements Countable"
$param = array_fill(0, count($timeSteps), '---');
}
foreach ($param as $key => $value) {
# prevents PHP warning "a non-numeric value encountered"
if($value !== null && !is_numeric($value)) {
$value = 0;
}
$v = $value;
if (in_array($id, array('TN', 'TX', 'TTT', 'Td'))) {
$v = round(floatval($value) - 273.15, 1);
$v = str_replace(',', '.', $v);
}
if ($id == 'PPPP') {
$v = round($value / 100, 0);
}
if (in_array($id, array('Neff', 'Nh', 'Nm', 'Nl', 'ww'))) {
$v = round($value);
}
if (in_array($id, array('RRhc', 'RRdc', 'RR6c'))) {
$v = round($value, 1);
$v = str_replace(',', '.', $v);
}
if ($id == 'VV') {
$v = round(floatval($value) / 1000, 2);
$v = str_replace(',', '.', $v);
}
if ($id == 'ww') {
$v = $strConditions_de[$v];
}
if ($id == 'DD') {
$v = getWindDirection(round($value));
}
if (in_array($id, array('FF', 'FX3'))) {
$v = round(floatval($value) * 3.6);
}
# Returns an array with units
if (in_array($id, array('TN', 'TX', 'TTT', 'Td'))) {
$v = $v.' °C';
}
if (in_array($id, array('FF', 'FX3'))) {
$v = $v.' km/h';
}
if ($id == 'Neff') {
$v = $v.' % (effektiv)';
}
if ($id == 'SunD3') {
# Zeit umrechnen in %/3h
$v = floatval($v) / 3600;
$v = round($v * 100 / 3);
$v = $v.' %';
}
if ($id == 'DRR1') { # 1h
$v = $v / 60;
$v = $v.' min/h';
}
if ($id == 'RRdc') { # 24h
$v = $v.' Ltr/24h';
}
if ($id == 'RRhc') { # 12h
$v = $v.' Ltr/12h';
}
if ($id == 'RR6c') { # 6h
$v = $v.' Ltr/6h';
}
if ($id == 'PPPP') {
$v = $v.' hPA';
}
if ($id == 'VV') {
$v = $v.' km';
}
if ($id == '-') {
$v = '---';
}
array_push($lines[$key], $v);
}
}// foreach $ids
// get Picture No (Significant Weather - ww)
// get Sun (SunD3)
// get Temp (TTT)
// get Weather Time ($WT) | Uhrzeit
$ww = getParamArray($fnode, 'ww');
$rs = getParamArray($fnode, 'SunD3');
$ttt = getParamArray($fnode, 'TTT');
foreach ($ww as $key => $value) {
# $intW = round(floatval($ww[$key]));
$valTTT = round(floatval($ttt[$key]) - 273.15, 1);
$intS = round(floatval($rs[$key]));
# Zeit umrechnen in %/3h
$intS = floatval($intS) / 3600;
$intS = round($intS * 100 / 3);
if($intS >= $intSun) {
$bolSun = true;
}
else{
$bolSun = false;
}
if($valTTT >= $valMaxT) {
$bolMaxT = true;
}
else{
$bolMaxT = false;
}
# für Wetter Icons (Tag oder Nacht)
$tr = strtotime($sunrise);
$tr = intval(date('G',$tr));
$intTagBeginn = $tr - 1;
$ts = strtotime($sunset);
$ts = intval(date('G',$ts));
$intTagEnde = $ts + 1;
$WT = strtotime($lines[$key][1]); # Uhrzeit
$WT = intval(date('G',$WT));
array_push($lines[$key], $strURLIcon.wwPic(round(floatval($value)), $bolSun, $intTagBeginn, $intTagEnde, $WT, $bolMaxT));
}
// berechnen der Luftfeuchtigkeit
// calculate humidity (hu %)
$t = getParamArray($fnode, 'TTT'); # Temperature 2m above surface
$d = getParamArray($fnode, 'Td'); # Dewpoint 2m above surface
foreach ($t as $key => $value) {
array_push($lines[$key], getHumidity($value, $d[$key]).' %');
}
$csvOutput = '';
// output header
# $csvOutput = str_replace(
# array_keys($alias),
# array_values($alias),
# 'Date|Time|Tag|'.implode('|', $ids).'|pic'.'|hu'.'||'
# );
// slice & output content
$lines = array_slice($lines, 0, $MAX_COUNT);
foreach ($lines as $line) {
if ($fcAll == 'false'){
if ($line[1] == $time1 or $line[1] == $time2 or $line[1] == $time3 or $line[1] == $time4){
$csvOutput = $csvOutput. implode('|', $line).'||';
}
} else {
$csvOutput = $csvOutput. implode('|', $line).'||';
}
}
} // END numFiles
# echo $csvOutput;
# mehrdimensionales Array erstellen
$array = array_map(function($v){return str_getcsv($v, '|');}, explode('||', $csvOutput));
# print_r($array);
$intCA = count($array) -1;
unset($array[$intCA]); # RIP last array (it is empty)
# Luftdrucktendenz - Zeitdifferenz in Stunden zwischen den 2 Messungen
$tPa1 = strtotime($array[0][0].' '.$array[0][1]);
$tPa2 = strtotime($array[1][0].' '.$array[1][1]);
$tPaDelta = $tPa2 - $tPa1;
$intStundenPaDelta = round($tPaDelta/60/60, 0);
# Luftdrucktendenz (Stabil wenn hPa Delta kleiner als $intPStable)
$hPa1 = intval($array[0][11]);
$hPa2 = intval($array[1][11]);
$hPaDelta = $hPa2 - $hPa1;
$hPaDeltaABS = abs($hPaDelta);
# bei positiven hPaDelta ein Pluszeichen für die Ausgabe setzen
if ($hPaDelta > 0) {
$hPaDelta = sprintf("%+d",$hPaDelta);
}
if ($hPaDeltaABS > $intPStable) {
if ($hPa1 > $hPa2) {
$strPTendenz = 'fallend';
} else {
$strPTendenz = 'steigend';
}
$modx->setPlaceholder('pDelta', '('.$hPaDelta.' hPa/'.$intStundenPaDelta.'h)');
} else {
$strPTendenz = 'stabil';
$modx->setPlaceholder('pDelta', '');
}
$modx->setPlaceholder('pTendenz', $strPTendenz);
$output = '';
$arr = '';
$arr = array();
$arr2 = '';
$arr2 = array();
foreach ($array AS $key => $value) {
if ($key >= $intQTY) break;
foreach ($value AS $subKey => $subValue) {
# echo $key.' | '.$subKey.' | '.$subValue.'<br>';
# Platzhalter (z.B. für Kalender)
$modx->setPlaceholder('fc_'.$key.'_'.$subKey, $subValue);
# Array für getChunk (kann per Platzhalter [[+dwdWeather]] platziert werden)
$arr = ['FC' => $key, 'fc'.$subKey => $subValue];
$arr = $arr + $arr2;
$arr2 = $arr;
}
if ($arr) {
$output .= $modx->getChunk($strTPL, $arr);
}
}
$modx->setPlaceholder('dwdWeather', $output);
[[!dwdWeather?
&STATION=`K428`
&QTY=`20`
&TPL=`dwdWetterTPL`
&T1=`[[!getTimeRoundH]]`
&T2=`[[!getTimeRoundH? &add=`6`]]`
&T3=`[[!getTimeRoundH? &add=`12`]]`
&T4=`[[!getTimeRoundH? &add=`18`]]`
]]
<?php
# get time and round hour
# Uhrzeit für das Wetter auf die volle Stunde aufrunden, aus "10:42" wird dann "11:00"
# z.B. [[!getTimeRoundH]] oder plus 4h [[!getTimeRoundH? &add=`4`]]
$timestamp = time();
$timestamp = ceil($timestamp/3600)*3600;
if (isset($add)) {
$timestamp = $timestamp + ($add * 3600); # 3600 = 1h
}
return date('H:i', $timestamp);
cd ~/Downloads
wget http://releases.libreelec.tv/LibreELEC.USB-SD.Creator.Linux-64bit.bin
chmod +x LibreELEC.USB-SD.Creator.Linux-64bit.bin
sudo ./LibreELEC.USB-SD.Creator.Linux-64bit.bin