Freitag, 6. Januar 2017

Star Trek (2009) Trailer Soundtrack

Als 2008 (oder 2009?) der erste Trailer für J.J. Abrams Star Trek-Reboot herauskam, haute es mich fast vom Hocker: Nicht nur, weil nach langem Warten endlich wieder einmal ein Star Trek-Film in die Kinosäle kommen sollte, sondern auch, weil der Trailer so sackstark war. Die Hauptschuld daran trug der epische Soundtrack:

Leider konnte ich das Stück seinerzeit nirgends finden, und da im Film selber schlussendlich nichts davon zu hören war, verlor ich den Hammer-Soundtrack bald einmal aus den Ohren.

Fast Forward zum Montag, 1. Januar 2017, wo Stephanie und ich Patrick und Christine nach Gstaad folgten, um das Neujahrsfeuerwerk des Hotels The Alpina Gstaad zu bestaunen. Auf dem Dorfplatz stehend war das Feuerwerk mit verschiedenen Songs unterlegt — unter anderem auch Thomas Bergersens „Empire of Angels“:

Als ich die Tage darauf den iTunes Music Store nach seinen Alben plünderte (ich habe mir das Album „Sun“ gekauft), wurde ich auf sein Projekt Two Steps From Hell aufmerksam, welches Filmmusik produziert.

Als ich mich durch die Vorschau einzelner Songs der Alben durchhörte, starrte ich plötzlich ungläubig auf den Bildschirm, als der Song „Freedom Fighters“ aus den Lautsprechern dröhnte:

Das war der Song, der über 7 Jahre lang verschollen war. Natürlich habe ich das Album noch in der selben Minute gekauft …

… und hat mir wieder einmal gezeigt: Die Wege des Herrn sind unergründlich — und voller Zufall.

Tags: , , , , , , ,
Labels: Medien

Keine Kommentare | neuen Kommentar verfassen

Dienstag, 3. Januar 2017

Steak-Garstufen

Am Neujahrstag haben wir mit einem befreundeten Paar in der Füürgruebe im Ermitage Golf Schönried gespiesen.

Als ich mein Steak — von meinen unzähligen USA-Aufenthalten geprägt — „medium rare“ bestellte, waren unsere Bekannte über die Bedeutung verwirrt, da sie normalerweise die französischen Garstufen verwenden.

Hiess „medium rare“ übersetzt nun wie vom Kellner behauptet „saignant“ (blutig) oder wie vom Päärchen eigentlich gewünscht „à point“?

Eine kurze Google-Suche führte zur Gewissheit: Wenn man sein Steak im Welschland „medium rare“ gebraten haben möchte, muss man es „saignant“ bestellen:

Gast: Mein Entercôte möchte ich gerne medium rare.

Kellner: Sie meinen saignant?

Gast: Nein. Um Himmelswillen. Ja nicht blutig.

Kellner: Aber medium rare und saignant sind das Gleiche.

Fallen Sie nicht über die Garstufe

Nachtrag

Kollege Roman hat mich auf die Speisekarte des Restaurant tonWERK in Regensdorf hingewiesen. Auf der letzten Seite des Menus liest man:

Quelle: Speisekarte

Oder im Klartext:

Um etwaige Unklarheiten zu beseitigen, hier unser Verständnis von Garstufen bei gereiftem Fleisch:

Rare / bleu / stark blutig

Aussen stark geröstet und karamellisiert. Die Kerntemperatur liegt zwischen 45° C und 47° C. Das Fleisch ist noch roh. Die Fleischsäfte sind rot.

Medium rare / saignant / blutig

Aussen stark geröstet und karamellisiert. Die Kerntem- peratur liegt zwischen 50° C und 52° C. Der Fleischkern ist temperiert und die Säfte sind hellrot. Bei greiftem Fleisch ist der Kern nicht mehr dunkelrot – es tritt kein Blut aus.

Medium / à point / rosa

Aussen stark geröstet und karamellisiert. Die Kerntemperatur liegt zwischen 55° C und 60° C. Bei mittlerer Hitze auf den Punkt «rosa» gegart. Die perfekte Garstufe auch für Gäste, die wenig Blutgeschmack haben wollen. Die Besonderheit des ge- reiften Fleisches führt hier zu einem hervorragenden Ergebnis. Ausgenommen beim Rindsfilet Swiss Gourmet.

Well done / bien cuit / leicht rosa

(Wird beim Rindsfilet «Swiss Gourmet» nicht empfohlen) Aussen stark geröstet und karamellisiert. Die Kerntemperatur liegt zwischen 64° C und 70° C. Das Fleisch ist im Kern leicht rosa und hat kein Blut mehr.

Tags: , , , , , , ,
Labels: Leben

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 14. Dezember 2016

Das in Chrome eingebettete Flash-Plugin aktualisieren

Die Aktualisierung von Chrome kann man anstossen, indem man den Browser startet und danach die Adresse

chrome://help/

ansurft.

Um die Aktualisierung des in Chrome integrierten Flash-Plugins anzustossen, startet man den Browser und surft man die folgende Adresse an:

chrome://components/

Dort sucht man den Eintrag „Adobe Flash Player“ und klickt auf den Button „Check for updates“:

Tags: , , , , , ,
Labels: IT

2 Kommentare | neuen Kommentar verfassen

Mittwoch, 14. Dezember 2016

Mehrere Benutzerkonten mit derselben E-Mail-Adresse

Bis kürzlich hatte ich noch nie von Web-Sites gehört, auf welchen man sich mit ein- und derselben E-Mail-Adresse mehrmals registrieren kann. PCP bricht aus mir unerklärlichen Gründen mit dieser Best Practice. Daraus resultieren dann Usability-Nightmares wie diese hier:

PCP Selbe E-Mail mehrere Benutzer

Tags: , , , ,
Labels: Funny, Web

Keine Kommentare | neuen Kommentar verfassen

Dienstag, 13. Dezember 2016

mitmproxy: Server-Antworten umschreiben (oder: M6 Geoblocker umgehen)

Heute durfte ich für einen Kollegen in den USA eine im Internet als Stream verfügbare M6 News-Sendung rippen.

Geoblocker

Damit ich an die m3u8-Datei des Streams herankam, musste ich aber zuerst die Geo-Sperre umgehen. Die Web-Site frägt nämlich beim Aufruf (gleich zweimal) ab, in welchem Land sich der Surfer befindet. Hierzu ruft der JavaScript-Code der Web-Site folgende zwei URLs auf:

Als Antwort erhält der Browser folgenden JSON-Code zurück (IP anonymisiert):

{"offset":"2","isp":"Andreas Fink","areas":[10],"country_code":"CH","asn":"AS6775","ip":"85.195.0.0"}

Diese Antwort bewegt den Player dazu, folgende Fehlermeldung anzuzeigen:

M6 6play Geoblock

mitmproxy installieren und konfigurieren

Der erste Task war somit klar: Ich musste mit dem quelloffenen Tool mitmproxy alle HTTP(S)-Requests meines iPads proxyifizieren und dann obige JSON-Antwort mit einer validen Antwort ersetzen, so wie sie über einen französischen ISP erfolgen würde.

mitmproxy hatte ich bereits auf meinem lokalen Linux-Server konfiguriert, weshalb ich auf dem iPad in den Netzwerkeinstellungen den Proxy nur noch erfassen musste: 10.0.X.Y:8888.

Auf dem Linux-Server startete ich mitmproxy folgendermassen:

# mitmproxy -p 8888

Als nächstes musste ich noch das mitmproxy-Zertifikat auf dem iPad installieren, damit HTTPS-Verbindungen entschlüsselt und umgeschrieben werden können. Hierzu reicht es, auf dem iPad die folgende URL aufzurufen …

mitm.it

… und den Anweisungen zu folgen (ACHTUNG: Sicherheitssensitive Personen löschen das Zertifikat nach der Verwendung wieder vom iPad. Es findet sich unter Settings > General > Profiles).

Inline-Script zum Umschreiben von Antworten

Damit ich vom Proxy-Server empfangene Antworten der M6-Server umschreiben konnte, musste ich nun noch ein mitmproxy Inline-Script einbauen, welches Aufrufe auf die oben genannten URLs abfängt und nach meinem Gusto umschreibt.

Hierzu legte ich unter /tmp/m6-geoip.py folgendes Python-Script ab:

import json

def response(context, flow):
	f = open('/tmp/mitm.log','a+')
	url = flow.request.get_url()
	f.write('URL "' + url  + '"' + "\n")

	if url.endswith('geoInfo') or url.endswith('geoInfos'):
		f.write('    matched' + "\n")
		data = json.loads(flow.response.content)
		# {"offset":"2","isp":"Andreas Fink","areas":[10],"country_code":"CH","asn":"AS6775","ip":"85.195.0.0"}
		# {"offset":"2","isp":"QSC AG","areas":[1,2,3,10,11],"country_code":"FR","asn":"AS20676","ip":"92.222.83.58"} via http://www.franceproxy.net
		#data["country_code"] = "FR"
		#jsonOut = json.dumps(data)
		jsonOut = '{"offset":"2","isp":"QSC AG","areas":[1,2,3,10,11],"country_code":"FR","asn":"AS20676","ip":"92.222.83.58"}'
		flow.response.content = jsonOut
		f.write("    " + jsonOut + "\n")
	f.close()

Tipp 1: Da selten Leute vom Himmel gefallen sind, welche ein Script auf Anhieb richtig hingekriegt haben, hilft es zum Debugging, statt mitmproxy mitmdump zu verwenden:

# mitmdump -e -p 8888 -s "/tmp/m6-geoip.py"

Bei Python-Problemen mit dem Inline-Script wird der Stack Trace und die Fehlermeldung direkt auf der Kommandozeile ausgegeben.

Tipp 2: Die Ausgabe aller URLs in eine Log-Datei resultiert in Performance-Einbussen, kann für das Debugging aber sehr nützlich sein.

Anschliessend startete ich den mitmproxy neu:

# mitmproxy -p 8888 -s "/tmp/m6-geoip.py"

JSON-Quelle

Doch von wo hatte ich den JSON-String?

Nach etwas Googeln fand ich folgenden Proxy-Service:

www.franceproxy.net

Gibt man dort eine der obigen URLs ein, erhält man als Antwort den JSON-Code, welchen ich dann auch für die Umgehung des Geoblockers verwendete.

Kostenloser Tipp an die Web-Entwickler von M6: Die Geo-Location eines Aufrufs prüft man nicht im JavaScript auf dem Client, sondern auf dem Server.

Der erneute Versuch im Web-Browser

Ich lud die Web-Seite auf dem iPad erneut — erhielt zwar eine Fehlermeldung, dass trotzdem irgendetwas schief gelaufen war, doch im mitmproxy-Log fand sich die sehnlichst gesuchte URL zur m3u8-Datei:

lb.cdn.m6web.fr

Daraus — und mit Informationen der aktuellsten Sendung, welche sich auch für Schweizer streamen lässt — leitete ich die tatsächliche URL zur Master-Playlist ab:

e112.cdn.m6web.fr

Von dieser Datei war es dann nur noch ein Katzensprung zur m3u8-Datei mit dem Stream mit der höchsten Bit-Rate:

e112.cdn.m6web.fr

Und so lud ich den Stream dann mit ffmpeg herunter:

$ ffmpeg -protocol_whitelist file,http,https,tcp,tls -i "http://e112.cdn.m6web.fr/usp/mb_sd3/2/8/1/Le-1945_c11636016_19-45-du-dimanche-11/Le-1945_c11636016_19-45-du-dimanche-11_unpnp.ism/Le-1945_c11636016_19-45-du-dimanche-11_unpnp-audio_fra=93468-video_eng=1501000.m3u8" video.mp4

Tags: , , , , , , , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Dienstag, 13. Dezember 2016

~/Library/Caches/com.apple.bird gigantisch

Wie bereits an folgenden Orten dokumentiert ist auch mein com.apple.bird auf 48.9 GB angewachsen:

Ein auf Github gefundenes Script namens blame-bird.py habe ich ausgeführt; das Resultat:

$ python blame-bird.py 
com.apple.Numbers                                   0.00MB      1
F6266T9T75.com.apple.iMovie                         0.00MB      1
LWL9XTYF8Q.com.syniumsoftware.macfamilytree7        0.00MB      1
com.apple.Pages                                     0.00MB      2
com.apple.Keynote                                   0.00MB      2
8YE23NZS57.com.kayak.travel                         0.00MB      3
iCloud.com.bodunov.galileo                          0.00MB      7
com.apple.mail                                      0.00MB     16
com.apple.TextInput                                 0.00MB     37
com.apple.TextEdit                                  0.00MB      3
4R6749AYRE.com.pixelmatorteam.pixelmator            0.00MB     53
com.apple.shoebox                                   0.00MB     38
iCloud.com.apple.iBooks                             0.02MB    310
57T9237FN3.net.whatsapp.WhatsApp                35564.12MB    717

Accounted for: 35564MB.  Still unaccounted: 16968MB

Also auch bei mir WhatsApp, welche das mit dem iCloud-Backup einfach nicht gebacken kriegen (im Sommer plagte mich folgendes, verwandtes Problem: WhatsApp kann nicht auf iCloud backupen).

Ich habe den Ordner nun gelöscht und hoffe, dass er nicht bald wieder fettleibig wird …

Labels: IT

2 Kommentare | neuen Kommentar verfassen

Montag, 5. Dezember 2016

Geschwindigkeiten von SD-Karten

Die Industrie unterscheidet zwei SD-Kartenarten: Standard sowie UHS.

Die (neueren) Standard-Karten kodieren ihre Geschwindigkeiten als Zahl in einem Kreis, aufgedruckt auf das Etikett:

Zahl im Kreis Geschwindigkeit
10 10 MBit/s
6 6 MBit/s
4 4 MBit/s
2 2 MBit/s

Die UHS-Karten haben die Geschwindigkeit als Zahl in einem u-ähnlichen Symbol aufgeführt:

Zahl im U Geschwindigkeit
3 30 MBit/s
1 10 MBit/s

Quelle: Speed Class

Tags: , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 27. November 2016

Die REST-API von SeedDMS ansprechen

Vor einiger Zeit habe ich mir auf meinem Linux-Server hier zu Hause das Dokumentenmanagement-System SeedDMS installiert. Ich habe dieses Produkt ausgewählt, weil es mit PHP programmiert ist (eine Alternative benötigt Java und scheint nach einem Testlauf nicht die erhofte Maturität aufzuweisen.)

Obwohl die Installation dieses Produkts auch nicht ganz simpel ist (dies erläutere ich dereinst in einem separaten Blog-Artikel), weist es die nötige Maturität aus und bringt eine ansehnliche Liste von Features mit. Grösstes Manko ist eine aktuelle, für Endanwender verständliche Dokumentation.

Eine der von mir gesuchten Funktionalitäten ist die REST API, welche man unter der URL /restapi/index.php ansprechen kann.

Als ich damit die ersten API-Calls machen wollte, kam leider eine leere Antwort zurück. Im php.err fand sich folgende Zeile:

...
[27-Nov-2016 11:55:44 Europe/Zurich] PHP Warning:  require(Slim/Slim.php): failed to open stream: No such file or directory in /var/www/seeddms/restapi/index.php on line 55
[27-Nov-2016 11:55:44 Europe/Zurich] PHP Fatal error:  require(): Failed opening required 'Slim/Slim.php' (include_path='/var/www/seeddms/::.:/usr/share/php/') in /var/www/seeddms/restapi/index.php on line 55
...

Hmmm! Da scheinen mit der Quickstart-Version 5.0.7 (die einzige, die ich auf meinem Server zum Laufen gebracht zu habe) nicht alle externen Dependencies mitzukommen.

Ein Issue auf Sourceforge bestätigt meine Vermutung, bringt aber keine Lösung mit (was bringt es dem Endbenutzer, wenn die Dependency im README ergänzt wird?).

Ein, zwei Google-Suchen später finde ich dann einerseits die Web-Site des Frameworks, andererseits das Github-Repository.

Doch wie und wo installiere ich das Paket nun?

Eine weitere Google-Suche leitet mich auf eine Web-Site weiter, welche die Dokumentenstruktur einer älteren SeedDMS-Installation auflistet und dabei auch einen Ordner Slim aufweist. Der Ordner enthält folgende Dateien:

Als ich diese Struktur mit dem Github-Repository verglich, konnte ich keine Ähnlichkeiten feststellen.

Dann der Geistesblitz: Vielleicht verwendet SeedDMS noch eine ältere Version des Frameworks? Richtig geraten: Aktuell trägt das Framework die Version 3.0, SeedDMS baut aber auf Version 2.0 des Frameworks auf.

Ein Blick auf die Dateistruktur des 2.x Branches bestätigt meine Vermutung. Ich lade mir von diesem Branch die ZIP-Datei herunter und kopiere anschliessend den Unterordner Slim im Ordner Slim-2.x in das Web-Root von SeedDMS (/var/www/seeddms/Slim).

Nun klappt der Aufruf der API, weil PHP die Include-Datei unter /var/www/seeddms/Slim/Slim.php findet!

Am Ende der /restapi/index.php findet sich auch eine Liste aller verfügbarer API-Calls:

$app->post('/login', 'doLogin');
$app->get('/logout', 'doLogout');
$app->get('/account', 'getAccount');
$app->get('/search', 'doSearch');
$app->get('/searchbyattr', 'doSearchByAttr');
$app->get('/folder/:id', 'getFolder');
$app->post('/folder/:id/move', 'moveFolder');
$app->delete('/folder/:id', 'deleteFolder');
$app->get('/folder/:id/children', 'getFolderChildren');
$app->get('/folder/:id/parent', 'getFolderParent');
$app->get('/folder/:id/path', 'getFolderPath');
$app->get('/folder/:id/attributes', 'getFolderAttributes');
$app->post('/folder/:id/createfolder', 'createFolder');
$app->put('/folder/:id/document', 'uploadDocument');
$app->get('/document/:id', 'getDocument');
$app->delete('/document/:id', 'deleteDocument');
$app->post('/document/:id/move', 'moveDocument');
$app->get('/document/:id/content', 'getDocumentContent');
$app->get('/document/:id/versions', 'getDocumentVersions');
$app->get('/document/:id/version/:version', 'getDocumentVersion');
$app->get('/document/:id/files', 'getDocumentFiles');
$app->get('/document/:id/file/:fileid', 'getDocumentFile');
$app->get('/document/:id/links', 'getDocumentLinks');
$app->get('/document/:id/attributes', 'getDocumentAttributes');
$app->put('/account/fullname', 'setFullName');
$app->put('/account/email', 'setEmail');
$app->get('/account/locked', 'getLockedDocuments');
$app->post('/accounts', 'createAccount');
$app->get('/accounts/:id', 'getAccountById');
$app->put('/accounts/:id/disable', 'setDisabledAccount');
$app->post('/groups', 'createGroup');
$app->get('/groups/:id', 'getGroup');
$app->put('/groups/:id/addUser', 'addUserToGroup');
$app->put('/groups/:id/removeUser', 'removeUserFromGroup');
$app->put('/folder/:id/setInherit', 'setFolderInheritsAccess');
$app->put('/folder/:id/access/group/add', 'addGroupAccessToFolder'); // 
$app->put('/folder/:id/access/user/add', 'addUserAccessToFolder'); // 
$app->put('/folder/:id/access/group/remove', 'removeGroupAccessFromFolder'); 
$app->put('/folder/:id/access/user/remove', 'removeUserAccessFromFolder'); 
$app->put('/folder/:id/access/clear', 'clearFolderAccessList');
$app->run();

Eine simple API-Abfrage schaut folgendermassen aus:

  1. /restapi/index.php/login mit den POST-Parametern user und pass
  2. Das Session-Cookie mydms_session=XXX; in eine Variable speichern. Es muss bei allen folgenden API-Calls mit übermittelt werden
  3. /restapi/index.php/searchbyattr?name=AttrName&value=AttrValue mit den GET-Parametern name und value
  4. Die Antwort wird als JSON zurückgegeben, welche mit json_decode() in ein PHP-Objekt/Array geparsed werden kann

Tags:
Labels: IT, Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 20. November 2016

Der beste Indikator, dass US-Asiaten tatsächlich die vielgepriesene Model Minority sind?

Eine Kollegin von Stephanie und mir hat heute auf Facebook den Artikel The real secret to Asian American success was not education gepostet.

Die Hypothese des Artikels ist es, dass die asiatischen Einwanderer in die USA nicht das höchste Einkommen aller US-Bevölkerungsgruppen verzeichnen, weil „sie“ strebsam und arbeitswillig sind sowie ihren Nachwuchs mit allen Mittel auf beste Schulnoten trimmen. Sondern weil seit den 1960er der Rassismus gegen diese Bevölkerungsgruppe markant zurückgegangen ist und die Gruppe im Berufsleben wie auch im gesellschaftlichen Leben zunehmend akzeptiert sei.

Man kann diese Model Minority noch so sehr über den Klee loben und herleiten, wieso gerade „die“ Asiaten geschafft haben, was bisher anderen Minderheiten (allen voran Afro-Amerikanern, aber auch Latinos) verwehrt geblieben ist — ich behaupte: Solange wir nicht mindestens ein halbes Dutzend asiatische Gesichter auf Apples Leadership Web-Seite sehen, haben es „die“ Asiaten (als gäbe es „die“ Europäer …) noch nicht geschafft, mit dem weissen Mann auf einer Stufe zu stehen:

Apple Executive Profiles

Dies ist aus meiner Sicht der beste, wenn auch völlig unwissenschaftliche Indikator, um die Gültigkeit des Model Minority-Status zu verifizieren.

Nachtrag

Wer aber wirklich Grips hat, wird insbesondere die Verallgemeinerung der „Asiaten“ in Frage stellen. Es macht auch keinen Sinn, einwandernde „Europäer“ alle in einen Topf zu werfen. Innerhalb der asiatischen Minderheit gibt es nämlich markante Unterschiede:

So, while Chinese-Americans and Indian-Americans are among the most prosperous groups in the country, Korean-Americans, Vietnamese-Americans, and Filipino-Americans have lower median personal earnings than the general population.

Quelle: THE TWO ASIAN AMERICAS

Nachtrag 2

Die Harvard Business Review gibt in einem Artikel mögliche Erklärungsansätze ab, wieso ein solcher „bamboo ceiling“ existiert:

As Wesley Yang wrote in New York magazine, Western society teaches that “the squeaky wheel gets the grease,” while Eastern society teaches that “the nail that sticks out gets hammered down.” […]

So Asians face a double bind as well: If they act more dominant, they will be less liked, but if they do not project dominance, they will not be seen as leaders.

Quelle: Why Aren’t There More Asian Americans in Leadership Positions?

Tags: , , , , , ,
Labels: Apple, USA

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 16. November 2016

Wenn sogar James Kunstler daneben liegt …

Knapp daneben ist auch vorbei … Ich mag den Contrarian und Prepper Kunstler sehr, doch das will nicht heissen, dass auch der Mann regelmässig warme Luft aussondert. Hier wagte er im September 2015 einen Blick in die Glaskugel:

I would not even bet against the possibility of the 2016 selection being canceled in some manner.

Quelle: The Parties Crawl Off to Die

Tags: , , , ,
Labels: USA

Keine Kommentare | neuen Kommentar verfassen