request_url_withoutHTTP=,canonical_url_withHTTP=,canonical_url_withoutHTTP=,request_url_withoutHTTP_realspaces=. Ruby (Seite 1 von 1) « Tags « Blog « Bernhard Häussner
Bernhard Häussner
Tags: Artikel mit dem Tag «Ruby» durchstöbern

Nazareth Knot: Generate SVG drawings using ERB

11.05.2016, 11:05

The Nazareth Knot is an ancient drawing in found in a church in Bethlehem (duh!). It is really a nice byzantine knot that reminds us of the very similar keltic knots. Of course I wanted to recreate it. First of all, I took a photo of the original mosaic. Then I made a pen-and-paper sketch of it to get a better intuition of the workings of this knot. And finally I created an SVG image, which is what this blog post is all about.

I did some calculations in Ruby and generated the SVG using ERB code. I really enjoyed playing with Ruby's array methods like map, zip, flatten, each_cons, each_slice and repeated_permutation. If you don't know what those method do, I would reccomment to look at the documentation of the Enumerable mixin, they are really useful. For developing I wrote a tiny script that renders the ERB into proper HTML, whenever the code changes using fswatch. It also displays errors on the page when something goes wrong. Happens to the best. Also I monkey-patched Ruby's Matrix class with some 2D affine transformation-foo for all the calculations. Also, I used copies of the paths and the stroke-dasharray CSS property to create the interweaved strings, as you can see on the web page.

The Ravello Knots are based on a mosaic found in a church in Ravello, Italy. The city is one of the most beautiful towns along the Amalfi Coast, mostly for its wonderful gardens. I found the knot a long time ago while travelling to Italy, I already „harvested“ this knot then, since I created a computer graphic of the original knot and later did a drawing of a slight modification to my sketchbook.

Since I wanted to continue exploring the SVG creations more I was looking for old sketches to refresh and the knot from Ravello came to my mind. I not only did a nice SVG drawing of the old sketch but took it further to create a totally new variation showing off the stroke-dasharray technique in a most spectacular way.

You can find all the code in the Git-Hub-Repository bxt/Nazareth-Knot.

Kommentare: keine

Qt4 Designer und Ruby - erste Schritte

06.01.2010, 11:23

Vor Kurzem habe ich ein bisschen mit Ruby herumgespielt und festgestellt, dass es keine ordentliche und aktuelle Kurzeinführung gibt, wie man die Interfaces aus dem Qt4 Designer mit Ruby Programmen verbindet. Darum habe ich die ersten Schritte hier kurz zusammengefasst:

Als erstes installiert man die Qt4-Development-Tools und die Ruby-Qt-Komponenten mit dem Paketmanager.

Interface im Qt4 Designer erstellen

Dann kann man sich ans Buttons zusammenklicken machen. Das Beispielinterface sieht im Qt Designer so aus:

Ich habe zwei QPushButtons und ein QListWidget in Layouts gepackt. Was es an Widgets gibt und was diese können steht in der Qt4 Dokumentation. In der Ruby API heißen die Klassen stets Qt::Name stat QName. Beim Basteln wichtig ist, dass ObjectName irgendwie Sinn hat, weil damit die Widgets dann benutzt werden können.

Rubycode mit rbuic erstellen

Als nächstes muss man die vom Designer erzeugte XML-Datei mit der Endung .ui in Ruby-Code umwandeln. Dazu gitb es rbuic bzw. rbuic4:

rbuic4 Sample.ui -o Sample.ui.rb

Jetzt haben wir ein Rubyscript in dem das Interface erstellt wird.

Interface in Rubyscript einbinden

Jetzt ist es Zeit dem Interface etwas Leben einzuhauchen. Dazu verbindet man die Signale - wer Webinterfaces Programmiert kennt das als „Events“ - mit den Entsprechenden Slots, die so ähnlich wie callbacks funktionieren. Das geht recht fix mit QMetaObject::connectSlotsByName. Damit dies funktioniert müssen die Funktionen, die aufgerufen werden sollen das Namensmuster on_ObjectName_Signal einhalten, wobei der ObjectName vorher im Designer festgelegt wurde und das Signal heißt z.B. triggered.

Wie man die GUI-Komponente in der Anwendung benutzt, z.B. hier durch Subclassing, und anderes will ich direkt am Beispiel erklären:

#!/usr/bin/ruby

#Laden der Qt-Klasse:
require 'Qt'

#Manchmal auch:
#require 'Qt4'

#Laden des generierten Interfaces:
require 'Sample.ui.rb'

#Initialisieren der Anwendung
app = Qt::Application.new ARGV

#Eine Klasse, um das Verhalten des Interfaces festzulegen:
class AppCommunicate < Qt::MainWindow
  #Die Liste der Slots
  #Sie werden von setupUi automatisch verbunden
  slots :on_actionQuit_triggered, :on_add_clicked, :on_rem_clicked
  def initialize
    puts "init"
    @item_count=0
    #Da wir vererben initialisieren wir so:
    super
    #Jetzt erstellen wir das Interface
    @ui=Ui_MainWindow.new
    #Und weisen es dem MainWindow zu
    @ui.setupUi self
    #Man könnte Slots auch manuell verbinden:
    #connect a.actionQuit, SIGNAL('triggered()'), $qApp, SLOT('quit()')
  end
  #Ein Handler für das Beenden:
  def on_actionQuit_triggered
    puts "Shutting down."
    #So wird die Anwendung gestoppt:
    $qApp.quit
  end
  # "add" ist der name des Buttons, bei click wird dieses signal gesendet
  def on_add_clicked
    puts "Adding item"
    #Es gibt attr_readers für alle Widgets
    #So können wir ihre Methoden aufrufen
    @ui.listWidget.addItem("Hallo Welt ##{@item_count} at #{Time.now.ctime}")
    #Hier könnten z.B. Daten der Anwendung ausgegeben werden
    #Zu demonstrationszwecken nummerieren wir die Einträge sichtbar
    @item_count+=1
  end
  def on_rem_clicked
    puts "Removing item"
    #In cpp könten wir die items deleten
    #Aber in ruby loopen wir über die markierten indizes
    @ui.listWidget.selectedIndexes.each do |i|
      #und nehmen sie aus der Liste
      @ui.listWidget.takeItem i.row
      #da wir keine Referenz speichern löscht sie der GC
    end
  end
end

#Wir erstellen eine Instanz unseres Verhaltens
wdg=AppCommunicate.new do |w|
    #Wir müssen das Interface zeigen
    #Wird auch alle child-widgets zeigen
    w.show
end

#Hier wird die GUI-Schleife gestartet:
app.exec

#TADA!

Wer das ganze ausprobieren will, kann sich die Beispieldateien hier herunterladen:

Ich hoffe das war hilfreich, ich finde es doch hin und wieder ganz nett ein Interface zu haben, vor allem für Scripte, die länger laufen und interaktiv sein sollen.

Kommentare: keine

XMPP (Jabber) mit Ruby am Beispiel FelicianXMPPBot

15.12.2009, 21:53
FelicianXMPPBot in action

FelicianXMPPBot in action

Das Protokoll XMPP für den (Nahezu-)Echtzeitaustausch von XML-Nachrichten (meist verwendet für IM, als „Jabber“) steht in Konkurrenz und Verbindung mit einigen aktuell mehr oder weniger neuen Technologien, die mit XML und realtime zu tun haben, wie RSS/Atom pings, realtime web oder AJAX. Und ein paar Spielereien auf diesem Gebiet können sicher nicht schaden, also habe ich mit XMPP etwas herumgebastelt.

Weil dies mit PHP irgendwie seltsam wäre und David Strohmayers Text und Präsentation über XMPP mit Java noch nicht existierte, habe ich das ganze mit Ruby gebastelt, da gibt es nämlich den Gem xmpp4r, der mit vielen Beispielen kommt. So konnte ich mal ein bisschem mit Ruby herumspielen. (Zwei Fliegen mit einer Klappe usw.)

Aus den Experimenten ist ein kleiner Server geworden, der einen Jabber-Bot betreibt und über ein einfaches TCP-Protokoll erreicht werden kann, sodass aus allen TCP-Fähigen Skripten (bash mit netcat, PHP…) einfach Nachrichten an einen Jabber-Endpunkt versendet werden können.

Code und Funktionalität bestehen aus drei Teilen:

Die Klasse Netx kümmert sich um den TCP-Server und parst das einfache Protokoll: Man schickt Zeilen und beendet einzelne Nachrichten mit einem Punkt, und die Verbindung (und damit auch die aktuelle Nachricht) mit zwei Punkten. So lassen sich die TCP-Clients leicht implementieren.

Die Klasse XmppRoute bietet nur ein wenig Grundfunktion für den Jabber-Bot. Sie vereinfacht Verbinden und Senden noch weiter, zudem extrahiert sie beim Empfang einer Nachricht einen Befehlsteil.

Der Rest kümmert sich um die Verbindung der beiden Komponenten und um das Parsen von Startup-Parametern.

Aber genug der vielen Worte, jetzt folgt der Code:

jabot.rb

#!/usr/bin/ruby

# Felician 0.9 - XMPP Wrapper
# (c) 2009 by Bernhard Häussner
# Licence: GPLv2+ http://www.gnu.org/licenses/gpl-2.0.txt
#
# This jabber wrapper will recieve messages via simple tcp.
#
# Quit by sending "exit" via jabber. 
# Send "info" via jabber to get running parameters. 
# Send "feedback [msg]" via jabber to post from jabber. 
# Connect to specified port and send messages terminated by lone "." in a line to post via TCP. 
# Send a line with ".." to quit connection. 
#
# Based on xmpp4r-0.5/data/doc/xmpp4r/examples/basic
#

require 'optparse'
require 'XmppRoute'
require 'Netx'

class FelicianXMPPBot
  def start(his_JID,my_txt_JID,my_password,listen_port)
    puts "FELC: Started. Sending to #{his_JID} from #{my_txt_JID} listening to #{listen_port}."
    my_JID=JID.new(my_txt_JID)
    netx=Netx.new
    XmppRoute.connect(my_JID,my_password) do
      on_recieve do |from,cmd,param|
        if from.strip.to_s.eql?his_JID then
          case cmd.downcase
            when 'exit' then
              send(from,"-> I've got to go!")
              puts "FELC: Got shutdown signal, waiting for children to terminate..."
              netx.halt
            when 'feedback' then send(from,param)
            when 'info'then send(from,"-> Felician sending to #{his_JID} listening to #{listen_port}. ")
            else send(from,"-> I don't know: #{cmd} #{param}")
          end
        else
          puts "XMPP: Ignored a message. "
          send(from,"Hi, #{from.strip.to_s}. Sorry, could not be deliverd. Try again later! ")
        end
      end
      
      netx.on_sended do |msg|
        send(his_JID,msg.strip)
        puts "XMPP: Client message sent. "
      end
      netx.listen(listen_port)
    end
    puts "FELC: Shutting down. "
  end
end

if $0 == __FILE__
  #defaults:
  listen_port=2000
  his_JID = "bot_admin@gmx.de"
  my_txt_JID = "i_am_a_bot@jabber.ccc.de/felician"
  my_password = "top_secret"
  # cli settings
  OptionParser.new do |opts|
  opts.banner = 'Usage: ruby jabot.rb -j jid/ressource -p password -t reciever_jid -l port'
  opts.separator ''
  opts.on('-j', '--jid JID', 'sets the sender jid') { |j| my_txt_JID = j }
  opts.on('-p', '--password PASSWORD', 'sets the sender password') { |p| my_password = p }
  opts.on('-t', '--to-jid JID', 'sets the message reciever') { |t| his_JID = t }
  opts.on('-l', '--listen PORT', 'sets the server listen port') { |l| listen_port = l }
    opts.on_tail('-h', '--help', 'Show this message') {
    puts opts
    exit
  }
  opts.parse!(ARGV)
  end
  FelicianXMPPBot.new.start(his_JID,my_txt_JID,my_password,listen_port)
end

XmppRoute.rb

require 'rubygems'
require 'xmpp4r/client'
include Jabber

class XmppRoute
  def initialize(jid,pwd)
    @cmd=Proc.new { |a,b,c| puts "XMPP: No reciever. " }
    @cl = Client.new(jid)
    @cl.connect
    @cl.auth(pwd)
    @cl.send(Presence.new)
    puts "XMPP: Connected! send messages to #{jid.strip.to_s}."
    @cl.add_message_callback { |m| process m }
  end
  def close
    @cl.close
  end
  def on_recieve(&cb)
    @cmd=cb
  end
  def send(to,mes)
    ms = Message.new(to,mes) # [_CY4_L8-R_4LLY-G4T3-R_]
    ms.type = :chat
    @cl.send(ms)
  end
  private
  def process(m)
    puts "XMPP: Got msg of type #{m.type} / #{m.name} with -#{m.body}- "
    if m.type == :chat && ! m.body.nil?
      index=(m.body.index(" ") || 0)-1
      com=m.body[0..index]
      param=(index==-1?"":m.body[index+2..-1])
      puts "XMPP: Call #{com} with --#{param}-- (caused from #{m.from})"
      @cmd.call(m.from,com,param)
    end
  end
  def self.connect(jid,pwd,&block)
    bot=XmppRoute.new(jid,pwd)
    bot.instance_eval(&block)
    bot.close
  end
end

Netx.rb

require 'socket' # Get sockets from stdlib

class Netx
  def initialize; @run=true; end
  def listen(port)
    puts "NETX: Bind to Port #{port}"
    #server = TCPServer.open(port)
    #only local:
    server = TCPServer.open("127.0.0.1",port) # Socket to listen
    while @run
      # this timeout allows us to kill this lop every few seconds...
      begin
        session = Timeout::timeout(10) { server.accept }
        Thread.start(session) { |c| connection c }
      rescue TimeoutError
        #puts "NETX: Refreshing TCPServer."
      end
    end
  end
  def on_sended(&cb); @client_cb=cb; end
  def halt; @run=false; end
  private
  def connection (client)
    puts "NETX: Client conntected..."
    client.puts("-- Hello on Felician at #{Time.now.ctime}. ") # Send the helo & time to the client
    conn_open=true;
    msg_buffer="";
    while conn_open do
      l = client.gets
      if (l.strip.eql?'..') || (l.strip.eql?'.') then
        puts "NETX: Client issued a message..."
        client.puts("-- accepted. ")
        @client_cb.call(msg_buffer)
        msg_buffer="";
        conn_open=false if l.strip.eql?'..'
      else
        msg_buffer << l
      end
    end
  ensure
    client.puts "-- Closing the connection. Bye!"
    puts "NETX: Client disconnect. "
    client.close # Disconnect from the client
  end
end

Erwartet nicht zu viel von dem Code, ist schließlich mein erster Ruby-Code, abgesehen von einigen Hello-World-Sachen. Funktioniert dafür allerdings erstaunlich gut und könnte sich schon fast eigenen, um z.B. einen Systemadministrator über wichtige Aktivitäten und Warnungen aus den verschiedensten Programmen und Wartungsscripten schnell zu informieren.

Man beachte vielleicht noch das alles in dem Code, was in anderen Programmiersprachen als schlechter Stil gälte, hier eher „the ruby way“ ist ;).

Benutzung

Eine Nachricht von der Shell schicken:

09:15  burny@home:~> echo -e "Hallo Welt\n.." | netcat localhost 2000
-- Hello on Felician at Tue Dec 15 21:16:02 2009.
-- accepted.
-- Closing the connection. Bye!

Mal sehen, ob ich das Ganze noch weiter entwickle, meistens ist doch das Senden einer ganz normalen eMail einfacher.

Kommentare: 2 Einträge

Howto: Alleinstehende Unds für XHTML umwandeln

16.04.2009, 13:22
$text=preg_replace ('/&(?!amp;|quot;|nbsp;|gt;|lt;|laquo;|raquo;|copy;|reg;|#[0-9]{1,5};|#x[0-9A-F]{1,4};)/','&', $text);

In meinem Markup-Parser für diesen Blog hatte ich das Problem, dass ich zwar einzelne & in &amp; umwandeln konnte, damit ich Et-Zeichen im ganz normalen Text schreiben kann, auf der anderen Seite aber auch HTML <tags> erlauben will. Wenn ich jetzt aber über HTML schrieben will, muss ich ja auch irgendwie die größer und kleiner-Zeichen encodieren, damit nicht alles einfach vom Browser gerendert wird. Wenn ich aber ein &lt; eingebe, würde das Kaufmanns-Und sofort zu &amp; umgewandelt und so würde dann im Quelltext &amp;lt; stehen und im Text nicht < sondern &lt;. Also brauchte ich eine Methode um nur einzelne kaufmännische Unds zu finden. Das lief dann auf obigen Regulären Ausdruck hinaus.

Er ersetzt & mit &amp; nur dann, wenn dahinter keines der HTML-Entities folgt. Da es eine sehr lange Liste von benannten HTML-Entities gibt, habe ich nur die aufgenommen, die man in HTML Umwandeln muss („htmlspecialchars“), damit ihre Bedeutung erhalten bleibt und ein paar Sonderzeichen, die ich sonst nie finde. Alles andere (z.B. &eacute; für é, 文字, ...) wird ja von UTF-8 abgedeckt. Für ASCII kann man auch noch die dezimale oder hexadecimale Unicode-Notierung verwenden.

Der regexp verwendet eine Erweiterung, die Negative Vorausschau (?!x). Das ist so etwas wie ein Unter-Ausdruck, der zwischendurch überprüft wird am Text nach der aktuellen Position. Die Buchstaben, die auf den überprüften Ausdrück passen, werden nicht mit "gefressen", sie werden also nicht übersprungen, sondern nur kurz getestet. Nur wenn der Ausdruck nicht zutrifft wird von der Ursprungsposition weiter getestet. Es gibt natürlich auch noch positive Vorausschau (?=x) (die weiter laufen lässt, wenn der Ausdruck passt), sowie positive (?<=x) und negative (?<!x) Zurückschau (die jeweils den Text vor der aktuellen Position prüfen).

Das würde zum Beispiel alle Minuskeln ausgeben, die nach einem „o“ stehen: [a-z](?<=o.). Man beachte den Punkt nach dem „o“. Er steht für das gerade überlaufene Zeichen für das jetzt geprüft wird was (von der aktuellen Position hinter dem Zeichen aus gesehen) davor steht. Das bedeutet in der Rücksicht sieht sich das Zeichen nochmal selbst. Noch ein Beispiel: .(?<=o(?#comment).{5}) findet alle Zeichen 5 Positionen vor „o“.

Diese Features stehen in Ruby übrigens nur teilweise zur Verfügung.

Kommentare: keine

Kate - mein geliebter Editor

27.10.2008, 22:54

Man hat als (Web-)Developer ja immer ein bisschen das Problem sich eine geeignete Arbeitsumgebung zu schaffen, weil es einfach nicht „die“ IDE gibt. Als Ruby on Rails Benutzer hat man die Wahl zwar sehr leicht, wenn man sehr ausgefallen ist und Java verwendet, führt fast nichts an Eclipse vorbei, doch ich bleibe lieber bei PHP. Und da ist der Markt irgendwie sehr unübersichtlich:

Natürlich zählen Subversion, CVS, vi, Apache und MySQL ganz gut zur Entwicklungsumgebung, aber ich will hier eher auf das Programm eingehen, das man am häufigsten braucht: Den Code-Editor.

Um PHP zu entwickeln kann man natürlich auf die - meist rudimentären - Möglichkeiten des ein oder anderen HTML-Editors zurückgreifen. Nur ist für mich ein HTML-Editor nicht mehr so aktuell, da ich HTML irgendwie fast im Schlaf beherrsche. Ich will nicht mehr unbedingt die Buttons für Überschriften usw. , oder gar einen WYSIWYG-Editor. Denn heutzutage braucht man für das Layout fast nur divs und den Content kann man ja dann wieder mit dem HTML-Editor oder im CMS basteln... wenn man will.

Dann gibt es natürlich auch diverse spezielle PHP-Editoren mit nettem Syntax-Highlighting und erweiterten Ersetzungs-Features. Diese sind teilweise mit Datei-Outlining, Projektverwaltung und ähnlichem Schickschnack voll gepackt, dass sie schon fast überladen wirken. Die Spitze des Eisbergs bildet hier wohl das hochwertige Programm UltraEdit, das auch gleich noch FTP-Client, SQL-Tools und viele weitere Features oben drauf setzt.

Jedoch sind diese PHP-Editoren kaum noch zu gebrauchen, wenn man etwas anderes als PHP, HTML usw. machen will. Hier kommt dann Kate ins Spiel. Der erweiterte KDE-Editor kann die Syntax von fast allen denkbaren Programmier- und Auszeichnungssprachen, farblich hervorheben. Darunter HTML, XML, PHP, SQL (sogar MySQL/PostgreSQL-spezifisch), Apache-Konfiguration, CSS, JavaScript, und ausgefallenes wie MediaWiki. Hinter Kate steckt also ein sehr allgemeiner Ansatz. Damit kommt einher, dass man leider auf direkte Implementierung für FTP-Client, Dokument-Outline oder anderes sehr PHP-spezifisches verzichten muss.

Doch das wird eigentlich recht schnell mit der Terminal-Funktion ausgehebelt. Über diese lassen sich dann letztendlich auch SVN oder CVS und eigentlich alle Kommandozeilenprogramme benutzten. Das Terminal cd"ed auch automatisch in den Ordner der gerade offenen Datei.

Das Terminal ist aber nur ein Beispiel, wie sich Kate perfekt in KDE bzw. „Linux“ integriert. Man kann auch Datei-übergreifend suchen und in einer Sidebar in Ordnern browsen. Achja, diese „Ordner“ beinhalten natürlich auch FTP, Webdav, Zip- und komprimierte Tar-Archive, sowie weitere Protokolle. Eben alle Protokolle, die z.B. Konqueror durch die KIO-Slaves auch kann. Dank SFTP kann man sogar auf Servern arbeiten, wo man nur ssh-Zugriff hat, das bedeutet nie wieder Putty- oder CLI-Herumirren.

Natürlich hat Kate auch sonst fast alle Funktion, die man sich so wünschen kann. In Tabs oder der Sidebar können mehrere Dokumente offen sein, an denen man parallel arbeiten kann und die alle gleichzeitig gespeichert werden können. Die offenen Dokumente werden dann in der Sitzung gespeichert. Auch Rechtschreibprüfung, auto-Vervollständigung, automatische Einrückung (mehrere Stile), und Ersetzen mit regulären Ausdrücken gehören zum Editor.

Besonders hilfreich ist auch immer die Integration mit Klipper. Klipper ist unter KDE ein Hilfsprogramm für die Zwischenablage. Es merkt sich automatisch den letzten markierten Text, der dann mit mittlerer Maustaste eingefügt werden kann. So ist sehr schnelles Copypaste möglich. Besonders nützlich kommt dann auch die History-Funktion von Kipper: Über eine Einfügen-Taste in der Symbolleiste kann man ein Menü öffnen und von dort aus den letzten markierten Texten wählen. Wenn man also im Internet oder in der Dokumentation recherchiert, markiert man einfach hin und wieder Funktionen oder Codesnippets die vielleicht nützlich sein könnten. Dann kann man sie später, dank Klipper, wieder aus dem Menü wählen und schnell in den eigenen Code einfügen. Das hilft enorm weiter, wenn man viel mit APIs arbeitet, oder mit altem Code, oder die Dokumentation braucht, oder, oder, oder... eigentlich immer.

In Kate habe ich irgendwie meinen perfekten Editor gefunden. Nicht so überladen, allgemein brauchbar. Nur manchmal fehlt eben noch ein bisschen das Eclipse-Feeling:

Als kleiner Ausblick: Ich habe eigentlich noch keinen PHP-Editor gefunden, der Ordentlich auto-Vervollständigen betreibt. Von Eclipse kennt man das ja, dass man fast immer das Vorgeschlagen bekommt, was man eigentlich wollte. Nut mit PHP hat das noch keiner so recht hin bekommen. Die Sichtweite ist irgendwie immer falsch, includes und autoload fast unerreichbar. Die Anzeige der Dakumentation in der Vervollständigung bei Eclipse habe ich auch immer sehr geschätzt. Wie auch immer, man muss immer seine Klassen und Funktionsaufrufe im Kopf haben, was bei großen Projekten mit vielen Includes sehr schnell zum Problem werden kann. Auch das „refractoring“, hier das Projektübergreifende Umbenennen von Variablen, Funktionen etc. kommt manchmal sehr praktisch zur Hand - in Eclipse. Bei Eclipse kann man auch mit klick auf die Variablen/Klassen zu ihrer Deklaration kommen, was sehr viel herum Suchen erspart. Für PHP gibt es derartige „globale Tools“ irgendwie noch kaum. Naja, man kann ja Erweiterungen für Kate schreiben, außerdem ist es OSS.

PS: Wenn ich die Funktion für Bilder im CMS habe, füge ich auch noch ein paar Screenshots ein...

Edit: Die Bilderfunktion ist jetzt da!

Kommentare: 3 Einträge
[ Seite 1 ]
 
Χρόνογραφ
© 2008-2017 by Bernhard Häussner - Impressum - Login
Kurz-Link zur Homepage: http://1.co.de/