BigBastis Blog About Me & my Digital Lifestyle

15Mrz/130

Clover: Tabs für den Windows Explorer

clover_screenshot

Ich glaube schon seit Windows 98 habe ich mich gefragt, warum Microsoft dem Windows Explorer keine Tabs spendiert. Auch Apple bekommt es unter Mac OS nicht hin den Finder Tab-Fähig zu machen. Warum eigentlich nicht?

Clover zeigt wie es gehen könnte. Dieses einfache kleine Tool kombiniert alle Windows Explorer Fenster unter einem Dach und lässt sich dabei so flüssig bedienen, dass es schon fast wie eine native Lösung wirkt.

Auf den ersten Blick fällt sofort auf, dass hier einige Teile vom Google Chrome eingeflossen sind. So gleicht das Look and Feel der Tabs und auch deren Bedienung bis ins Detail dem von Chrome. Alles ist super Flüssig und funktioniert komplett ohne Konfiguration sofort so wie man es gewohnt ist.

So lassen sich neue Tabs mit STRG+T öffnen und mit STRG+TAB durchschalten. Mit einem Doppelklick während man die STRG-Taste gedrückt hält wird der gewählte Ordner in einem neuen Tab geöffnet. Die Tabs selbst integrieren sich in die Titelleiste des Fensters und verbrauchen so gut wie keinen Platz.

Optional kann man auch noch (wie auch im Chrome) eine Lesezeichenleiste einblenden lassen, in der man seine Lieblingsordner speichern kann. Ich finde aber, dass es die Optik etwas stört.

Das Icon des Programms könnt ihr ebenfalls verändern, wenn euch das Kleeblatt nicht zusagt. Eine Anleitung dafür gibts auf der Homepage des Entwicklers.

Weitere Infos und Download.

28Feb/131

iPhone Webapp-Links nicht im Safari öffnen

iOS bietet euch eine nette Funktion mit der ihr Webseiten als Verknüpfung auf eurem Homescreen ablegen könnt. Wenn ihr eure Seite darauf noch etwas vorbereitet, könnt ihr sogar euer eigenes Logo hinterlegen und auch die Webseite später im Fullscreen Modus laufen lassen.

Dazu müsst ihr lediglich ein paar Ressourcen hinterlegen:


    <!-- Setzen der Icons für die verschiedenen Auflösungen -->
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/Content/grafik/icons/apple-touch-icon-144-precomposed.png">
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/Content/grafik/icons/apple-touch-icon-114-precomposed.png">
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="/Content/grafik/icons/apple-touch-icon-72-precomposed.png">
    <link rel="apple-touch-icon-precomposed" href="/Content/grafik/icons/apple-touch-icon-57-precomposed.png">
    <!-- sorgt dafür dass die App im Vollbild ausgeführt wird -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <!-- Farbe der Statuszeile -->
    <meta name="apple-mobile-web-app-status-bar-style" content="black">


Safari erkennt dann diese Tags und zeigt euer Icon und führt die Seite dann auch im Vollbildmodus aus. Ein weiteres Goodie ist, dass die Webseite als "App" läuft und im Taskmanager sogar ein eigenes Icon bekommt.

Hier am Beispiel meiner kleinen F1-Tippspiel Seite:

Diese Diashow benötigt JavaScript.

Der Haken
Ein kleines Problem bleibt dann aber noch. Sobald ihr einen Link auf die Seite setzt und der Benutzer diesen antippt wird der Link ein einer neuen Safari Instanz geöffnet. Das Liegt daran, dass iOS euere Seite als App betrachtet und alle Links werden in iOS vom Safari behandelt.

Zum Glück kann man dieses Verhalten sehr einfach mit etwas Javascript umgehen:


<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>

Weitere Infos und Quelle zu der Lösung findet ihr bei Stackoverflow.

Nun werden alle Links in eurer "App" geöffnet und alles funktioniert wie gewohnt :)

29Jan/130

Nice 2 Know: Razor ViewEngine ausserhalb von MVC nutzen

Wenn ihr ASP.NET MVC ab Version 3 schon mal benutzt habt dann wird euch die Razor ViwEngine kein Fremdword mehr sein. Oft kommt man aber gar nicht drauf, dass man diese praktische Templating-Engine auch außerhalb von MVC benutzen kann.

So kann man dieses Feature super gebrauchen wenn die App E-Mails versenden soll und man größere E-Mail Templates nutzen will. Das Schöne an der Razor Engine ist, dass man diese sehr einfach integrieren kann und der Code sehr verständlich und sauber bleibt.

Die Installation erfolgt hier wie so oft sehr einfach über NuGet:

Jetzt ist man im Grunde schon fertig und kann sofort loslegen. Starten wir mit dem Model, das die Razor Engine für uns verarbeiten wird. Dies ist eine gewöhnliche Klasse (POCO):


public class TipReminder
{
	public string DisplayName { get; set; }

	public string EmailAdress { get; set; }

	public DateTime LastLogin { get; set; }
}

Jetzt legen wir uns ein kleines Template an, das den Inhalt der Email darstellen soll:


@model Projekt.Domain.AppUser
<!DOCTYPE html>

<head>
    <meta name="viewport" content="width=device-width" />
    <title>Newsletter</title>
</head>
<body>
    <div>
        <h2>Hallo @Model.DisplayName</h2>
        <p>Es ist wieder Zeit für einen Newsletter</p>
        <p>Dein letzter Login war am @Model.LastLogin - das ist schon lange her!</p>
        <p>Schau doch mal wieder vorbei.</p>
        <hr />
        <p>Bitte antworten Sie nicht auf diese EMail</p>
        <p>Viel Spaß weiterhin!</p>
    </div>
</body>
</html>

Man beachte hier besonders die Zeilen 10 und 12 wo wir auf das Model zugreifen.

Wenn ihr ASP.NET MVC 3 oder 4 schon mal genutzt habt, werdet ihr feststellen, dass alles exakt der Syntax einer View gleicht, sogar die Definition der strickten Typisierung auf das Model oben.

Die eigentliche Nutzung ist dann ein Kinderspiel:


foreach (AppUser user in db.Users)
{
    string renderedEmail = Razor.Parse(File.ReadAllText(pathToEmailTemplate), user);
    EMailHelper.SendEmail(renderedEmail, user.EmailAdress);
}

Wirklich interessant ist hier nur Zeile 3 wo wir den eigentlichen Aufruf an die RazorEngine tätigen. Die Parse-methode benötigt lediglich das Template als String und ein Model zur Verarbeitung.

Das ist ein wirklich praktisches Feature um die Templates auf einfachste Weise aus dem Programm herauszulösen. Das Ganze ist nicht neu (gibt’s schon seit fast 2 Jahren) man muss nur wissen, dass es möglich ist. :-)

8Aug/120

iOS6 Smart App Banner auf eurer Seite nutzen

Bilder von iphoneblog.de

Sicherlich kennt ihr diese hässlichen Popups auf größeren Seiten wie Welt.de die auch eine (Bezahl-)App im Appstore haben. Diese Popups sind nicht nur unschön, sondern nerven auch extrem!

In iOS6 will Apple das Ganze nun etwas verschönern und bietet den Webseiten an ein Banner über dem Seiteninhalt anzuzeigen, das die gewünschte App inklusive ein paar Informationen wie Bewertung und Hersteller enthält.

Wie das aussehen kann seht ihr in dem oberen Screenshot des Safari unter iOS6. Statt einem Popup zeigt ted.com den neuen Banner an.

Implementierung

Wenn ihr eure Seite auch mit einer App verknüpfen wollt könnt ihr das ziemlich einfach gestalten:


<meta name="apple-itunes-app" content="app-id=%APPID%, app-argument=%APPPARAMETER%">

Ihr bindet einfach den oberen Meta-Tag in eurem Header ein und der mobile Safari erledigt den Rest. Ihr habt hier dabei zwei Parameter zu befüllen, wobei der zweite optional ist.

Die App-ID ist die Id der App im Appstore. Diese findet ihr in der URL der App im iTunes Store:

http://itunes.apple.com/de/app/doodle-jump-achtung-hochste/id307727765?mt=8

Dabei gebt ihr nur die Zahl an (ohne "id").

Der zweite Parameter wird der App (falls die verlinkte App bereits installiert ist) übergeben. So könnt ihr den Besucher nahtlos in die App wechseln lassen und automatisch an die Stelle in der App springen auf der der Besucher auf der Webseite war.

Da iOS6 sich wenn es bald raus ist ziemlich schnell verbreiten wird lohnt es sich sicher schon mal die Header anzupassen ;-)

7Aug/120

Log4Net in einem ASP.NET MVC Projekt nutzen

Nutzt ihr eigentlich Logging Systeme? Ja? Wirklich? Jaja, das hätte ich jetzt auch gesagt ;-) Wenn ihr noch kein Logging in euren Web Projekten habt solltet ihr das schleunigst nachholen, denn es ist oft einfachste und schnellste Weg genaue Informationen darüber zu erhalten was in der Applikation los war als es zu einem Fehler oder Absturz kam.

Eine der einfachsten und schnellsten Möglichkeiten Logging zu implementieren ist es die fertige und sehr mächtige Library Log4Net zu nutzen. Java Entwickler werden diese als Log4J kennen und schätzen.

Am schnellsten geht es wenn ihr Log4Net über NuGet installiert:

Nun habt ihr schon mal die Assembly in eurem Projekt. Als nächstes müssen wir Log4Net konfigurieren. Das kann man zum Beispiel in der web.config machen:


    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    </configSections>

    <log4net>
        <root>
            <level value="ALL" />
            <appender-ref ref="RollingFile" />
        </root>
        <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
            <file value="app.log" />
            <appendToFile value="true" />
            <maximumFileSize value="1000KB" />
            <maxSizeRollBackups value="2" />
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5p %c - %message%newline" />
            </layout>
        </appender>
    </log4net>

Interessant ist hier eigentlich der Appender-Teil, denn hier definiert ihr wie geloggt werden soll. In diesem Beispiel werden alle Ausgaben in eine Datei namens app.log geloggt, weiterhin werden Informationen wie Datum, Zeit, Thread, Log-Level, Klasse und Lognachricht angezeigt. Hier gibt es unendlich viele Kombinationen.

Auf der Homepage von Log4Net findet ihr noch viele andere Beispiele für Appender-Configs, mit denen ihr direkt in eine Datenbank loggen könnt, oder die Nachrichten an einen SMTP Server senden könnt, die dann per Mail versendet werden. Natürlich kann auch auf die Konsole geloggt werden, sucht euch einfach die Appender aus die ihr benötigt und tragt diese ein, ihr könnt auch mehrere Appender kombinieren.

Bevor ihr nun losloggen könnt müsst ihr den Logger noch laden. Das macht ihr in der Application_Start-Methode in der Global.asax.cs. Hierzu reicht eine einfach Zeile:


log4net.Config.XmlConfigurator.Configure();

Wenn ihr die Konfiguration von Log4Net in eine Extra Datei auslagern wollt, könnt ihr hier auch den Pfad zu dieser Konfiguration angeben.


log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(filename));

Nun wechseln wir mal in einen Controller und loggen mal etwas:


    public ActionResult Index()
    {
        ILog logger = LogManager.GetLogger(typeof(HomeController));

        logger.Info("Index Action wurde aufgerufen.....");

        try
        {
            logger.Debug("Don't mess with math dude...");
            int zero = 0;
            int endOfWorld = 12 / zero;
        }
        catch (Exception ex)
        {
            logger.Error("Ohh noez, you're dead now!", ex);
        }

        return View();
    }

Wie man sieht funktioniert das Ganze ziemlich einfach und effektiv. Der Logger lässt euch zwischen verschiedenen Log-Leveln auswählen. In der XML-Konfiguration definiert ihr den Loglevel, dann werden nur bestimmte Dinge geloggt. So könnt ihr für Diagnosezwecke den DEBUG-Level setzen um alle wichtigen Infos zu erhalten, und später wenn alles erledigt ist den Level wieder auf INFO senken.

So sieht übrigens die Ausgabe zu dem oberen Code aus:

Im Grunde ziemlich simpel, aber sehr effektiv. Alternativ kann man auch ELMAH verwenden.

Ein Demo-Projekt findet ihr hier.

16Apr/120

GlassFish: Unnoetige HTTP-Response Header entfernen

In dem letzten Artikel habe ich beschrieben, wie ihr unter ASP.NET MVC Anwendungen die verräterischen HTTP Header ausblenden könnt, nun können wir auch mal auf den GlassFish schauen.

Default-Header

Wie ihr in dem oberen Bild erkennen könnt sendet der GlassFish hier seinen Namen, die Version und auch das verwendete Framework mit. Das wollen wir natürlich nicht haben.

Fangen wir mit dem Server-Header an. Dieser ist recht einfach zu entfernen durch das Setzen eines VM-Parameters in der GlassFish Adminoberfläche.

  1. Startet die Admin console
  2. Wählt Configuration ->JVM Settings
  3. Wählt oben JVM Options
  4. Klickst auf Add JVM Option
  5. In der neue textfeld tragt ihr ein:  -Dproduct.name=""
  6. Klickt auf Save und startet den GlassFish neu

Nun ist der Server-Header nciht ausgefüllt

Auch wenn das nun etwas komisch aussieht, haben wir so den Server-Header entfernt. Dabei verhält sich der GlassFish unter verschiedenen Umständen anders. Manchmal zeigt er den Header so an wie in dem Bild, manchmal lässt er ihn auch komplett weg. (Wenn ihr hier mehr wisst hinterlasst bitte ein Kommentar).
X-Powered-By header

  1. Startet die Admin console
  2. Geht zu Configuration -> Network Config -> Network Listeners
  3. Wählt http-listener-2 aus und wählt dann oben "HTTP"
  4. Deaktiviert den Hacken bei "XPowered By" (Siehe Bild)
  5. Speichert und startet den GlassFish neu

Der Hacken zum deaktivieren des Headers

Leider ist die Sache damit noch nicht gegessen, da dies scheinbar nur den "X-Powered-By: Servlet/3.0" Header entfernt den "X-Powered-By: JSP/2.1" muss man nochmal wo anders entfernen.

  1. Navigiert zu domains/domain1/config
  2. öffnet die Datei default-web.xml
  3. sucht nach xpoweredBy und setzt diesen Setting auf "false" (siehe Bild)
  4. Speichert und startet den GlassFish neu

Konfiguration in der default-web.xml

Nun sieht die Sache wieder bessern aus:

nun ist alles fast OK

Wenn ihr noch einen Tipp habt wie man den Server-Header ganz weg bekommt wäre ich für einen Kommentar dankbar!

5Apr/122

ASP.NET MVC Security Teil 2: Unnoetige HTTP Response-Header entfernen

In dieser Reihe von Posts möchte ich Wege zum Absichern einer MVC Anwendung zeigen, die man gerne mal vergisst oder als Neueinsteiger nicht gleich auf dem Schirm hat.

Teil 2: Unnötige HTTP Response-Header entfernen

Wenn wir im Internet surfen werden oft Informationen über uns ohne unser Zutun bei jedem Request an den Server übertragen. Dies geschieht über die HTTP-Header. So wird z.B. die Adresse der Seite auf der wir einen Link geklickt haben in dem Referrer-Header an den Server übertragen.

Aber auch die Server selbst sind in dieser Sache oft sehr gesprächig und verraten mehr über sich als wirklich nötig ist.

Eine Typische ASP.NET Serverantwort

In dem Bild sieht man (rot eingerahmt) Informationen die der Server über unsere Anwendung nach außen gibt, die eigentlich lieber geheim bleiben sollten.

Warum ist das gefährlich?

Die Informationen, die hier angezeigt werden verraten die Version des Servers, der Laufzeitumgebung und die Version des Frameworks, das wir benutzen. In diesem Fall ASP.NET MVC 3.

Falls nun bekannt wird, dass der Server oder ASP.NET in dieser Version eine Sicherheitslücke aufweist, sieht ein potentieller Angreifer sofort, dass unsere Seite für eine Attacke anfällig ist.

Es gibt sogar extra Tools, die das Web nach Webseiten durchsuchen, die eine Serverversion aufweisen, die als unsicher eingestuft wird oder für die es bekannte Lücken gibt. Diese Tools nutzen unter Anderem dann auch diese Informationen um zu prüfen ob es sich lohnt bei dieser Seite einen Angriff zu starten.

Was nun?

Im Grunde ist die Aufgabe sehr einfach, wir müssen diese unnötigen Serverheader ausblenden. Wenn die Webseite dann keine anderen Frameworkspezifischen Merkmale aufweist (wie z.B. einen Viewstate) ist es für einen Besucher praktisch unmöglich herauszufinden, welcher Server und welches Framework im Backend laufen.

Die Umsetzung

Leider ist ASP.NET in dieser Hinsicht noch nicht so richtig benutzerfreundlich, denn um all diese Header zu entfernen müssen wir an einigen verschiedenen Stellen Änderungen vornehmen. Gehen wir mal Schritt für Schritt alles durch.

1. ASP.NET &  MVC Header

Diesen Header können wir recht einfach entfernen, indem wir in der global.asax die nötige Property setzen:


protected void Application_Start()
{
    MvcHandler.DisableMvcResponseHeader = true; //<- Hier

    AreaRegistration.RegisterAllAreas();

    Database.SetInitializer(new F1DBInitializer());

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Dies hat schon eine Gute Wirkung auf unsere Response Header:

Verbliebene Response Header

Die Version von ASP.NET und des MVC Frameworks wird nun nicht mehr angezeigt. Nun zu den anderen.

2. X-Powered-By Header

Um diesen Header zu entfernen müssen wir unsere web.config ergänzen (Quelle):


<?xml version="1.0"?>
<configuration>

  <system.web>
    <httpRuntime enableVersionHeader="false" />
    ...
  </system.web>

  <system.webServer>
    ...
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

 ...
</configuration>

Dann verabschiedet sich auch dieser Header.

Und auch X-Powered-By ist nun weg

3. Einer geht noch: Der Server-Header

Dies geht leider nicht so einfach durch das Setzen eines Configparameters, hier müssen wir selbst Hand anlegen und diesen Header aus der Response löschen. Dazu schreiben wir uns ein eigenes HttpModul (Quelle):


public class RemoveServerHeaderModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreSendRequestHeaders += OnPreSendRequestHeaders;
    }

    public void Dispose()
    { }

    void OnPreSendRequestHeaders(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Headers.Remove("Server");
    }
}

Anschließend müssen wir das neue Modul über die web.config registrieren (Quelle):


<?xml version="1.0"?>
<configuration>
  ...
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="RemoveServerHeaderModule" type="SecurityTipp.RemoveServerHeaderModule"/>
    </modules>
	...
  </system.webServer>

</configuration>

Das Ergebnis:

Alle unnötigen Header sind raus

Nun haben wir unser Ziel erreicht und alle Plaudertaschen aus der Response entfernt :)

Weitergedacht

Hier könnte man nun ansetzen und sogar versuchen den potentiellen Angreifer in die Irre zu führen, indem man einen modifizierten Server-Header zurückgibt der auf eine Ganz andere Serversoftware verweist, Apache oder sowas ;)

Das Schöne hierbei ist weiterhin, dass wir alle diese Änderungen innerhalb unserer App machen können und nicht im IIS rumfummeln müssen. Einerseits weil man da viel kaputtkonfigurieren kann, andererseits weil man nicht immer Zugriff auf den IIS hat, wenn man z.B. nur ein Webspace hat.

Diese Schritte sollten bei jeder Anwendung durchgeführt werden, egal ob MVC, ASP.NET oder PHP, gebt den Besuchern nicht mehr Informationen als sie unbedingt benötigen!

kick it on dotnet-kicks.de

4Apr/120

ASP.NET MVC Security Teil 1: Das AntiForgeryToken nutzen

In dieser Reihe von Posts möchte ich Wege zum Absichern einer MVC Anwendung zeigen, die man gerne mal vergisst oder als Neueinsteiger nicht gleich auf dem Schirm hat.

Teil 1: Nutzen des AntiForgeryToken bei POST Requests

POST Requests sind gefährlich, da diese im Normalfall dafür verwendet werden dem Server Informationen mitzuteilen. Die Informationen sollte man natürlich prüfen, auf Form und Inhalt, aber noch wichtiger ist es, zu wissen wer uns diese Daten sendet. (Cross-Site-Attacken verhindern)

Wie funktioniert das?

Mit dem AntiForgeryToken können wir an dieser Stelle sichergehen, dass nur Formulare am Server angenommen werden, die der Server selbst erzeugt hat.
Dabei erzeugt der Server beim Generieren des Formulars einen Token und speichert diesen in einem versteckten Input-Feld (__RequestVerificationToken), des Weiteren wird auch ein Cookie namens "__RequestVerificationToken" mit dem gleichen Token angelegt, sodass beim Absenden des Formulars sowohl der Cookie als auch das versteckte Feld wieder zurück an den Server übertragen wird.

Wenn der Server diesen Request empfängt prüft er diesen Token aus dem versteckten Feld gegen das Token aus dem Cookie. Gibt es hier keine Übereinstimmung wird der Request abgewiesen.

Wie wird das implementiert?

Als Erstes muss das Token in das Formular gesetzt werden und das Cookie erzeugt werden. Diese Aufgabe übernimmt für und der kleine Html-Helper aus MVC.


<div class="myForm">
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <!-- REST DES FORMULARS -->
    }
</div>

Das ging ja einfach, nun müssen wir dafür sorgen, dass dieses Token beim Verarbeiten des Requests auch geprüft wird.


[ValidateAntiForgeryToken]
public ActionResult UpdateStuff()
{
...
}

Mehr ist das nicht, ein einfaches Attribut genügt, und unsere MVC Anwendung ist mit nur zwei Zeilen sicherer geworden.

Wenn Ihr nun einen Blick in euer gerendertes Formular werft, werdet ihr etwas in der Art finden:


<input name="__RequestVerificationToken" type="hidden" value="4PhvBw7EO5I3O4zw2cdYkaEfSJycy1Ugi8AOT6glW6IqZNnVKXTzL52LgQGNMviOhYTxAOQH3iZRtehUoHKRprcHXa8YNel6RzVmKjGAEi0W0duRpnwJu9EpR7ybAoZX9yqeiP3Pyng/ma1t/k6QhM2bbcoBgkou5y0KXEj8Ut8=" />

Gibt es Einschränkungen?

  • Da hier ein Cookie gesetzt wird müssen natürlich Cookies aktiviert sein da der Server sonst alle Requests abweisen wird.
  • Das Ganze funktioniert nur mit POST Requests, was auch logisch ist, da GET Requests nur zum Abfragen von Informationen genutzt werden sollten.

Alternativen?

Wenn man keine Cookies nutzen will kann man ein ähnliches Verhalten hervorrufen, indem man prüft ob der eingehende Request ein Referrer-Header besitzt der auf unsere eigene Domain + URL verweist.
Dies ist natürlich nicht wirklich Sicher, da es leicht zu fälschen ist und außerdem haben manche Browser Anonymisierungsfunktionen die diese Header-Felder nicht mitsenden, also ist hier Vorsicht geboten.

Zusammenfassung

Das AntiForgeryToken bietet einen recht guten Schutz vor Cross-Site-Attacken bei sehr sehr einfacher und schneller Implementierung.

kick it on dotnet-kicks.de

27Feb/123

GMail: Punkte im Benutzernamen werden ignoriert

Heute habe ich eine EMail bekommen, die ganz klar nicht an mich gerichtet war, denn ich kannte weder den Absender und auch der Betreff brachte nichts zum Klingeln.

Als guter Mensch der ich auch bin ;) wollte ich die Mail natürlich an den eigentlichen Empfänger weiterleiten, denn seine Adresse stand unten als Ausgabe eines HTML-Formulars in der Mail mit drin.

Als ich die Adresse gesehen habe wurde mir auch klar, warum die bei mir angekommen ist, denn diese war:

big.basti@gouglemail.com

Ich dachte die korrekte Adresse wäre big.basti@googlemail.com und habe die Mail auch mit einer kurzen Erklärung dorthin weitergeleitet. Zu meiner Überraschung landete diese mail prompt wieder in meinem Posteingang.

Was ist denn nun los?

Nun habe ich mal genauer hingeschaut:

Alternative Adressen

Dann ist mir auch der kleine Hinweis im Bild aufgefallen. Anscheinend weiß Google schon dass diese Verwechselung häufiger passiert. und hinter dem Link der sich hinter "Learn more" verbirgt bringt dann auch Licht ins dunkle.

There are three common reasons why Gmail users think they're receiving someone else's mail. Please select the description that matches your situation below.

Your address is similar but has more or fewer dots (.) or different capitalization.

Sometimes you may receive a message sent to an address that looks like yours but has a different number or arrangement of periods. While we know it might be unnerving if you think someone else's mail is being routed to your account, don't worry: both of these addresses are yours.

Gmail doesn't recognize dots as characters within usernames, you can add or remove the dots from a Gmail address without changing the actual destination address; they'll all go to your inbox, and only yours. In short:

  • homerjsimpson@gmail.com = hom.er.j.sim.ps.on@gmail.com
  • homerjsimpson@gmail.com = HOMERJSIMPSON@gmail.com
  • homerjsimpson@gmail.com = Homer.J.Simpson@gmail.com

 

All these addresses belong to the same person. You can see this if you try to sign in with your username, but adding or removing a dot from it. You'll still go to your account.

Nun machts auch Sinn. Aber im Hintergrund scheint noch viel mehr zu passieren, denn man kann auch ein paar Buchstaben drehen oder weglassen und die Mails kommen dann trotzdem immer noch an - zumindest ist mir das schon häufiger passiert.

Auf jeden Fall ist das gut zu wissen, denn beim ersten Mal verwirrt es einen schon ganz schön :)

TL;DR

Google ignoriert Punkte "." im Benutzernamen, daher kommt die Mail dennoch an.

9Feb/120

Aktuelle Zeile bei Kommandozeilen Applikationen aktualisieren

Vielleicht ist euch das ja auch schon Mal passiert, ihr entwickelt eine Kommandozeilen-App und wollt die Aktuelle Zeile ändern. Ein Beispiel dafür wäre ein Fortschrittsbalken oder der beliebte Command-Line-Spinner ( bestehend aus den Zeichen /, -, \, |. Wenn diese nacheinander angezeigt werden sieht das so aus wie ein sich drehender Ast :)

Das Ganze kann in allen Kommandozeilenfenstern, egal ob Unix oder Windows implementiert werden. Der Schlüssel hierzu ist das Sonderzeichen \b - welches das Drücken der Backspace Taste simuliert. Ähnliche Vertreter sind \t für Tab und \n für Zeilenumbruch.

Solange ihr noch keinen Zeilenumbruch abgesetzt habt könnt ihr jede Ausgabe in der aktuellen Zeile widerrufen durch das ausgeben von \b dabei müsst ihr jedes Zeichen einzeln widerrufen. Wenn wir nun also unser Spinner-beispiel betrachten kann man das sehr einfach in .NET umsetzen:


        static void Main(string[] args) {
            string[] states = { "\\", "|", "/", "-" };
            int cur_state = 0;

            while (true) {
                Thread.Sleep(100);

                Console.Write("\b");
                Console.Write(states[cur_state]);
                cur_state++;
                if (cur_state == 4) {
                    cur_state = 0;
                }
            }
        }

Genauso einfach geht das Ganze dann auch in Java:


        public static void Main(string[] args) {

            string[] states = { "\\", "|", "/", "-" };
            int cur_state = 0;

            while (true) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {}

                System.out.print("\b");
                System.out.print(states[cur_state]);
                cur_state++;
                if (cur_state == 4) {
                    cur_state = 0;
                }
            }
        }

Ist in jedem Fall ein nettes Gimmick :) Beachten sollte man noch, dass man hier print() bzw. Write() benutzen muss und nicht println() oder WriteLine() da hier sonst automatisch ein \n mit an das Ende der Zeile gepackt wird!

Get Adobe Flash player