LibreOffice: Inhalts- und Stichwortverzeichnis automatisch aktualisieren

Sunday, November 4, 2018

Die Verzeichnisse wie Inhalts- oder Stichwortverzeichnis in einem LibreOffice Writer Dokument, können beim Speichern oder Exportieren automatisch aktualisiert werden. Dazu verknüpft man folgendes Makro an die Ereignisse Dokument speichern und Dokumentkopie speichern oder exportieren.

Den Dialog dazu findet man unter Extras/Makros/Bearbeiten und für das Zuweisen unter Extras/Makros/Verwalten/LibreOffice Basic/Zuweisen.

loMakroDocumentIndexesUpdate1.png

loMakroDocumentIndexesUpdate2.png

Das Makro

REM  *****  BASIC  *****

Sub Main

End Sub	

REM Verzeichnisse aktualisieren
REM Siehe auch: https://www.oooforum.de/viewtopic.php?f=18&t=70890
REM             https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=2557
Sub DocumentUpdateIndexes
	If Not thisComponent.supportsService ("com.sun.star.text.GenericTextDocument") Then
		Exit Sub
	End If

	oIndexes = ThisComponent.getDocumentIndexes()
	for i = 0 to oIndexes.getCount () - 1
		oIndexes (i).update
	next i
End Sub

Sub DokumentSpeichern
	DocumentUpdateIndexes
End Sub

Sub DokumentkopieSpeichernOderExportieren
	DocumentUpdateIndexes
End Sub

Dresden

Saturday, October 13, 2018

Liebe Eve,

vielen Dank für die Städtereise nach Dresden :-)

frauenkirche-luther.jpg

Martin Luther vor der Frauenkirche

moschee.jpg

Moschee…

goldener-reiter-1.jpg
goldener-reiter-2.jpg

Goldener Reiter

Gegen die Sonne fotografiert, schaut es fast wieder wie eine Feuervergoldung aus

IMG-20181011-WA0096.jpg

20181010_172816.jpg

Dresden Altstadt

konsum.jpg
trabant.jpg

Ostalgie^^

raddampfer.jpg

Raddampfer (Reederei Dresden)

dresden-neustadt1.jpg
dresden-neustadt2.jpg
dresden-neustadt3.jpg

Dresden Neustadt

fernsehturm.jpg

Fernsehturm

PhantomJS/listlinks: Alle Hyperlinks einer Website auflisten, mit Unterstützung für JavaScript und Frames

Friday, June 1, 2018

Das folgende PhantomJS-Skript listlinks.js, listet alle Hyperlinks einer Website auf, wobei JavaScript und Frames unterstützt werden.

Damit ist es z.B. möglich…

  • sich über Gratisaktionen von Steam Informieren lassen (Free Weekend/Free For a Limited Time)
  • Werbebanner von Google Ads/Ad Scence automatisiert anklicken

Hinweis: Mittlerweile auch als Projekt auf Github zu finden: https://github.com/1nn3/listlinks

#!/usr/bin/phantomjs
// listlinks.js
// Lists all hyperlinks of an URL, supports JavaScript and Frames
// See also: http://phantomjs.org/api/
"use strict";

// Um Endlosrekursion in der Frametiefe zu erkennen und abzufangen
// FIXME: Make it a constant
// const FRAME_RECURSION_MAX_DEPTH = 10;
// SyntaxError: Unexpected token 'const'
// See: https://github.com/ariya/phantomjs/issues/14521
var FRAME_RECURSION_MAX_DEPTH = 10;

function getAttributesFromAllElementsByTagName(tagName, attributeList) {
	var elements = window.document.getElementsByTagName(tagName);

	var values = [];
	for (var i = 0; i < elements.length; i++) {
		values.push({});

		for (var j = 0; j < attributeList.length; j++) {
			values[i][attributeList[j]] = elements[i].getAttribute(attributeList[j]) || "";
		}

		values[i]["textContent"] = elements[i].textContent || "";
	}
	return values;
}

function listLinks () {
	var a = page.evaluate(getAttributesFromAllElementsByTagName, "a", ["href"]);

	for (var i = 0; i < a.length; i++) {
		// FIXME: Use the class URL to get an absolut URL
		// See: https://github.com/ariya/phantomjs/issues/14349
		var href = new URL(a[i]["href"], page.url).href || a[i]["href"];
		var textContent = a[i]["textContent"].replace(/\s+/g, " ");
		system.stdout.writeLine(href + "\t" + textContent);
	}
}

function getFrames (parrents) {
	var a = page.evaluate(getAttributesFromAllElementsByTagName, "iframe", []);

	var frames = [];
	for (var i = 0; i < a.length; i++) {
		frames.push(parrents.concat([i])); // frame position
	}
	return frames;
}

function walkThroughFrames (frames) {
	for (var i = 0; i < frames.length; i++) {
		system.stderr.writeLine("I: Switching to frame: " + frames[i].toString() + " frameName=" + page.frameName + " frameURL=" + page.frameUrl);

		if (frames[i].length > FRAME_RECURSION_MAX_DEPTH) {
			system.stderr.writeLine("W: FRAME_RECURSION_MAX_DEPTH reached!");
			continue;
		}

		page.switchToMainFrame();
		for (var j = 0; j < frames[i].length; j++) {
			page.switchToFrame(frames[i][j]);
		}

		listLinks();
		walkThroughFrames(getFrames(frames[i])); // subframes
	}
}

var system = require('system');

if (system.args.length != 2) {
	system.stderr.writeLine("Usage: " + system.args[0] + " <url>");
	phantom.exit(1);
}

var page = require("webpage").create();
page.settings.javascriptEnabled = true
page.settings.userAgent = system.env["LISTLINKS_USER_AGENT"] || "";

page.open(system.args[1], function (status) {
	if (status !== "success") {
		system.stderr.writeLine("E: Fail to load URL: " + system.args[1]);
		phantom.exit(1);
	}

	listLinks();
	walkThroughFrames(getFrames([]));
	phantom.exit(0);
});

Download: fp-content/attachs/listlinks.js

Zur Installation laden das Skript nach /usr/local/bin/ herunter und machen es ausführbar. Dies ist für die Beispiele unten notwendig!

# wget -O /usr/local/bin/listlinks https://0010100.net/blog/fp-content/attachs/listlinks.js
# chmod +x /usr/local/bin/listlinks

Benutzt wird es dann so:

$ listlinks <URL>

Sich über Gratisaktionen von Steam Informieren lassen (Free Weekend/Free For a Limited Time)

Mit dem Shell-Skript free-games-on-steam.sh, kann man sich über Gratisaktionen von Steam informieren lassen (Free Weekend/Free For a Limited Time). Dazu erstellt man einen Cronjob: @hourly free-games-on-steam 2>/dev/null

So bekommt man alle neuen Gratisaktionen via Mail mitgeteilt.

#!/bin/sh

set -e

seen="${XDG_CACHE_HOME:-$HOME/.cache}/free-games-on-steam.seen"
listlinks="$(which listlinks)"
url="https://store.steampowered.com/news/?headlines=1"

mkdir -p "$(dirname "$seen")"
touch "$seen"

xvfb-run --auto-servernum "$listlinks" "$url" | cut -f 2 | grep -i -w "free" | while read REPLY; do
	if grep -q --line-regexp "$REPLY" "$seen"; then
		continue
	fi

	echo "$REPLY" | tee --append "$seen"
done

cut-cache "$seen"

Download: fp-content/attachs/free-games-on-steam.sh

Werbebanner von Google Ads/Ad Scence automatisiert anklicken

Mit dem Shell-Skript gadclick.sh, können Werbebanner von Google Ads/Ad Scence automatisiert anklicken werden. Das funktioniert allerdings nicht immer/mit allen Websites (Ich tippe mal auf ein Timing-Problem o.ä.).

#!/bin/sh

set -e

temp="$(/bin/mktemp --tmpdir=/dev/shm/)"
trap "rm -f -- '$temp'" 0 1 2 3 15 # Lösche Datei beim Beenden, Abbruch ...

listlinks="$(which listlinks)"
log="${XDG_CACHE_HOME:-$HOME/.cache}/gadclick.log"
sites="${XDG_CONFIG_HOME:-$HOME/.config}/gadclick.sites"

mkdir -p "$(dirname "$log")"
touch "$log"

get_gad() {
	local website="${1:-http://www.example.net}"
	xvfb-run --auto-servernum "$listlinks" "$website" | cut -f 1 >"$temp" \
		&& cat <<! | grep -E -f - "$temp" | shuf -n 1
^https?://adclick\.g\.doubleclick\.net/
^https?://googleads\.g\.doubleclick\.net/
^https?://www\.googleadservices\.com/
!
}

shuf "$sites" | while read REPLY; do
	if ! wget -qO "/dev/null" "$(get_gad "$REPLY")"; then
		date +"%D %T	0	$REPLY" >>"$log"
		continue
	else
		date +"%D %T	1	$REPLY" >>"$log"
	fi
done

cut-cache "$log"

Download: fp-content/attachs/gadclick.sh

cut-cache

#!/bin/sh
# Cache kürzen
# cut-cache <path/to/cachefile> [keep [threshold]]

set -e

cachefile="$1"
keep="${2:-100}"
threshold="${3:-500}"

if test "$( cat "$cachefile" | wc -l )" -gt "$threshold"; then
	temp="$(mktemp)"
	tail -n "$keep" "$cachefile" >"$temp"
	mv "$temp" "$cachefile"
fi

Download: fp-content/attachs/cut-cache.sh

Wie die anderen Skripte auch, kann cut-cache.sh nach /usr/local/bin/ installiert und ausführbar gemacht werden:

$ wget -O /usr/local/bin/listlinks https://0010100.net/blog/fp-content/attachs/listlinks.js
$ wget -O /usr/local/bin/free-games-on-steam https://0010100.net/blog/fp-content/attachs/free-games-on-steam.sh
$ wget -O /usr/local/bin/gadclick https://0010100.net/blog/fp-content/attachs/gadclick.sh
$ wget -O /usr/local/bin/cut-cache https://0010100.net/blog/fp-content/attachs/cut-cache.sh
$ chmod +x /usr/local/bin/{listlinks,free-games-on-steam,gadclick,cut-cache}

Anhang: Weitere Lösungen mit Selenium

Die Skripte nutzen z.Z. Chromium, aber Firefox sollte auch funktionieren (entsprechenden Code aktivieren).

PhantomJS funktioniert z.Z. nicht (könnte aber einzurichten sein):

Message: Error - Unable to load Atom ‘find_elements’ from file ‘:/ghostdriver/./third_party/webdriver-atoms/find_elements.js’

DLNA mit minidlna

Sunday, May 27, 2018

Was ist DLNA? Die Digital Living Network Alliance (DLNA) ist ein festgelegter Standard/Netzwerkprotokoll für Geräte wie Mediaplayer, SmartTV oder Smartphones und definiert eine Norm für die Bild-, Ton- und Videoübertragung. So das alle zertifizierten Geräte die Daten abspielen können.

Der Server (hier MiniDLNA) kodiert dafür ggf. die Daten neu und stellt diese dann als Stream bereit (Mindestanforderung für die Datenübertragung ist dabei JPEG, lineare PCM-Ton und MPEG-2. Wobei wichtiger ist, welche Formate der Server einlesen kann).

minidlna einrichten

Mein Setup besteht aus diesen zwei Paketen: minidlna und bindfs

# apt-get install minidlna bindfs

Hat man seine Multimediasammlung z.B. unter /var/local/nas/ gespeichert, hängt man dieses Verzeichnis mittels bindfs ins Verzeichnis /var/lib/minidlna ein. Dies ist das Standardverzeichnis, wo nach Dateien gesucht wird:

# cat <<! >>/etc/fstab
/var/local/nas /var/lib/minidlna fuse.bindfs force-user=minidlna,force-group=minidlna,perms=0000:u=rD 0 0
!
# mount /var/lib/minidlna
# minidlnad -R # Dateien neu in die Datenbank einlesen

Der Server läuft unter Debian als Prozess minidlnad mit der UID minidlna und hat so auf das Verzeichnis /var/lib/minidlna nur lesenden Zugriff.

Die Einteilung in Fotos, Musik und Videos passiert dabei automatisch.

Immer wenn sich der Verzeichnisinhalt von /var/lib/minidlna geändert hat, muss mittels minidlnad -R bzw. minidlnad -r, die Datenbank aktualisiert werden (MiniDLNA hat aber auch inotify Unterstützung aktiviert, um neu hinzugefüge Dateien zu indizieren).

Eine eventuell eingerichtete Firewall, muss mindestens die Ports 8200/TCP und 1900/UDP zulassen.

GNOME

Die Denktopumgebung GNOME hat in den Einstellungen unter Freigabe/Medienfreigabe eine eigene integrierte Möglichkeit um Fotos, Musik und Videos über das Netzwerk mittels DLNA freizugeben (Es können auch benutzerdefinierte Verzeichnisse freigegeben werden). Fehlt diese Einstellung, muss rygel installiert werden.
Hier wird minidlna i.d.R. nicht gebraucht.

gnome-rygel.png

Fehlerbehandlung

Läuft der MiniDLNA Server, wird dieser über das Netzwerk meist als neue Eingangsquelle/Source/Input bei den Clients angezeigt.

Bei Problemen ist das folgende Kommando nützlich, um eine Fehlermeldung zu bekommen:

# service minidlna restart
# journalctl -f -u minidlna # Log anzeigen

Wie Städte subtil gegen Obdachlose vorgehen

Sunday, May 6, 2018

Damit Obdachlose an bestimmten Stellen zum Beispiel an Tourismus-Hotspots nicht mehr übernachten, haben sich bestimmte Methoden etabliert den öffentlichen Raum dementsprechend zu gestalten.

20180506_bank_Sandra-Schindlauer_banner.jpg

So werden u.a. Bänke in der Mitte mit Armlehnen versehen, sodass Obdachlose darauf nicht mehr schlafen können.

Mehr dazu im Artikel auf www.deutschlandfunknova.de: Wie Städte subtil gegen Obdachlose vorgehen von Sandra Wolf, Geografin.