E-Mail Adressen mit Javascript bzw. JQuery vor Grabbern schützen

Wenn man seine E-Mail Adresse oder die von anderen einfach als HTML Code veröffentlicht, besteht die Gefahr, dass die Adressen von Skripten maschinell eingelesen werden, mit dem Zweck diese als Empfänger für Spam zu nutzen. Es gibt einige mehr oder minder effektive Möglichkeiten, die Adressen für Homepagebesucher sichtbar zu machen, aber das automatisierte Ablesen zu erschweren.

Eine davon ist die Adresse von eindeutigen Merkmalen wie @ (jede E-Mail Adresse besitzt bekannterweise genau ein @) oder . (als Trennzeichen zwischen Domain und TLD) zu bereinigen, in dem man diese Zeichen durch Marker ersetzt und zur Laufzeit dann mit den richtigen Zeichen austauscht.

Also, anstatt im HTML Quelltext zu schreiben
<a href=”mailto:mailname@domain.tld”>mailname@domain.tld</a>
schreiben wir
<span class=”amailto”>mailname at domain dot tld</span>
Javascript (JQuery):
$(document).ready(function(){
  var at = / at /;
  var dot = / dot /g;
  $(“span.amailto”).each(function(){
    var addr = $(this).text().replace(at,”@”).replace(dot,”.”);
    $(this).after(“<a href=’mailto:”+addr+”‘ title=’E-Mail senden’>”+ addr +”</a>”);
    $(this).remove();
  });
});

Telko-Maker – Telefonkonferenz: “Bin drin”

Dass es bereits viele Telefonkonferenzlösungen gibt, heisst noch lange nicht, dass man für sich die passende gefunden hat. Telko-Maker vereint einzigartige Funktionen, um das gemeinsame Telefonieren einfacher und bequemer zu gestalten.

Nutzen Sie beispielsweise das Einladungssystem, um mehrere Personen einzuladen und bieten Sie ihnen mehrere Terminmöglichkeiten zur Teilnahme an. Telko-Maker wird anhand der Antworten automatisch den ersten gemeinsamen Termin aufsetzen und die Teilnehmer benachrichtigen…

Telko-Maker bündelt in wenigen Optionen ein doch mächtiges Interface sowohl für gelegentliche Nutzer als Dauerkonferenzler. Momentan ist die Software im Beta Status kostenfrei nutzbar, Sie können sich einfach auf http://www.telko-maker.com anmelden.

Wie kann man die Rufnummer bei Telefonaten zwischen Sipgate Teilnehmern und Asterisk anzeigen (anstatt interne Sipgate-ID)?

AsteriskAnrufe zwischen Sipgate Teilnehmern werden automatisch als SIP-Anrufe geroutet, selbst wenn man die “externe” Telefonnummer anruft. Das hat den Vorteil, dass die Anrufe zwischen den Sipgate Teilnehmern nichts kosten, da die Telefonate über Internet abgewickelt werden. Schön wäre es aber auch zu wissen, wer mich anruft 😉

Problem:
In der From-Header steht dann nicht die Telefonnummer des Anrufers sondern die SIP-URL (z.B. <sip:12345e0@sipgate.de>). Die von Asterisk gesetzte Variable CALLERID(num) beinhaltet dann nur noch die Sipgate SIP-UserID wie z.B. 12345e0. Die an Asterisk angeschlossenen Telefone können meistens damit nichts anfangen. Wenn die ID einen Buchstaben enthält (hier im Beispiel ‘e‘), führt es dazu, dass manch ältere Telefone gar keine Rufnummer anzeigen. Besonders ärgerlich ist es, wenn man einen Anruf verpasst hat und die Rufnummer nicht mehr zuordnen kann, wer tatsächtlich angerufen hat.

Lösungsweg:
Schaut man sich die SIP Header an, stellt man fest, dass die gewünschte Information in dem Headerelement “P-Asserted-Identity” enthalten ist:

INVITE sip:5000@10.0.0.33 SIP/2.0
...
From: <sip:12345e0@sipgate.de>;tag=CAFEBABE
To: <sip:072198765432@sipgate.de>
Contact: <sip:12345e0@12.34.56.78;uniq=CAFEAFFE23>
...
P-Asserted-Identity: <sip:072112345678@sipgate.de>

Bei anderen Anbietern kann das Format abweichen. Mehr dazu in http://www.ietf.org/rfc/rfc3325.txt.

Zwecks Demonstration habe ich einen kleinen Dialplan für Asterisk geschrieben:

; debug
exten => 5000,1,NoOp(Caller-ID: ${CALLERID(all)})
exten => 5000,2,NoOp(SIP From: ${SIP_HEADER(From)})
exten => 5000,3,NoOp(SIP To  : ${SIP_HEADER(TO)})
exten => 5000,4,NoOp(SIP PAI : ${SIP_HEADER(P-Asserted-Identity)})

; try to extract phone number from sip header P-Asserted-Identity
exten => 5000,5,Set(FON=$["${SIP_HEADER(P-Asserted-Identity)}" : "<sip:([0-9]+)"])
exten => 5000,6,ExecIf($[${ISNULL(${FON})}=0]?Set(CALLERID(num)=${FON}))

; debug
exten => 5000,7,NoOp(Caller-ID: ${CALLERID(all)})
...

Erläuterung:
5: Wir extrahieren die Nummer mit RegExp und speichern das Ergebnis in die Variable FON.
6: Falls FON nicht null ist, ersetzen wir die CALLERID(num) mit dem Wert von FON.

Hier zwei UseCases und Ausgabe von Asterisk:
Teinehmer für das Beispiel (Telefonnummer, IPs sowie alle TAGs sind verschleiert).
Angerufene (Asterisk mit Sipgate-Account):
– Telefonnumber = 072198765432
Anrufer 1 (Fritzbox mit Sipgate-Account):
– Sipgate ID = 12345e0
– Telefonnumber = 072112345678
Anrufer 2 (Mobil):
– Telefonnumber = 017112345678

Case 1: Anrufer 1 (sipgate -> sipgate):

-- Exec...1] NoOp("SIP/sipgate.de-000000b6", "Caller-ID: "" <12345e0>") in new stack
-- Exec...2] NoOp("S..b6", "SIP From: <sip:12345e0@sipgate.de>;tag=CAFEBABE") in new stack
-- Exec...3] NoOp("S..b6", "SIP To  : <sip:072198765432@sipgate.de>") in new stack
-- Exec...4] NoOp("S..b6", "SIP PAI : <sip:072112345678@sipgate.de>") in new stack
-- Exec...5] Set("S..b6", "FON=072112345678") in new stack
-- Exec...6] ExecIf("S..b6", "1?Set(CALLERID(num)=072112345678)") in new stack
-- Exec...7] NoOp("S..b6", "Caller-ID: "" <072112345678>") in new stack
-- Exec...8] ...

Exec…5: Die externe Rufnummer des Anrufers wurde in FON reingeschrieben
Exec…6: 1? => Kondition erfüllt => ersetze CALLERID(num)
Exec…7: Verifizierung, dass die Nummer ersetzt wurde (vgl. Exec…1)

Case 2: Anrufer 2 (mobil -> sipgate):

-- Exec...1] NoOp("S..b8", "Caller-ID: "017112345678" <017112345678>") in new stack
-- Exec...2] NoOp("S..b8", "SIP From: "017112345678" <sip:017112345678@sipgate.de>;tag=cafebabe") in new stack
-- Exec...3] NoOp("S..b8", "SIP To  : <sip:004972198765432@sipgate.de>") in new stack
-- Exec...4] NoOp("S..b8", "SIP PAI : ") in new stack
-- Exec...5] Set("S..b8", "FON=") in new stack
-- Exec...6] ExecIf("S..b8", "0?Set(CALLERID(num)=)") in new stack
-- Exec...7] NoOp("S..b8", "Caller-ID: "017112345678" <017112345678>") in new stack
-- Exec...8] ...

Exec…5: Patternmatching schlägt fehl, da der Header nicht gesetzt ist, somit is die Variable FON null.
Exec…6: 0? => Kondition nicht erfüllt => nichts tun
Exec…7: Verifizierung, dass die Nummer unverändert geblieben ist (vgl. Exec…1)

Die Endgräte zeigen nun immer die externe Rufnummer des Anrufers an. Somit kann der Anrufer bei einem verpassten Anruf auch zurückgerufen werden.

Viel Spass,

= C. | SaaS Web Techniklabor =

P.S.: Lustig ist, dass die App von Sipgate auch nur die interne ID anzeigt (“Anruf von 12345e0”) und man verwirrt ist, wer nun wirklich anruft…

Multilinguale Homepage mit WebsiteBaker

Dieses einfache CMS ist für viele kleinere Projekte mit Sicherheit bestens geeignet. Wenig Schnickschnack, dafür leichtverständliche Menues in einem schlichten Design.

Besonders interessant sind 2 Aspekte:

  1. Eigene Templates: das Template System ist sehr einfach; Sie können in wenigen Minuten eigene Seiten erstellen, genau wie Sie es sich wünschen.
    • Schritt eins: Verzeichnis erstellen mit dem Namen der Vorlage
    • Schritt zwei: Dateien info.php, index.php und template.css anlegen (Mindestanforderung).

      Besser ist es noch ein /images Verzeichnis zu erstellen, um Bilder und Icons für das Template abzuspeichern.
    • Schritt drei: In info.php die Bereiche angeben, die genutzt werden; zunächst Metadaten, um das Template beim Import richtig in die Datenbank einzutragen. Es muss auch angegeben werden, ob es mehrere Navigationsmenues gibt, mehrere Contentbereiche, …
    • Schritt vier: In index.php nun eine HTML Ansicht der Seite vorbereiten und mit den PHP-Befehlen page_header(), show_menu(), page_content() und page_footer() die wichtigsten CMS-gesteuerten Bereiche anlegen.
      PS: show_menu2() ist eine neue Variante für die Navigationsanzeige und sollte möglichst an der Stelle von show_menu() genutzt werden, vor allem wenn man verschachtelte Navigationen einsetzt.
    • Schritt fünf: Verzeichnis zippen und als Vorlage in WebsiteBaker importieren. Ab dann kann das Template auch direkt in der WebsiteBaker Installation bearbeitet werden und muss nicht permanent neu gezipped und hochgeladen werden.

    Doku zu dem Thema gibt es hier.

  2. Multilingual: einfach Sprach-Container anlegen und schon hat man eine Sprachtrennung – URL rewriting wird automatisch eingestellt.

Natürlich hat SaaS Web gehostete WebsiteBaker Pakete im Sortiment.

Die Nacht der lebenden Karten – OpenStreetMap

Der erste globale “Mapathon” wird am 7. Februar stattfinden, unter dem Motto: “Night of the living Maps”. Wie ein OpenStreetMap-Projektverantwortlicher formuliert, eine LAN-Party für GIS-Freaks 🙂

Es sollen zwar viele lokale Parties organisiert werden, allerdings weniger mit dem Ziel “zu schwatzen”, sondern komplette Gebiete abzufotografieren, von Sonnenuntergang bis Sonnenaufgang.

Zu dem Projekt Wiki