This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Seit ich Ende der 90er Jahre das erste mal "Online" gewesen bin, war ICQ mein ständiger Begleiter. Ich weiß nicht mehr, wann genau ich meine jetzige ICQ-Nummer registriert habe, aber ich konnte die Spuren bis ins Jahr 2000 zurückverfolgen. Andere Instant-Messaging-Dienste wie AIM oder MSN waren für mich immer tabu, und selbst als ich mich bei meinem Wechsel auf Linux als Betriebssystem mit Multi-Protokoll-Clients auseinander setzen musste, bin ich Mirabilis treu geblieben. Sogar den Verkauf an AOL habe ich akzeptiert.
Das einzige Protokoll, mit dem ich hin und wieder geliebäugelt habe, ist das freie Jabber, aber mangels Jabber-Kontakten war es mir den Aufwand nie Wert. Mit wem sollte ich schon über Jabber chatten...?
Bis heute. Denn mit dieser Aktion (also die Aussperrung von vielen alternativen ICQ-Programmen) hat es AOL echt übertrieben. Die Verwendung anderer Clients war zwar schon immer verboten, immerhin gehen damit potentielle Werbeeinnahmen verloren. Doch zeigen solche Aktionen, welche Macht ein zentralisierter und proprietärer Dienst hat. Angenommen, wir würden ICQ für die Firmenkommunikation nutzen, worüber wir tatsächlich schon nachgedacht haben. Dann wären wir gestern ohne eigenes verschulden einen Tag lang nicht erreichbar gewesen.
Deshalb habe ich mir heute einen Jabber-Account eingerichtet. Für die, die sich damit nicht auskennen: Jabber ist, ähnlich wie E-Mail, ein dezentrales Protokoll. Das heißt, es gibt weder das Jabber-Programm, noch die Jabber-Website, auf der man sich anmelden kann. Statt dessen sucht man sich erstmal einen Serveranbieter aus, so wie man sich zum Beispiel auch bei der Einrichtung einer E-Mailadresse zwischen GMX, Web.de, GoogleMail usw. entscheidet. Dies kann zum Beispiel jabber.org oder der Chaos Computer Club sein, aber auch kommerzielle Dienstleister wie United Internet (GMX, Web.de, etc) bieten diesen Dienst an. Meistens wird es dann einfach XMPP-Protokoll genannt, nach dem Namen des standardisierten Teil des Jabber-Protokolls. Alternativ kann man sich natürlich auch einen eigenen Server einrichten, wenn man über die entsprechende Hardware und Internetanbindung verfügt (Wink mit dem Zaunpfahl ans Rechenzentrum der Uni :-)). Ich hab mich für den Jabber-Dienst des CCC entschieden.
Als nächstes sucht man sich einen Client für sein Betriebssystem aus (gerne auch einen Client, der mehrere Dienste beherscht), installiert ihn, und meldet sich darüber bei dem gewählten Serverdienst an. Viele Programme schlagen auch gleich eine umfangreiche Liste von in Frage kommenden Diensten vor, so dass man den ersten Schritt eventuell optional ist. Bei Pidgin sieht das ganze dann so aus, wenn man unter "Protokoll" den Eintrag "XMPP" ausgewählt hat:
Nun noch die Daumen drücken, dass der gewählte Spitzname auf dem Server verfügbar ist und anmelden. Falls der Name schon durch jemand anderen genutzt wird, muss man entweder einen anderen Server oder einen anderen Namen auswählen.
Fertig. Der Rest ist im großen und ganzen genauso, wie man es von ICQ kennt. Nur, dass es einige weitere Features wie verschlüsselte Verbindungen gibt, und dass der Ausfall eines zentralen Serverdienstes nicht das ganze Netzwerk lahmlegen kann (egal ob Absicht oder Versehen).
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Ubuntu 8.10 ("Intrepid Ibex") uses the kernel's default suspend system, swsusp, but lacks support for TuxOnIce (formally known as "suspend2"). TOI has some advantages to the classic suspend system, for example "suspend to file", "LZW compression" (for faster resuming) and the ability to cancel any suspend request by pressing ESC. Have a look at the feature list for a comparison of these systems.
Espacially "suspend to file" is extremly important to me, because it allows to resume from an encrypted root partition. Of course, this also works with swsusp by using an encrypted swap device, but then you can't use a random password (or a password file stored on root) and have to enter at least two passwords when booting or resuming: one for root (/) and one for swap.
To add TOI support to Ubuntu, you have to build your own kernel. It's pretty easy, but if you use restricted kernel modules (drivers for your graphic card, VMWare/VirtualBox, ...) you will have to recompile them. So, here we go. First of all, download the kernel source and install some additional packages required at compile time:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Warning: At the moment I can not recommend to use this script in conjunction with filewriter if you use a journaling filesystem for your root partition (ext3, reiser, ...). The reason is that when using filewriter the initramfs-script in /etc/initramfs-tools/scripts/local-premount/resume_tuxonice mounts this partition read-only to get the hibernation file's target. Unfortunately, the journal will be replayed in any case, so "mount -r /dev/hdX" does not mean "mount /dev/hdX, but don't make any changes on it". And this may result in a filesystem corruption because the resumed system things that these open transaction have not been handled yet. I'll do some changes to the scripts during the weekend, so please be patient of you want to "suspend to file". Yesterday, I described how to patch TuxOnIce-support into Ubuntu's kernel image. Today we will learn how to integrate this into Ubuntu's default hibernation framework, pm-hibernate. By doing this, you'll benefit from TuxOnIce' features without modifying your bootloader's configuration file and will be able to use your desktop's "Suspend to Disk"-command without changing any system file (because a customized system file might be overwritten on your next update). Furthermore, you will be able to combine suspend to disk with encrypted swap devices or (I prefer this) suspend to a file on your encrypted root partition.
Please note that the scripts I'll introduce are tested only by myself (yet), and they still lack of some features. I would be happy about every improvement. And of course I do not provide any warranty, you'll do this on your own risk. I think that the worst thing that might happen is that data on your root partition gets lost. But of course you're doing backups, don't you?
So, let's start. Oh, wait... did you ensure that you have a suitable backup? Ok. First I'll introduce what has to be done, and at the end I'll provide the scripts that implements this. Well, the first thing we have to do is to add resume support into Ubuntu's initramfs-Image. That is the file stored in /boot, starting with ' initrd.img' and ending with your kernel's version. If you're curious: it's a gzip'd cpio-archive, you can extract it using the following command:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
If you experience problems or poor performance using Ubuntu's latest nVidia driver nvidia-glx-177 (as I did with a "nVidia Quadro NVS 160M"), try to upgrade to version 180. A package has been build for the next version of ubuntu (called "Jaunty Jackalope"), but sadly it has not been backported to Intrepid yet.
Who cares, I'll explain how to use Jaunty's repository with Intrepid to install this driver. First, make sure that you installation is up to date:
sudoapt-get update
sudoapt-get upgrade
Now, add Jaunty's "universe" repository to Apt's sources:
Prohibit an unmeant package replacement using Apt pinning. Edit /etc/apt/preferences (which might not exist yet) and put the following lines into it:
Package: *
Pin: release a=jaunty
Pin-Priority: 40
Multiple entries have to be separated by blank lines. If you want to know what this entries mean: there is an excellent (german) article at FedoraWiki.
Now run apt-get update again. If you upgraded before, apt-get upgrade should report zero updates. If there is a bunch of updates now that has not occured before, cancel and check wether you've edited /etc/apt/preferences correctly.
Last step: install the driver.
sudoapt-getinstall nvidia-glx-180
If you did not used the proprietary driver before, you have to edit /etc/X11/xorg.conf. Or, what I would suggest, install and run envyng to replace your current driver.
Beware
Unfortunately, Suspend-To-Disk-Support seems to be completely broken in this version. X crashes on resume. I was not able to get this working, neither with 180.06 nor with 180.11. At the moment, I've installed nvidia-glx-173 again.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Symfony provides a nice feature called "embedded Forms" ( sfForm::embedForm) to embed subforms into a parent form. This can be used to edit multiple records at the same time. So let's say you have a basic user table called 'sf_guard_user' and a profile table called 'user_profile', then you might follow this guide to merge these forms together: lib/forms/doctrine/sfUserGuardAdminForm.php:
classsfGuardUserAdminFormextendsBasesfGuardUserAdminForm{publicfunctionconfigure(){parent::configure();// Embed UserProfileForm into sfGuardUserAdminForm$profileForm=newUserProfileForm($this->object->Profile);unset($profileForm['id'],$profileForm['sf_guard_user_id']);$this->embedForm("profile",$profileForm);}}
Remember to add "profile" to the list of visible columns in apps/backend/modules/sfGuardUser/config/generator.yml as decribed in the linked guide. The result may look like this:
This does what it is expected to do, but it doesn't look very nice. Especially for 1:1 related tables I'm more interested in a solution that looks like this:
You can reach this using sfForm::mergeForm, but sadly the merged model won't get updated and you'll run into problems if the forms are sharing fieldnames. The solution is the following method embedMergeForm which can be defined in BaseFormDoctrine to be avaible in all other forms:
lib/forms/doctrine/BaseFormDoctrine.php:
abstractclassBaseFormDoctrineextendssfFormDoctrine{/**
* Embeds a form like "mergeForm" does, but will still
* save the input data.
*/publicfunctionembedMergeForm($name,sfForm$form){// This starts like sfForm::embedForm$name=(string)$name;if(true===$this->isBound()||true===$form->isBound()){thrownewLogicException('A bound form cannot be merged');}$this->embeddedForms[$name]=$form;$form=clone$form;unset($form[self::$CSRFFieldName]);// But now, copy each widget instead of the while form into the current// form. Each widget ist named "formname|fieldname".foreach($form->getWidgetSchema()->getFields()as$field=>$widget){$widgetName="$name|$field";if(isset($this->widgetSchema[$widgetName])){thrownewLogicException("The forms cannot be merged. A field name '$widgetName' already exists.");}$this->widgetSchema[$widgetName]=$widget;// Copy widget$this->validatorSchema[$widgetName]=$form->validatorSchema[$field];// Copy schema$this->setDefault($widgetName,$form->getDefault($field));// Copy default valueif(!$widget->getLabel()){// Re-create label if not set (otherwise it would be named 'ucfirst($widgetName)')$label=$form->getWidgetSchema()->getFormFormatter()->generateLabelName($field);$this->getWidgetSchema()->setLabel($widgetName,$label);}}// And this is like in sfForm::embedForm$this->resetFormFields();}/**
* Override sfFormDoctrine to prepare the
* values: FORMNAME|FIELDNAME has to be transformed
* to FORMNAME[FIELDNAME]
*/publicfunctionupdateObject($values=null){if(is_null($values)){$values=$this->values;foreach($this->embeddedFormsAS$name=>$form){foreach($formAS$field=>$f){if(isset($values["$name|$field"])){// Re-rename the form field and remove// the original field$values[$name][$field]=$values["$name|$field"];unset($values["$name|$field"]);}}}}// Give the request to the original methodparent::updateObject($values);}}
This method ensures that each fieldname is unique (named 'FORMNAME|FIELDNAME') and the subform is validated and saved. It is used like embedForm:
lib/forms/doctrine/sfUserGuardAdminForm.php:
classsfGuardUserAdminFormextendsBasesfGuardUserAdminForm{publicfunctionconfigure(){parent::configure();// Embed UserProfileForm into sfGuardUserAdminForm// without looking like an embedded form$profileForm=newUserProfileForm($this->object->Profile);unset($profileForm['id'],$profileForm['sf_guard_user_id']);$this->embedMergeForm("profile",$profileForm);}}
Feel free to use this method in your own project. Maybe this method get's merged into Symfony some day ;-)
Update
frostpearl reported a problem using embedFormMerge() in conjunction with the autocompleter widget from sfFormExtraPlugin. If you expire these problems try to replace all occurences of $name|$field with $name-$field.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Neben den klassischen WLANs "Uni Osnabrueck" und "FH Osnabrueck" sind beide Hochschulen seit längerem auch Teil des WLAN-Netzwerkes eduroeam. Für die Studenten hat dieses Netzwerk den Vorteil, dass sie auch den Zugang der jeweils anderen Hochschule mitnutzen können. Mit Kubuntu und seiner komischen NetworkManager-Lösung konnte ich mich dort nie erfolgreich anmelden, aber mit Mandriva geht es relativ problemlos.
Dann öffnet man die Netzwerk-Konfiguration "draknetcenter" und wählt das gefundene "eduroam"-Netzwerk (auf die Bilder klicken zum Vergrößern):
Ein Mausklick auf den Button "Konfigurieren" bringt einen auf die Einstellungsseite. Als Verschlüsselungsmodus muss "WPA/WPA2 Enterprise" ausgewählt sein, der "EAP Login/Benutzername" entspricht dem Benutzernamen für die Universitätsdienste mit angehängtem "@uni-osnabrueck.de", also z.B. "username@uni-osnabrueck.de", und das "EAP Passwort" ist das selbe, mit dem man sich z.B. in den Webmaildienst oder dem Stud.IP einlogt:
Für das eduroam-Netzwerk müssen noch einige "Fortgeschrittene Optionen" konfiguriert werden, indem der entsprechende Knopf am Ende der Seite angeklickt wird. Hier sind die folgenden Einstellungen zu treffen:
EAP CA Zertifikat: Vollständiger Pfad zur heruntergeladenen Zertifikatskette
Fertig, im Normalfall sollte das Netzwerk nun verbinden. Falls es nicht klappt hat es bei geholfen, die Datei /etc/wpa_supplicant.conf nach dem network mit der Zeile ssid="eduroam" zu suchen und einige überflüssige Zeilen zu entfernen, so dass der Ausschnitt danach so aussieht (die Reihenfolge der Einträge ist egal):
Nun noch mit dem Befehl /etc/init.d/network restart das Netzwerk neu starten und fertig. Natürlich kann man alternativ auch gleich die Datei /etc/wpa_supplicant.conf bearbeiten, wenn man keine Lust auf den grafischen Assistenten verspürt ;-)
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
In my installation, KDE failes to lock the screen on suspend / hibernate, even if the checkbox "lock screen" in the "Energieverwaltung" (how is this labeled in english? Power configuration? Don't know...) is enabled. So I've adapted this patch to Mandriva.
Create the file /etc/pm/sleep.d/50-lock with the following content:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
In my current Symfony project I have a model called "Country" and a model called "Region". A Region always belongs to a Country, and this country will never change.
I've used Doctrine's admin generator to create the administration backend:
$ php symfony doctrine:generate-admin --plural="Countries" backend Country
$ php symfony doctrine:generate-admin backend Region
This command produces two modules, "apps/backend/modules/country/" and "apps/backend/modules/region/", and the following entries in apps/backend/config/routing.yml:
region:class: sfDoctrineRouteCollection
options:model: Region
module: region
prefix_path: region
column: id
with_wildcard_routes:truecountry:class: sfDoctrineRouteCollection
options:model: Country
module: country
prefix_path: country
column: id
with_wildcard_routes:true
You can reach this with minimal effort. First, you have to modify the routing. Change the entry for region as shown below (changed line is in bold font):
apps/backend/config/routing.yml:
region:class: sfDoctrineRouteCollection
options:model: Region
module: region
prefix_path: country/:country_id/region
column: id
with_wildcard_routes:true
500 | Internal Server Error | InvalidArgumentException
The "/country/:country_id/region/:action/action.:sf_format" route has some missing mandatory parameters (:country_id).This is because the (automatically generated) region view tries to call 'url_for()' for actions like 'filter' or 'add', and there is an parameter called 'country_id' defined which is missing in the argument list. You can solve this problem by overwriting the 'execute()' function in the action class.
publicfunctionexecute($sfRequest){$this->forward404Unless($country_id=$sfRequest->getUrlParameter(‘country_id’));$this->forward404Unless($this->country=Doctrine::getTable(‘Country’)->find($country_id));$this->getContext()->getRouting()->setDefaultParameter(‘country_id’,$country_id);if($id=$sfRequest->getUrlParameter(‘id’)){$this->getContext()->getRouting()->setDefaultParameter(‘id’,$id);}$result=parent::execute($sfRequest);// UPDATE: This is required for the 'new' actionif(isset($this->form)&&$this->form->getObject()&&$this->form->getObject()->isNew()){$this->form->getObject()->country_id=$country_id;}return$result;}
This will set the current country id as default parameter for all calls to methods like 'link_to()' or 'url_for()', and abort if an valid id is missing.
Of course you still have to modify the filters and forms to regard the given country as default, and add some extra actions to the Country view, but the most trickiest part is done. Have a look at this article from Sven to learn how to modify the default filter and read Jobeet Tutorial, Chapter 12 to see how the default actions can be customized.
If you expire some problems with 'new' and 'edit' forms (action="/backend.php/country/region" in <form>-tag), read bug report #6881. Update: This problem can be solved by setting the 'country_id' field of new objects (e.g. by overriding executeNew() and executeCreate()).
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
In my current Abobe Flex project, I needed to upload multple generated files and form fields to a server. UploadPostHelper by Jonathan Marston is a great for uploading one file at time, but sadly I couldn't use (or even modify) it - it's licensed under NonCommercial CC, and my project is a commercial one.
So I had to write my own code which I would like to share with other's (dual-licensed under MPL 1.1 and LGPL 2.1).
Usage of HttpPostData-class: <Update April 1st 2010>I had an error in this text for a half year and nobody noticed? Strange...</Update>
Create an Instance of HttpPostData:
varpostData:HttpPostData =newHttpPostData()
Add your parameters and file attachments
postData.addParameter('foo1','bar1');// POST-Field 'foo1' has value 'bar1'
postData.addParameter('foo2','bar2');// POST-Field 'foo2' has value 'bar2'// POST-Field 'uploadedFile1' contains someBinaryData1 (ByteArray)// as 'application/octet-stream' with filename 'uploadedFile1'
postData.addFile('uploadedFile1', someBinaryData1);// POST-Field 'uploadedFile2' contains someBinaryData2 (ByteArray)// as 'image/png' with filename 'image.png'
postData.addFile('uploadedFile2', someBinaryData2,'image.png','image/png')
Close this object. This will append the ending boundary to the data which makes it impossible to add additional form data.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Wie schon erwähnt fehlt meinem neuen Notebook leider ein UMTS-Model. Nun ja, mein Handy habe ich immer dabei und dank der Fonic Tagesflatrate (2,50 EUR pro Kalendertag) kann ich in wichtigen Fällen darüber online gehen. Doch dazu müsste ich ja auch ständig das USB-Kabel mit mir rumschleppen. Glücklicherweise haben die Erfinder von Bluetooth schon vor vielen Jahren daran gedacht, dass man Handies ja auch als drahtlose Modem verwenden könnte.
Der Standard ist bereits ca. 10 Jahre alt, inzwischen sollte es doch auch für Linux kein Problem sein, oder? Denkste. Zumindest, was KDE 4.4 angeht. Das "kbluetooth"-Applet hilft zwar beim Austausch von Dateien und möglicherweise ist es auch für Eingabegeräte geeignet, aber das Pairing zum Einsatz der DUN-Schnittstelle ist damit offenbar nicht möglich.
Das heißt also: wie seit zig Jahren mit Kommandozeilentools rumfrickeln. Oder das GUI-Programm blueman installieren, welches sich in den Paketquellen aller aktuellen Distributionen befinden sollte. Anschließend den Gerätemanager 'blueman-manager' starten, der sich auch gleich als Applet ('blueman-applet') ins Tray einträgt.
Bluetooth am Handy aktivieren bzw. sichtbar schalten und anschließend auf die Lupensymbol (Adapter > Suche) klicken. Das Gerät auswählen und über das "Plus"-Symbol (oder Rechtsklick) hinzufügen. Optional anschließend durch das Stern-Symbol (oder Rechtsklick) "vertrauen". Nun per Rechtsklick oder über das "Gerät"-Menü den Punkt "Serielle Anschlüsse > Einwahl-Dienst" auswählen. Das Handy wird nun nach einer Pin fragen, hier eine beliebige Zahlenkombination eingeben. Danach wird der Bluetooth-Manager nach eben dieser Zahl fragen. Nun noch am Handy bestätigen, dass der PC sich verbinden darf und fertig. Wer mag, kann die Geräte über den entsprechenden Menüpunkt auch dauerhaft koppeln.
Damit ist die Arbeit für Blueman erstmal beendet, nun ist endlich wieder KDE an der Reihe. Das Symbol des KNetworkManagers rechts anklicken und auf "Verbindungen bearbeiten" gehen. Hier das Tab "Mobiles Breitband" öffnen und den Button "hinzufügen" anklicken. In dem Dialog, der sich nun geöffnet haben sollte, wahlweise "Irgendein Gerät" oder "Installiertes GSM-Gerät" auswählen und dann den Anweisungen folgen. KDE kennt bereits eine Vielzahl von Providern, darunter auch deutsche. Im Idealfall muss man also nur ein paar mal auf "Weiter" klicken und gar keine eigenen Daten eingeben.
Wenn alles geklappt hat, dann sollte der KNetworkManager nun bei einem Klick mit der linken Maustaste den Punkt "Mobiles Breitband" und darunter die eingerichtete Verbindung anzeigen. Sobald man diese anklickt, ist man online (jedenfalls theoretisch).
Wie gesagt, 2010 und immer noch so eine lange Anleitung erforderlich. Gut, dass das Pairing mit Headsets oder dem Bordcomputer im Auto nicht so kompliziert ist.
Achja, falls in Blueman beim Aufruf der "Einwahl-Schnittstelle" ein Fehler erscheint, dass das Gerät bereits verwendet wird, dann hilft es, den Eintrag zu löschen und das Telefon anschließend erneut hinzuzufügen.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Vor einem Jahr erschien im Linux Magazin ein Artikel, der die Anti-Spammechanismen von OpenBSD beschrieb. Obwohl ich mich damals entschloss, dies auszuprobieren, dauerte es bis zum vorgangenen Wochenende, dass ich endlich mal Zeit und Muse fand mich damit zu beschäftigen.
Bei der Installation von OpenBSD 4.6 in einer KVM mussten ein paar Klippen umschifft werden, sonst lief es aber ziemlich problemlos.
Daneben durfte ich mich noch durch duzende HowTos und Tutorials für OpenBSD und iptables (zur Anbindung an die Außenwelt) wühlen. Aber das Ergebnis hat sich gelohnt: Trotz recht großzügiger Whitelists ist alleine durch das Greylisting / Greytrapping die Zahl der Spammails am heutigen Tag von normal ca. 100 bis 150 alleine auf meiner für Mailinglisten bestimmten Adresse auf 1(!) gesunken. Und die Eine hat Spamassassin mehr als eindeutig als solche erkannt.
Die OpenBSD-VM arbeitet dabei als Gateway zum normalen Linux-Postfix, der nun quasi arbeitslos geworden ist und nichts anderes zu tun hat als die paar noch eingehenden Mails auf die Postfächer zu verteilen. Konsequenterweise könnte zwar auch OpenBSD die Mailboxen verwalten, aber vorher müsste ich mein Usermanagement mal auf OpenLDAP oder sowas bringen - das hat noch ein weiteres Jahr Zeit :p
Die nächsten Tage behalte ich noch die Logs und spamdb im Auge, außerdem zögere ich noch, die wichtigen Domains ebenfalls durch das Gateway zu jagen. Aber ich bin guter Dinge...
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
XStream is a nice Java library for serializing and deserializing objects. One of it's advantages is that it does not require the deserialized class to have a default constructor. But sometimes this will be a problem. A simple real-life example:
publicclassPerson{publictransientfinalPropertyChangeSupport pcs =newPropertyChangeSupport(this);privateString name ="";publicStringgetName(){return name;}publicvoidsetPerson(Name name){
pcs.firePropertyChange("name",this.name,this.name = name);}}
The PropertyChangeSupport object should be marked transient, otherwise serializing would include the whole object, including its listeners. But sadly, he following code won't work:
XStream xstream =newXStream();Person p =newPerson();
p.setName("Roland");String serialized = xstream.toXML(p);// ...
p = xstream.fromXML(serialized);System.out.println(p.getName());// prints "Roland"
p.setName("Cybso");// Throws NullPointerException in Person.setName(Name)
The call to p.setName("Cybso") throws a NullPointerException because pcs has not been initialized.
There are two standard ways to work around this problem. The first is to initialize XStream using a PureJavaReflectionProvider-Instance:
This would force XStream create new objects using Class.newInstance() - and prevents you from (de)serializing classes without default constructor. The other way is to implement a method called readResolve() which will be called after the object has been created:
This means to abandon the using of final transient fields and in this special case it enforces the implementation of a getPCS() or delegation methods. So let me suggest another solution: Create a custom converter that feels responsible for all classes having a default constructor. This reduces the final transient problem to classes without a default constructor.
publicstaticclassDefaultConstructorConverterextendsReflectionConverter{publicDefaultConstructorConverter(Mapper mapper,ReflectionProvider reflectionProvider){super(mapper, reflectionProvider);}@OverridepublicbooleancanConvert(Class clazz){for(Constructor c : clazz.getConstructors()){if(c.getParameterTypes().length ==0){returntrue;}}returnfalse;}@OverrideprotectedObjectinstantiateNewInstance(HierarchicalStreamReader reader,UnmarshallingContext context){try{Class clazz =Class.forName(reader.getNodeName());return clazz.newInstance();}catch(Exception e){thrownewConversionException("Could not create instance of class "+ reader.getNodeName(), e);}}}
Using this converter the original code will work:
XStream xstream =newXStream();
xstream.registerConverter(newDefaultConstructorConverter(xstream.getMapper(), xstream.getReflectionProvider()));Person p =newPerson();
p.setName("Roland");String serialized = xstream.toXML(p);//...
p = xstream.fromXML(serialized);System.out.println(p.getName());// prints "Roland"
p.setName("Cybso");// No exception thrown!System.out.println(p.getName());// prints "Cybso"
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Since my laptop is under repair I've tried to boot its operating system (Fedora 13) from a Mac Mini. I've bought a cheap external USB-Case for 2,5"-SATA-Drives from LogiLink, removed the drive from my Acer Aspire 1810T (beware of the glued foil and cable!), put it into the case and attached both USB cables to the laptop. And voilà, it works! Linux starts without any problems, as if the drive had never been anywhere else but in an external USB connector. So I've hopefully attached it to the Mac Mini. And this is the story how Apple stoles me a whole day of my life.
Even while I would like to tell you the whole story I think it would be a very boring article. So I'll just tell you what you have to do if you want to boot Linux from an external USB device.
First part, prepare the Mac. In OSX download and install rEFIt, an EFI boot menu. Take care that you customize the installation type during setup (german: "Installationstyp > Anpassen", I don't know how these steps are labeled in english) and select "File System Drivers" to get access to ext2, ext3 and ReiserFS partitions. After the second reboot you should see a boot menu with entries for OS-X, Windows (if installed) and, if your USB-Drive is already connected, an entry to boot Linux from it. If today is your lucky day this will work and you could stop reading now. But supposably something like this happens:
rEFIt's FAQ provides no real solution for this. It looks like Apple just don't want you to boot a native (MBR) bootloader from USB, as booting the same loader from the internal harddisk or from a bootable cdrom seems to work without any problems. So, let's modify the linux system to make it will be bootable by rEFIt by installing an EFI-enabled version of Grub2.
Boot the linux drive from another system. If you don't have one you can use a rescue system like grml, it will be listed in the rEFIt loader - and even bootable (wtf?). I recommend to take the latest grml64-medium, but ensure that you are downloading the same architecture as the linux system on the usb drive. Mount your root partition, chdir into its directory and execute mount -o bind /dev dev; mount -t proc none proc; chroot . bin/bash. Then mount other required devices like /boot or /home.
After you've booted (or chroot'ed) into your system you have to install grub2 with EFI support. Most likely your distribution's package is compiled without it, so download the current release from ftp://alpha.gnu.org/gnu/grub/ (1.98 at the time of writing), untar and compile it. You can do this as a normal user. Please don't run make install if you don't know for sure what you are doing.
$ wget ftp://alpha.gnu.org/gnu/grub/grub-1.98.tar.gz
$ tar xvzf grub-1.98.tar.gz
$ cd grub-1.98
$ ./configure --with-platform=efi --target=x86_64
$ make
$ ./grub-mkimage -d.-o grub.efi normal sh chain boot configfile \rebootcat lspci ls datetime loadenv search help efi_uga fixvideo \
font minicmd fat ext2 linux part_msdos part_gpt hfsplus appleldr
$ sudomkdir-p /boot/EFI/grub2
$ sudocp grub.efi *.mod *.lst /boot/EFI/grub2
This example supposes that the /boot directory is on it's own partition. If it isn't please use /EFI/grub2 instead of /boot/EFI/grub2. And if you want this to work don't name it anything else than EFI, not "efi" nor "Efi", since rEFIt is scanning for this directory.
A short note to the ./grub-mkimage-command: The grub.efi file should contain all modules that have to be avaible in the very first step. In most cases "help", "search", "minicmd", etc can be loaded at runtime using "insmod". But if something goes wrong you will be happy to have these modules in the core image. If you don't want to put grub on an OS-X device it should be safe to remove part_gpt hfsplus appleldr from the command line, but I haven't tried.
Now you have to create the configuration file at /boot/EFI/grub2/grub.cfg. If you're already using grub2 you can copy or symlink your existing config. Here's an example that should be bootable on any system. Of course you have to change the filenames of "vmlinuz" and "initramfs" to the ones on your system. If /boot isn't on it's own partition prepend /boot to the paths. Replace BOOT_PARTITION_UUID and ROOT_PARTITION_UUID with the values valid for your system. ls -l /dev/disk/by-uuid/ shows the current mappings. Note that these values will change if you reformat these partitions.
set default="0"
set timeout=5
set root='(hd1,1)'
search --no-floppy --fs-uuid --set BOOT_PARTITION_UUID
menuentry "GNU/Linux" --class gnu-linux --class gnu --class os {
set gfxpayload=keep
set root='(hd1,1)'
search --no-floppy --fs-uuid --set BOOT_PARTITION_UUID
echo Loading Linux ...
linux /vmlinuz-2.6.34.6-54.fc13.x86_64 root=UUID=ROOT_PARTITION_UUID ro quiet rhgb
echo Loading initial ramdisk ...
initrd /initramfs-2.6.34.6-54.fc13.x86_64.img
}
If you want to use the same settings for EFI and PC version of grub2 (the one shipped with your distribution) you can create a symlink: cd /boot/grub2 && symlink -s ../EFI/grub2/grub.cfg or vice versa.
Finally, I had to do some driver modifications. Put the following line into /etc/modprobe.d/macmini.conf for audio support:
options snd-hda-intel model=mb31
And replace the nouveau driver by the proprietary one. On Fedora 13 this is done by the following commands:
You can append rdblacklist=nouveau to the kernel's command line, but ensure that X isn't started as it might try to replace the VESA driver with nouveau.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Wer im Internet nach einer USB- Relais karte sucht (damit kann man Schalter per USB auslösen, beispielsweise um einen Drucker vom Computer aus vom Netz zu trennen, irgendwelche Lichter zu schalten oder vielleicht auch Kaffee zu kochen), der wird früher oder später auf das entsprechende Selbstbau-Projekt von Ulrich Radig stoßen. Sie bietet sechs einzelnd schaltbare Relais (bis 8A/250 VAC) und vier per Optokoppler getrennte Eingänge bis max. 48V an. Die Platine kann man in seinem Shop bestellen, den Rest gibt's bei Reichelt oder Conrad. Alles in allem muss man mit etwa 50 EUR rechnen, wobei die teuersten Teile die Platine, die Relais, das Netzteil und der Versand sind. Und so sieht's dann aus:
USB-Relaiskarte von Ulrich Radig
Im Gegensatz zum Original habe ich ein paar kleine Änderungen vorgenommen. Die Relais stecken auf Sockeln von Typ "FIN 95.15.2", damit man sie zum Experimentieren am Treiber abnehmen kann und beim Löten nicht beschädigt. Da der eigentlich vorgesehene Relaistyp bei Reichelt nicht verfügbar war, habe ich den Typ "FIN 41.61.9 12V" verwendet. Der unterschied ist im wesentlichen nur, dass das Original zwei parallele Schalter besitzt und dieser hier nur einen. Das ist aber nicht schlimm, da der zweite Schalter vom Platinenlayout nicht verwendet wird. Des Weiteren habe ich gelbe statt rote LEDs für die Eingänge verwendet und dem Darlington-Array (ULN 2003A) einen Sockel spendiert, da es beim ersten mal ein wenig empfindlich auf die Hitze des Lötkolben reagierte ;-). Potentiellen Nachbauern würde ich nahelegen, die Power-LED ebenfalls durch eine andersfarbige zu ersetzen, um sie deutlicher von der Relais-Kontroll-LED unterscheiden zu können. Dazu muss der entsprechende Widerstand angepasst werden.
Update:
Neben dem ULN 2003A hat sich auch die Feinsicherung als problematisch herausgestellt. Jeder noch so kleine Kurzschluss beim Basteln zerstört diese. Ist ja auch ihre Aufgabe, aber sie jedesmal auszulöten ist ganz schön nervig. Als Lösung bietet es sich entweder an während der Entwicklung die Sicherung zu überbrücken (dann aber bitte nur mit einer 9V-Batterie und nicht mit einem Netzteil als Stromquelle arbeiten), oder die Anschlüsse durch Steckkontakte zu ersetzen und darüber mit einer herkömmlichen gefassten Feinsicherung zu verbinden. Letzteres funktioniert hier ziemlich gut :-)
Die rudimentäre Firmware habe ich ein wenig modifiziert, die Details sind in Ulrich's Forum beschrieben. Mit dieser modifizierten Firmware erfolgt die Verwendung wie folgt:
Die Relaiskarte identifiziert sich bei Linux als serielle USB-Schnittstelle /dev/ttyACM0. Unter Windows wird es wohl COM0 oder etwas in der Art sein. Die Steuerung erfolgt über einzelne Bytes, die an diese Schnittstelle gesendet bzw. gelesen werden. Ich habe dazu die pySerial-Bibliothek verwendet.
Zunächst muss das Gerät initialisiert werden, in dem 16 mal hintereinander das Byte 0xC0 (Binär: 11000000) gesendet wird. Bis dahin akzeptiert es keine Eingaben, um Problemen mit der automatischen Hardwareerkennung vorzubeugen. Anschließend ist die Bedeutung der einzelnen gesendeten Bits die folgende:
1 1 1 1 1 1 1 1
8 7 6 5 4 3 2 1
Die Bits 1 bis 6 steuern die einzelnen Relais. Eine 1 an der entsprechenden Position aktiviert das Relais, eine 0 deaktiviert es. Das 7. Bit ändert dies in einen "Toggle"-Befehl um, wenn es aktiviert ist. Der Befehl 01000000 macht also gar nichts, der Befehl 01111111 ändert den Zustand aller Relais. Das 8. Bit fordert von der Karte eine Statusmeldung an.
An den PC gesendet werden einzelne Bytes, deren Bits entwedern den Status der Eingänge (8. Bit = 0) oder der Relais (8. Bit = 1) angeben. Diese Ausgabe erfolgt entweder automatisch, wenn sich der Zustand eines Eingangs ändert, oder explizit wenn eine Statusanfrage angefordert wurde (8. Bit = 1 im gesendeten Byte).
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Zutaten:
20 Vishay TSAL6400 Infrarot-LEDs (940nm)
4 Widerstände 10 Ohm
Steifenrasterplatine, in zwei Stücke mit je 1cm Breite geschnitten (quer zum Raster)
2m Kabelkanal
Netzteil 7,5V bis 9V, ca. 500mA
Ein paar Kabel und Drahtbrücken
Alles in einen Topf geben, gut mit heißem Lötzinn verrühren, und voilà:
Details: Es werden jeweils 5 IR-LEDs in Serie an einen 10-Ohm-Widerstand geschaltet, also zwei dieser Arrays auf jeder Seite. Eine Betriebsspannung von 7,5V bedeutet dann pro LED ca. 1,3V und damit die normale Forward Voltage der TSAL6400. Legt man statt dessen 9V an, so kommt man auf ca. 1,6V, was der "Maximum Forward Voltage" dieser LED entspricht. So kann man bei Bedarf noch etwas mehr "Helligkeit" herausholen. Falls dies immer noch nicht reicht kann man weitere Arrays hinzufügen. Aber bitte auf den Strombedarf achten, im Zweifel das Netzteil lieber etwas höher dimensionieren.
Nachtrag: Die Reichweite beträgt schon bei 7,5V locker 25 Meter... :-)
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Ein kleiner Memo-Eintrag, in erster Linie für mich selbst. Logisch, dass dies in Deutschland so nur mit selbst erstellten DVDs oder mit gekauften DVDs ohne Kopierschutz gemacht werden darf (und die archivierte Kopie natürlich auch nicht weitergegeben werden darf, aber das ist wohl selbstverständlich)...
Die Zuordnung der Indexes zu den Sprachen kann zum Beispiel mit mplayer geprüft werden. Allerdings verwendet mplayer die dezimale Schreibweise: 0x80 = 128, 0x81 = 129, usw. Mit dem Wissen um die Zuordnung kann die Umwandlung gestartet werden. Hier im Beispiel werden die zwei Tonspuren 0x80 (eng) und 0x81 (ger) getauscht. Weitere können am Ende des Befehls angefügt werden. Soll die Reihenfolge der Spuren nicht geändert werden, dann sind die -map-Parameter optional.
ffmpeg -i dvdtitel-N.vob -threads0\-map0-map0.2-map0.1\-vcodec libx264 -vpre normal -level51-crf23\-acodec copy -alang ger \
dvdtitel-N.mkv \-acodec copy -alang eng -newaudio
Bei Filmen im Interlaced-Format sollte man hinter "-vpre normal" außerdem noch " -flags +ilme+ildct" einfügen. Ob es sich um Interlacing-Material handelt, kann man zum Beispiel mit transcode schnell herausfinden:
Den Untertitel mit der ID 1 und der Sprache deutsch im vobsub-Format in die Dateien "dvdtitel-N.idx" und "dvdtitel-N.sub" speichern:
$ mencoder dvdnav://N -nocache-nosound-ovc frameno -o /dev/null \-slang de -sid1-vobsuboutindex0-vobsuboutid de -vobsubout dvdtitel-N
Den vobsub-Untertitel mithilfe von Texterkennung in das SRT-Format umwandeln:
Avidemux starten
Tools >OCR (VobSub -> srt)...
IDX-Datei auswählen, die dazugehörige .SUB wird automatisch gefunden
Ausgabe SRT-Datei
Falls bereits vorhanden kann ein bestehender Zeichensatz für die Texterkennung ("Glyphs") ausgewählt werden.
Dem OCR-Programm bei der Erkennung der Buchstaben helfen.
Avidemux scheint Probleme mit Umlauten zu haben. Stößt das Programm auf ein "ö,ä,ü,ß", so empfehlt es sich, statt dessen eben "oe,ae,ue,ss" einzugeben.
Gegebenenfalls den so erstellen Zeichensatz für eine zukünftige Verwendung speichern.
Die erzeugte SRT-Datei falls nötig ins UTF8-Format umwandeln:
$ recode latin1..utf8 dvdtitel-N.srt
Falls Avidemux die Zeichen nicht erkennt, fehlt in der .IDX-Datei vermutlich die Farbpalette. In diesem Fall die Datei einfach in einem Texteditor öffnen und die folgende Zeile einfügen (ohne den Zeilenumbruch):
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Today I wanted to embed a SWT component (Browser) into an existing JFrame. This is the way it works:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Flexbackup is a very nice and flexible tool to create full, incremental and differential backups. But if you store your backups in an untrusted environment you might want do encrypt the created archive files. Flexbackup cannot handle it by default, but there is a very simple way to get the desired results by replacing the default gzip binary with a wrapper file.
In this example I'm using mcrypt with symmetric block cipher DES. Replace it with gnupg if you want asymmetric encryption, but remember: if someone gains root access to read the key he doesn't need to decrypt your backup files - he already has access to the originals.
Create a file named /usr/local/bin/gzip_crypt:
#!/bin/shgzip$*| mcrypt -a des --keyfile"$HOME/mcrypt.key"
Store an encryption key in $HOME/mcrypt.key, e.g. /root/mcrypt.key. I would suggest to use at least 16 random characters for it, see the manpage of mcrypt for details. Ensure that the key isn't readable for someone else:
$ chmod 0600 "$HOME/mcrypt.key"
Don't - DON'T, DON'T, DON'T - enter the key as command line argument to mcrypt as it would be visible in the process list for every user while mcrypt is running!
Now edit your flexbackup.conf and change the following options to these values:
$compress='gzip';$comp_log='bzip2';# or just 'false', gzip_crypt isn't able to handle this$path{'gzip'}='/usr/local/bin/gzip_crypt';
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
If you have a table "tablename" with a (non-PK) column "number" and you want to enumerate all existing rows starting with 1000 you can use the following SQL statement:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Schonmal versucht, nen Mac Mini in einen 19"-Schrank zu stellen? So geht's:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Today I wrote a patch to Flexbackup 1.2.1 which allows you to define exclude expressions on a per-directory-base (like svn:ignore, cvs_ignore or tar's --exclude-from). Apply this patch and add the following line to your flexbackup.conf:
$exclude_expr_filename='.flexbackup_exclude';
This activates an additional routine in the file_list_cmd() method. As soon as the 'find' command has enough parameters to iterate through all directory it is used to retrieve a list of '.flexbackup_exclude' files. Each file is read line by line and a regular expression will build and appended to the directory's name, e.g:
All files matching this expression will be ignored. This is done by piping find's output through xargs and perl:
$ find.[conditions...]-print0|xargs-0 perl -e'foreach (@ARGV) { print "$_" if ! /dummy\/((.*\.tmp$)|(a_very_big_file\.iso))/ and 1'
If more than one .flexbackup_exclude-file is found more conditions are prepended to the 'and 1'-dummy-condition. Because every condition is tested (and ignored if compilation failed) it should not be possible to break the backup using these files.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
2014-02-26:
I've updated this HowTo for current versions of udev and kvm.
libvirt/kvm allows you to expose any usb device attached to your physical maschine to the guests. Just edit the domain's XML definition and add the following <hostdev> to the <devices> area:
<domaintype='kvm'>
...
<devices>
....
<!-- The XHCI driver includes support for USB 2 devices, which makes
it easier as with UHCI/EHCI to add an USB controller. Remove
existing USB controllers from definition. --><controllertype='usb'index='0'model='nec-xhci'/><hostdevmode='subsystem'type='usb'managed='yes'><sourcestartupPolicy='optional'><vendorid='0x03f0'/><productid='0x4217'/></source></hostdev></devices></domain>
Vendor id and product id can be determined with lsusb:
$ lsusb
...
Bus 002 Device 018: ID 03f0:4217 Hewlett-Packard EWS CM1015
...
Sadly this only works if the device is attached and enabled when the VM is started. The connection will be lost whenever the device is disabled or removed. But you can re-attach it at runtime. Just put the hostdev-definition into it's own file:
Previously, this example depended on sysFs{idVendor} and sysFs{idProduct} in order to match the correct USB device. These do not exist any longer, so I replaced them with environment variables containing the same information. To find out what attributes are available for matching, run udev monitor --property --udev while attaching and detaching the device.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Viele haben vernünftigerweise gar keinen Facebook-Account, aber die, die sich doch angemeldet haben, werden nach dem Login für Facebook furchtbar transparent - dank des "Gefällt mir" / "Like"-Buttons. Dieser stammt im normalfall direkt vom Facebook-Server und beinhaltet auch die URL der aufgerufenen Seite:
Dieser Dienst, der viele wohl so gut kennt wie niemand sonst, erhält auf diese Weise also auch noch ein fast flächendeckendes Bewegungsprofil im normalen Netz - Nachtrag: selbst wenn man den Button nicht anklickt!. Vorratsdatenspeicherung ist nichts dagegen :-). Wer kein Interesse an Facebook hat, kann das einfach durch einen Eintrag in die hosts-Datei des Systems blockieren:
127.0.0.101 facebook.com www.facebook.com
Leider wird dadurch Facebook generell unbenutzbar. Wer dort also doch in und wieder mal reinschauen möchte, der kommt um eine Alternative nicht herum. Opera bietet hierzu von Haus aus die Datei urlfilter.ini an. Den genauen Pfad der Datei bekommt man durch den Aufruf der Seite "opera:config#urlfilter" (Wordpress macht den Link leider kaputt) heraus, auf Unix-Systemen ist es $HOME/.opera/urlfilter.ini. Dort kann man sehr fein gesteuert die erlaubten und verbotenen Seiten festlegen:
Opera Preferences version 2.1
; Do not edit this file while Opera is running; This file is stored in UTF-8 encoding[prefs]prioritize excludelist=1[include]
*
[exclude]
*://*.facebook.com/plugins/like.php*
*://*.facebook.com/plugins/likebox.php*
*://*.facebook.com/plugins/*
Die Änderungen werden nach einem Neustart von Opera wirksam, der Gefällt-Mir-Button sollte dann von allen Seiten verschwunden sein. Wenn man auch gleich den ein oder anderen Werbedienst blockieren möchte, kombiniert man dies einfach mit bestehenden Filterlisten, etwa von urlfilter.de.
Nachtrag: Da es offenbar auch noch weitere Facebook-Anwendungen gibt, die in die eigene Seite eingebettet werden können (z.B. Kommentare) habe ich eine dritte exclude-Zeile hinzugefügt, die alle "plugins" blockiert. Der normale Facebook-Betrieb scheint diese nicht zu nutzen.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Wie bekannt und auch hier im Blog schon beschrieben funktioniert der Broadcom-WLAN-Chip im Lenvo Ideapad U160 unter Linux nicht. Die Karte wird wahlweise durch Softblock oder die Hardblock behindert.
Durch einen Bugreport-Eintrag von Ross Patterson habe ich die Lösung gefunden, auch wenn es bei mir eine andere Reihenfolge brauchte als bei ihm.
Das Problem ist wohl der acer_wmi-Treiber, der die Steuerung der WLAN-Karte stört, aber offenbar irgendetwas initialisiert, wodurch es nach dem Laden und Entladen des Moduls funktioniert.
Da ich gerade nicht viel Zeit habe hier die Kurzfassung für Fedora 15:
Die Pakete "broadcom-wl" und "kmod-wl" installieren.
Eine neue Datei unter /etc/modprobe.d/acer_wmi mit folgendem Inhalt anlegen:
Seit dieser Änderung funktioniert es für mich zuverlässig. Es muss tatsächlich zweimal /sbin/rfkill unblock all drin stehen, mit nur einem Aufruf klappt es nicht.
Wer seinen WLAN-Chip gegen eine Intel-Karte ausgetauscht hat, der kriegt sie mit der selben Änderung zum Laufen, ersetzt jedoch "wl" durch "iwlagn".
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
When doing MVC programming in Java, there is a problem that most people don't know about. I've ignored it myself much too long. The problem is that when you bind a model class to an UI component you will get a giant memory leak.
What happens?
Well, imagine a model class supporting listening for property changes. A simple example might look like this (I extend from PropertyChangeSupport here so that I don't have to delegate all the methods, normally you wouldn't do so, of course):
publicclassModelextendsPropertyChangeSupport{privateString name;publicModel(String name){super(newObject());// Only an example! Don't do this in RL!this.name = name;}publicStringgetName(){return name;}publicvoidsetName(String name){firePropertyChange("name",this.name,this.name = name);}}
Next, imagine a view for this model class. It has an input field that is binded in both direction with the model (very simplified example here, I normally don't code this way ;-)):
From now on we have a memory leak, because the JPanel, the JLabel and the JTextField (and all other referenced) objects will never be removed by the garbage collector as long as the model exists (which might be until the applications end of life). The reason is that the anonymous inner PropertyChangeListener instance has (and must have!) an implicit reference to the JPanel. And even if you replace it by a static class it does have to know the textfield which is a child object of the panel and has a reference back to it. So even if nobody else references the panel the garbage collector sees:
Model => PropertyChangeListener => JPanel
There is a little known class called WeakReference (and his brother WeakHashMap). It contains an object, but the object could still be removed by the garbage collector as long as there is no other (non-weak) reference to it.
A naive idea is to just encapsulate the PropertyChangeListener within a WeakReference object:
publicclassWeakListenerimplementsPropertyChangeListener{privatefinalWeakReference<PropertyChangeListener> listener;publicWeakListener(PropertyChangeListener listener){this.listener =newWeakReference<PropertyChangeListener>(listener);}publicvoidpropertyChange(PropertyChangeEvent e){PropertyChangeListener l =this.listener.get();if(l !=null){
l.propertyChange(e);}}}
Code in ModelView constructor:
// Bind model => textfield (with little memory leak)
model.addPropertyChangeListener("name",newWeakListener(newPropertyChangeListener(){publicvoidpropertyChange(PropertyChangeEvent e){
textfield.setText(model.getName());}}));
The idea is that you still have this simple and small WeakListener object within your model's listener list, but the really big part (the original listener, the panel, label, textfield, etc) could be free'd. Sadly, this will not work, because as soon as you gave the anonymous PropertyChangeListener to WeakListener's constructor nobody else does reference to it, so the garbage collector will remove the object immediately.
The trick is to create a single reference to it which belongs the parent object:
publicclassModelViewextendsJPanel{privatePropertyChangeListener modelTextfieldListener;publicModelView(finalModel model){super(newBorderLayout());add(newJLabel("Name: "),BorderLayout.WEST);finalJTextField textfield =newJTextField(model.getName());add(textfield,BorderLayout.CENTER);// Bind textfield => model (harmless)
textfield.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvent e){
model.setName(textfield.getText());}});// Bind model => textfield (with little memory leak)
model.addPropertyChangeListener("name",newWeakListener(modelTextfieldListener =newPropertyChangeListener(){publicvoidpropertyChange(PropertyChangeEvent e){
textfield.setText(model.getName());}}));}}
That's it. To make this easier I've created a little support class WeakListenerSupport that's very helpful if you have to deal with multiple input-property-bindings. Also it tries to remove ("unlink") itself from the model if the listener doesn't exist any longer. It even allows to unlink all weak listeners from a single object.
With this class the above example would look like:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Soeben habe ich die neuen 2TB-Festplatten in den Media-PC eingebaut und mich dazu entschieden, dieses mal dem neuen Linux-Dateisystem btrfs eine Chance zu geben. Im Gegensatz zum klassischen ext beherscht dieses nämlich von Haus aus RAID-Funktionalitäten (Level 0, 1 und 10) sowie Snapshots. Das RAID im Level 1 schützt vor physikalischen Fehlern, die Snapshots - sofern man sie regelmäßig anlegt - vor logischen, wie einem versehentlichen 'rm -rf'.
Die Frage ist, wie stabil btrfs inzwischen geworden ist. Da es beinahe das Standardsystem unter Fedora 16 geworden wäre ist meine persönliche Einschätzung: Stabil genug für mich. Der Grund, warum FC16 doch noch ext4 verwendet, ist das fehlende bzw. nicht rechtzeitig fertig gewordene fsck. Mit den git-Quellen jedoch kein Problem, dort findet sich inzwischen ein btrfsck. Sowieso würde ich für den Einsatz einen aktuellen Kernel (3.x) und die aktuellen Tools aus dem Git-Repository verwenden, siehe https://btrfs.wiki.kernel.org/.
Zuerst müssen die Partitionen im RAID-1-Modus formatiert werden:
Im Gegensatz zu einem klassischen mkfs gibt man hier also zwei (bzw. mehr) Devices an. Mit den Parametern -d (--data) und -m (--metadata) wird der jeweilige Speichermodus festgelegt. Standardmäßig spiegelt btrfs bei mehr als einer Partition die Metadaten (raid1) und teilt die Daten auf beide Devices auf (raid0).
Damit btrfs alle zusammengehörigen Partitionen automatisch finden kann, erhalten sie die selbe UUID und unterschiedliche Sub-UUIDs:
Dementsprechend reicht es beim Mounten auch aus, entweder eines der beiden Devices oder die UUID anzugeben. Die folgenden drei Befehle sind also identisch zueinander:
$ mount /dev/sdd1 /mnt
$ mount /dev/sde1 /mnt
$ mountUUID=243efbc4-5f72-4352-9160-d693b3ed41b5 /mnt
Der Befehl btrfs filesystem show zeigt alle erkannten Dateisysteme an:
$ sudo btrfs filesystem show
Label: 'mediafiles' uuid: 243efbc4-5f72-4352-9160-d693b3ed41b5
Total devices 2 FS bytes used 809.82GB
devid 1 size 1.82TB used 817.03GB path /dev/sdd1
devid 2 size 1.82TB used 817.01GB path /dev/sde1
Btrfs v0.19-102-g2482539
Es gibt jedoch eine kleine Stolperfalle. Soll das RAID-1-btrfs beim Booten automatisch eingehängt werden, so *müssen* alle Devices in der /etc/fstab eingetragen werden. Ansonsten meckert das System, da es nicht alle dazugehörigen Devices selbst finden kann, selbst wenn die UUID verwendet wird:
Gefährlich ist dies vor allem bei Headless-Systemen, da im laufenden Betrieb die automatische Erkennung der Devices durchaus funktioniert und ein Eintrag ohne die device=-Optionen daher beim Testen durchaus funktionieren würde.
Nicht ganz einfach ist übrigens die Größe bzw. der freie Speicher des RAID-1-Dateisystems zu ermitteln:
df zählt hier also einfach den gesamten und belegten Speicher aller Einzelpartitionen zusammen. Der Grund hierfür liegt, soweit ich das im Wiki verstanden habe, in einem Berechtigungsproblem: Um das Dateisystem als RAID-1 zu erkennen und die Größe damit korrekt anzugeben müsste df direkt darauf zugreifen, was ihm aber zumindest als normaler User nicht erlaubt ist. btrfs bringt daher sein eigenes df mit:
Das Tool btrfs wird auch verwendet, um weitere Devices zum Raid hinzuzufügen, zu entfernen, Snapshots anzulegen oder das FS zu defragmentieren. Hiermit habe ich bisher aber noch nicht experimentiert, ggf. wird's einen Nachtrag geben. Erstmal werde ich nun das Verhalten im MythTV-Betrieb beobachten und vor allem auf die - subjektive - Performance im Vergleich zu ext4 achten.
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
JTextPane and his ancestors JEditorPane and JTextComponent won't respect the color defined with setBackground(Color) since they display a "styled document" and expect the background color to be defined in the content. You'll always see a white background.
To change the background color (without modifying the content) you have to define attributes for the document:
JTextPane textPane =newJTextPane();
textPane.setContentType("text/html");// or any other styled content type
textPane.setText("White text on a red background");
textPane.setForeground(Color.white);// Works as expected
textPane.setBackground(Color.red);// Obsolete, no affect// Define a default background color attributeColor backgroundColor =Color.red;SimpleAttributeSet background =newSimpleAttributeSet();StyleConstants.setBackground(background, backgroundColor);
textPane.getStyledDocument().setParagraphAttributes(0,
textPane.getDocument().getLength(), background,false);// And remove default (white) margin
textPane.setBorder(BorderFactory.createEmptyBorder());// Alternative: Leave a 2px border but draw it in the same color
textPane.setBorder(BorderFactory.createLineBorder(backgroundColor,2));
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Wichtiger Hinweis: Dieses "HowTo" ist in erster Linie als Erinnerung für mich selbst gedacht. Wenn ich jemand anderem damit ebenfalls helfen kann freue ich mich, aber aus zeitlichen Gründen kann ich im Moment nur sehr begrenzt Support geben.
Ich betreibe den yaVDR als Client/Server-Anwendung. Im Server befinden sich zwei DVB-S(2)-Karten, der Client im Wohnzimmer ist über das LAN angebunden.
Der Frontend des Client ist der ganz normale vdr-sxfe (libxineoutput), bei Bedarf kann XBMC über das Menü oder eine Taste gestartet werden. De Server selbst wird als Client nur selten benutzt, und wenn, dann meistens für Videos oder Aufnahmen. Aus diesem Grund kommt dort der XBMC mit PVR-Addon als Frontend zum Einsatz.
Damit der auf dem Server laufende VDR keine DVB-S-Karte für sich selbst belegt, schaltet das VDR-Plugin suspendoutput nach einer kurzen Wartezeit den VDR (als Client) ab:
Doch bei diesem Setup gibt es ein Problem, denn suspendoutput bewirkt, dass der automatische Shutdown (bzw. Standby) nach der "MinUserInactivity" des VDR bei Nichtverwendung ignoriert wird. Und selbst wenn dieser ausgelöst würde: Das laufende XBMC würde den Shutdown verhindern.
Gehen wir zuerst das einfachere Problem an. XBMC soll erst nach einem Tastendruck auf der Fernbedienung tatsächlich gestartet werden. Dies geht über das Templatesystem von yaVDR recht einfach:
$ cat> /etc/yavdr/templates_custom/etc/init/xbmc.conf/25_wait-for-remote <<EOL
xset dpms force off
(irw | read -r) || true
xset dpms force on
EOL
$ process-template /etc/init/xbmc.conf
Mit "xset" wird das Display ab- bzw. wieder eingeschaltet, und die Anweisung mit "irw | read -r" horcht auf die Fernbedienung und beendet sich nach der ersten Zeile (= dem ersten Tastendruck). Die Klammern und das "true" sind notwendig, damit ein Abbruch des "irw" durch ein "kill" nicht als Fehler interpretiert wird.
Dass der Shutdown überhaupt ausgelöst wird ist etwas schwieriger, wenn suspendoutput in Betrieb bleiben soll. Im Quelltext des Plugins gibt es sogar einen entsprechenden Codeschnipsel, der jedoch auskommentiert ist und so direkt erstmal nicht funktioniert.
Leider habe ich den Entwickler des Plugins per E-Mail nicht erreichen können, also habe ich mich selbst an die Arbeit gemacht und einen Patch geschrieben, der den Code aktiviert und einen entsprechenden Eintrag im Konfigurationsmenü ergänzt.
Mit diesen Tricks sollte sich der Server nun nach der eingestellten Wartezeit in den Standby-Modus begeben und rechtzeitig zu einer Aufnahme wieder aufwachen, natürlich vorausgesetzt, dass gerade keine andere Aufnahme läuft.
Damit der Client den Server wieder aufweckt, modifiziert man am besten die Datei /etc/network/interfaces:
# The primary network interface
auto eth0
iface eth0 inet dhcp
post-up /usr/sbin/etherwake AA:BB:CC:DD:EE:FF
AA:BB:CC:DD:EE:FF muss durch die MAC-Adresse ("Hardware address") des Servers ersetzt werden, die man mit "ifconfig" ermitteln kann. Außerdem muss das Paket "etherwake" installiert sein. Andere Wake-On-Lan-Pakete sind natürlich auch geeignet, nur muss dann der Befehl hintre "post-up" entsprechend angepasst werden.
Ein kleines Problem gibt es immer noch: Nach einem Standby wird das Interface zwangsweise neu gestartet. Um das zu erzwingen hilft noch ein kleines Script:
$ cat> /etc/pm/sleep.d/40_etherwake << EOL
#!/bin/shcase$1in
hibernate|suspend)#Befehl vor Wechsel in Suspend;;
thaw|resume)#Befehl nach aufwachen aus Suspend
/etc/init.d/networking restart
;;esac
Nun sollte der Client den Server beim Einschalten automatisch aufwecken.
Den Shutdown testen kann man übrigens am besten, in dem man eine "screen"-Session öffnet, den Shutdown-Befehl mit einer Verzögerung von 10 Sekunden auslöst, die Screen-Session mit STRG-A, STRG-D detached und sich auslogt:
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Some tutorials suggest to use the system properties http.proxyUser and http.proxyPassword to get proxy authentication, but that won't work since - in contrast to http.proxyHost and http.proxyPort - these properties will not be processed by Java's HttpURLConnection.
Other suggest to use a custom default Authenticator. But that's dangerous because this would send your password to anybody who asks.
The following snippet contains some code that uses an Authenticator to process http.proxyUser, but ensures that these information will be sent to the host that is defined by http.proxyHost:
// Java ignores http.proxyUser. Here come's the workaround.Authenticator.setDefault(newAuthenticator(){@OverrideprotectedPasswordAuthenticationgetPasswordAuthentication(){if(getRequestorType()==RequestorType.PROXY){String prot =getRequestingProtocol().toLowerCase();String host =System.getProperty(prot +".proxyHost","");String port =System.getProperty(prot +".proxyPort","");String user =System.getProperty(prot +".proxyUser","");String password =System.getProperty(prot +".proxyPassword","");if(getRequestingHost().toLowerCase().equals(host.toLowerCase())){if(Integer.parseInt(port)==getRequestingPort()){// Seems to be OK.returnnewPasswordAuthentication(user, password.toCharArray());}}}returnnull;}});
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Apache's include directive does not accept wildcards, so something like this won't be allowed:
Include /srv/www/vhosts/*/conf/vhost.conf
You can use mod_perl to realize this. Additionally, the following example does a simple permission check to ensure that the included file has not been modified by an ordinary user:
<perl>use File::stat;foreach$file(glob '/srv/www/vhosts/*/conf/vhost.conf'){my$stat= stat($file);if($stat->uid !=0||$stat->gid !=0){
warn "$file is not owned by root:root, skipping!\n";next;}if($stat->mode &0002){
warn "$file is world-writable, skipping!\n";next;}
push @Include,$file;}</perl>
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.
Since there is no mechanism defined to log the user out of a HTTP authenticated session you have to use a workaround. Most browsers forget their login data once they received a 403 response. The problem is, that the user have to return to the normal starting page manually.
Update 2017-02-22: It seems that this technique doesn't work anymore in recent Firefox and Chrome browsers.
The following code, which can be embedded into an Apache VHost declaration, uses a cookie to send a 403 response to the browser the first time he requests "/logout", and redirects it to "/" on the second time. So the user can immediately login again if he want to.
Please note that the order of the declarations does matter! The Location-Block must be the last block which requires a user or group.
Use this howto on your own risk! I do not guarantee that it's free of errors! If you're not absolutly sure about something written here, or you don't know how to make backups of your router config and how to savely restore them: don't follow these instructions!
First of all, since there is no package for ferm available, we have to install it manually. Luckily, it's only a simple Perl script, so just fetch the ferm script file, copy it to /usr/sbin/ferm and make it executable.
Next, the required perl packages have to be installed with opkg. I've started with a basic set of Perl modules and installed the missing ones one after one, until a call to ferm didn't throw an error. These are the packages I've finally installed:
Next, place you're ferm ruleset at /etc/firewall.ferm. This is my, for the moment, but of course you can extend it as you want. This ruleset allows SSH from WAN port, so ensure that password authentication is disabled! Otherwise, remove the rule at line 42:
Now write an "include" script for OpenWRT's firewall so that it get's executed when the firewall is started or reloaded:
/etc/firewall.ferm.sh:
/usr/sbin/ferm /etc/firewall.ferm
And append the following block to /etc/config/firewall:
config include
option path '/etc/firewall.ferm.sh'
option reload '1'
And remove the include config for /etc/firewall.user. You could disable (option enabled '0') every config rule as they would be replaced by ferm nevertheless, but don't disable the zone configs! They are still required so that fw3 reloads the ruleset when the interfaces changes.
Finally, if you want to be able to edit your ferm rules via the LuCI web frontend, symlink /etc/firewall.ferm to /etc/firewall.user.
Remember: If you add new interface to your filewall zones this won't have any effect! You have to manually add them to the ferm config. I've added some variables at the top of the config that makes this easier.