seeseekey.net - Invictus Deus Ex Machina

Möchte man in einer .NET respek­tive Mono­spra­che einen Anwen­dung schrei­ben wel­che mit der Twit­ter API inter­agiert, so sollte man hier­für eine Biblio­thek nut­zen um den Auf­wand in Gren­zen zu halten.

tweetinvi.codeplex.com

Eine emp­feh­lens­werte Bibli­to­thek in die­sem Bereich ist dabei Tweet­invi wel­che auf Code­P­lex zu fin­den ist. Tweet­invi ist dabei unter der Micro­soft Public License lizen­siert und somit freie Soft­ware. Die Biblio­thek ist dabei pro­blem­los in der Lage meh­rere Mil­lio­nen Tweets zu ver­ar­bei­ten und befin­det sich in akti­ver Ent­wick­lung. Ein ein­fa­ches Bei­spiel um einen Tweet abzu­set­zen könnte dabei so aussehen:

IToken token=new Token(twitterAccessToken, twitterAccessTokenSecret, twitterConsumerKey, twitterConsumerSecret);
ITweet tweet=new Tweet(tweetText, token);
bool success=tweet.Publish();

Damit hätte man den ers­ten Tweet mit die­ser Biblio­thek abgesendet.

Wenn man beim Aus­füh­ren einer Mono-Applikation auf einem Ubuntu-Server Feh­ler­mel­dun­gen wie diese:

Unhandled Exception: System.TypeLoadException: A type load exception has occurred.
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: A type load exception has occurred.

zu sehen bekommt, so lässt sich die­ses Pro­blem meist leicht lösen, indem man die pas­sen­den Mono-Bibliotheken durch Instal­la­tion des Pake­tes „mono-complete“ hinzufügt:

apt-get install mono-complete

Danach sollte die ent­spre­chende Anwen­dung ohne Pro­bleme starten.

Manch­mal möchte man eine Zei­chen­kette im Arbeits­spei­cher nicht län­ger als nötig im Klar­text vor­hal­ten. Hier­für gibt es unter .NET/Mono die Klasse „Secu­re­String“. Diese ver­schlüs­selt den Klar­text, so das die­ser nicht ohne wei­te­res im Spei­cher zu fin­den ist. Lei­der ist die Nut­zung der „Secu­re­String“ etwas komplizierter:

SecureString secureString=new SecureString();
secureString.AppendChar('g');
secureString.AppendChar('e');
secureString.AppendChar('h');
secureString.AppendChar('e');
secureString.AppendChar('i');
secureString.AppendChar('m');

// in Klartext umwandeln
IntPtr secureStringPointer=Marshal.SecureStringToBSTR(secureString);
string klartext=Marshal.PtrToStringAuto(secureStringPointer);

Hier muss man abwä­gen, ob sich die Nut­zung eines sol­ches Kon­struk­tes lohnt, oder man wei­ter­hin nor­male Strings für sen­si­ble Daten nutzt.

Im Web kennt man sol­che Boxen zu genüge. Ein Such­feld in wel­chem in aus­ge­grau­ter Schrift „Suchen“ oder ähn­li­ches steht. Unter .NET ist das ganze lei­der nicht als vor­ge­fer­tig­tes Con­trol vor­han­den, so das man hier selbst Hand anle­gen muss. Für ein sol­ches Con­trol nimmt man eine Text­Box und setzt die Events „Enter“ und „Leave“ und befüllt sie wie folgt:

string grayedText="Search...";

private void tbSearch_Enter(object sender, System.EventArgs e)
{
	if(tbSearch.Text==""||tbSearch.Text==grayedText)
	{
		grayedText=tbSearch.Text;
		tbSearch.Text="";
		tbSearch.ForeColor=Color.Black;
	}
}

private void tbSearch_Leave(object sender, System.EventArgs e)
{
	if(tbSearch.Text=="")
	{
		tbSearch.ForeColor=Color.Gray;
		tbSearch.Text=grayedText;
	}
}

Damit steht in der Text­Box der aus­ge­graute Text „Search…“ wel­cher ver­schwin­det, sobald man den Fokus in die Text­Box setzt. Der Platz­hal­ter­text wird nur dann ange­zeigt, wenn kein Inhalt in der Text­box vor­han­den ist.

Wenn man mit nicht von einer Cer­ti­fi­cate Aut­ho­rity signier­ten Zer­ti­fi­ka­ten arbei­tet, so wird man frü­her oder spä­ter fol­gende Feh­ler­mel­dung unter .NET zu sehen bekommen.

Das Remotezertifikat ist laut Validierungsverfahren ungültig.

Gege­ben sei dabei fol­gen­des Beispiel

SmtpClient client=new SmtpClient(host, port);
client.EnableSsl=true;

SSL ist zwar akti­viert, aber das Zer­ti­fi­kat kann in die­sem Fall nicht vali­diert wer­den. Eine Methode um die Vali­die­rung abzu­schal­ten ist dabei fol­gen­den Ein­zei­ler über diese Zei­len zu schreiben:

ServicePointManager.ServerCertificateValidationCallback=delegate { return true; };

Danach bekommt man keine Zer­ti­fi­kats­war­nung mehr und kann die Ver­bin­dung nutzen.

Der Kindle als eBook Rea­der macht vie­les rich­tig. Nur beim Über­tra­gen von eige­nen Doku­men­ten wird es schwie­rig. Es gibt zwar die Mög­lich­keit Doku­mente per Mail oder USB auf den Kindle zu brin­gen, aller­dings wird das in man­chen Fäl­len etwas umständlich.

Der Kindle Paper­white im aus­ge­schal­te­ten Zustand

So bie­tet Ama­zon eine Kon­ver­tie­rung von PDFs in ein auf dem Kindle les­ba­res For­mat an. Um das ganze zu ver­ein­fa­chen, habe ich eine kleine Anwen­dung namens „Kindle Uploa­der“ geschrie­ben. Nach der Kon­fi­gu­ra­tion kann man ganze Ord­ner oder auch ein­zelne Dateien an sei­nen Kindle sen­den. Mit Hilfe der Option „-con­vert“ ist es mög­lich die Kon­ver­tie­rung in das AZW For­mat (für bes­sere Les­bar­keit) anzustoßen:

kindleuploader.exe -convert test.pdf folder test.txt

Die Anwen­dung ist dabei freie Soft­ware unter der GPLv3 und kann auf Git­Hub „besich­tigt“ wer­den. Alter­na­tiv kann das ganze als aus­führ­bare Datei her­un­ter­ge­la­den werden.

Manch­mal ist Mono Deve­lop etwas undurch­sich­tig. So bekam ich bei einem Pro­jekt wel­ches ich neu kom­pi­lie­ren wollte mehr­mals die Fehlermeldung:

Error CS1904: `' is not a valid warning number (CS1904) (CSCL)

Der Com­pi­ler beschwert sich hier­bei dar­über, das eine spe­zi­fi­zierte War­nungs­num­mer nicht exis­tiert. Aller­dings ist es schwie­rig eine nicht vor­han­dene Num­mer zu finden.

Die Com­pi­ler Optionen

Die Lösung lag in den Com­pi­ler Optio­nen des Pro­jek­tes. Hier befand sich unter „War­nun­gen igno­rie­ren“ die Zeile:

0168 ; 0169; 0414; 0618; 0649

Das Pro­blem an die­ser Zeile waren die Leer­zei­chen, wel­che von Mono­De­ve­lop als zu igno­rie­rende War­nun­gen inter­pre­tiert wur­den. Und eine War­nung ohne Num­mer kennt das Sys­tem natür­lich nicht. Nach dem Ent­fer­nen der Leer­zei­chen, kom­pi­lierte auch das Pro­jekt wieder.

Für ein klei­nes Expe­ri­ment war ich auf der Suche nach einer .NET Biblio­thek mit wel­cher sich MIDI Dateien schrei­ben las­sen. Auf den ers­ten Blick fin­det man dabei nur Biblio­the­ken wel­che das MIDI Inter­face anspre­chen, aber sol­che wel­che Midi Dateien schrei­ben kön­nen sind eher sel­ten. Abhilfe schuf hier die Biblio­thek NAu­dio, wel­che unter http://naudio.codeplex.com/ zu fin­den ist. Das Pro­blem an der Biblio­thek ist ihre schiere Größe und die feh­lende Platt­for­mu­n­ab­hä­gig­keit, da für einige Stel­len P-Invokes in native DLLs benö­tigt wer­den. Dane­ben bie­tet NAu­dio wesent­lich mehr als nur MIDI-Support, so das die Biblio­thek für mei­nen Zweck nicht zum tra­gen kam.

Dank der freien Lizenz (unter der Ms-Pl) stellte dies kein Pro­blem da und so wurde libmidi.net aus der Taufe geho­ben. Die Biblio­thek bestand am Anfang aus dem Midi Teil von NAu­dio. Im Laufe der Ent­wick­lung wurde alle Mög­lich­kei­ten für den Zugriff auf MIDI-Geräte ent­fernt. Die Biblio­thek ist damit zu einer klei­nen Biblio­thek zum Lesen und Schrei­ben von MIDI-Dateien gewor­den. Dazu wur­den auch einige Dinge wie die „MidiNote“-Enumeration hin­zu­ge­fügt, anhand deren man die Noten als Noten anstatt als Num­mern ange­ben kann. Im Gegen­satz zum Ori­gi­nal, wel­ches haupt­säch­lich auf die Bear­bei­tung bereits exis­tie­ren­der MIDIs abziehlt, soll die Biblio­thek so gestal­tet wer­den, das auch das Erzeu­gen neuer MIDIs leicht von der Hand geht. Zu fin­den ist das Pro­jekt unter https://github.com/seeseekey/libmidi.net.

Ein Pro­gramm wel­ches in C# geschrie­ben wird, wird beim kom­pi­lie­ren in ein Intermediate-Assembly umge­wan­delt. Das bedeu­tet das der Code in einer Zwi­schen­spra­che dar­auf war­tet auf sei­nem Ziel­sys­tem in nati­ven Code umge­wan­delt zu wer­den. Der Vor– und auch Nach­teil die­ser Vor­ge­hens­weise ist, das sich der Quell­code sehr ein­fach aus dem IL-Code zurück­wan­deln lässt. Im Ide­al­fall ver­liert man bloß einige Variablennamen.

Um das zu ver­hin­dern gibt es soge­nannte Obfu­sca­to­ren, wel­che ver­su­chen den ent­spre­chen­den Quell­text zu ver­schlei­ern, so das er nicht mehr ein­fach zurück­ge­wan­delt wer­den kann. Aber wie so oft im Leben gibt es auch hier einen Wett­lauf mit der Zeit. So gibt es einige Tools wel­che den obfus­kier­ten Quell­text wie­der deob­fus­kie­ren. Eines die­ser Pro­jekte ist „de4dot“ wel­ches unter https://bitbucket.org/0xd4d/de4dot/ zu fin­den ist. Das unter der GPL ste­hende Pro­jekte, erkennt dabei den ver­wen­de­ten Obfu­sca­tor und ver­sucht seine Ände­run­gen soweit wie mög­lich rück­gän­gig zu machen. Dabei wer­den eine statt­li­che Anzahl von Obfu­sca­to­ren, wie der Dot­fu­sca­tor, Goliath.NET und Skater.NET unterstützt.

Unter .NET gibt es an jedem Objekt die Methode „GetHash­Code“ wel­che einen Hash­Code zurück­lie­fert. Das Pro­blem an die­ser Methode ist jedoch das sie vom Objekt selbst imple­men­tiert wer­den muss. Möchte man nun eine Methode mit der man jedes Objekt gene­risch has­hen kann, so ist diese Funk­tion hilfreich:

public string GetSHA1HashFromObject(object obj)
{
	SHA1CryptoServiceProvider sha1Provider=new SHA1CryptoServiceProvider();
	DataContractSerializer serializer=new DataContractSerializer(obj.GetType());

	using(MemoryStream memoryStream=new MemoryStream())
	{
		serializer.WriteObject(memoryStream, obj);
		sha1Provider.ComputeHash(memoryStream.ToArray());
		return Convert.ToBase64String(sha1Provider.Hash);
	}
}

Die Funk­tion seria­li­siert dabei das Objekt und hasht anschlie­ßend das seria­li­sierte Objekt. Damit ist es egal, wel­ches Objekt in die Funk­tion gege­ben wird.