<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kolios &#187; tech</title>
	<atom:link href="http://www.kolios.dk/category/tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kolios.dk</link>
	<description></description>
	<lastBuildDate>Wed, 14 Jul 2010 06:57:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>How to migrate django models with South</title>
		<link>http://www.kolios.dk/2010/02/12/how-to-migrate-django-models-with-south/</link>
		<comments>http://www.kolios.dk/2010/02/12/how-to-migrate-django-models-with-south/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 09:22:22 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://www.kolios.dk/?p=524</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/coding-48x48.png" width="48" height="48" alt="" title="Coding" /><img src="http://www.machezdanois.com/icons/django-48x48.png" width="48" height="48" alt="" title="django" /><br/>Hi django fridayers ! Today on python friday, we will discuss the model and data migration of django. Many of you are probably developing the web app in python and are absolutely amazed about how easy it to create a database schema from your django models. Just run an manage.py syncdb and &#8230;voila ! Your [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/coding-48x48.png" width="48" height="48" alt="" title="Coding" /><img src="http://www.machezdanois.com/icons/django-48x48.png" width="48" height="48" alt="" title="django" /><br/><p>Hi django fridayers !</p>
<p>Today on python friday, we will discuss the model and data migration of django.</p>
<p>Many of you are probably developing the web app in python and are absolutely amazed about how easy it to create a database schema from your django models. Just run an manage.py syncdb and &#8230;voila ! Your brand new application has all the support needed in the backend database.</p>
<p>But let&#8217;s face it, this is not really practical when it comes to modify an application that is ALREADY online and have data (registered users, stored personal information, &#8230;).</p>
<p><span id="more-524"></span></p>
<h3>The problem</h3>
<p>How can you migrate from one model to another without loosing any data ?</p>
<h3>The solution.</h3>
<p><a title="South migration tool" href="http://south.aeracode.org">South</a></p>
<p>This python package will take care of most of the trouble caused by your model modifications.<br />
With South, you can :</p>
<ul>
<li>Modify the schema of your database according to your model</li>
<li>Migrate your data to make sure that you wont lose any data across the migration</li>
</ul>
<p><!-- more --></p>
<h3>Installing South</h3>
<ul>
<li>download</li>
<li>setup.py install (as root)</li>
<li>edit your settings.py to activate &#8220;south&#8221; in the installed apps</li>
</ul>
<h3>A simple example</h3>
<p>You can now type :</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage syncdb</pre>
<p>to create the good tables in your database. South keep track of every migration in the project database.</p>
<p>Now, let&#8217;s consider that you have a the following model:</p>
<pre class="brush: python">class Customer(models.Model):
    name = models.CharField(max_length= 60)

    def __unicode__(self):
        return self.name</pre>
<p>The first thing you need to do is to initialize south so it can keep track of your<br />
modification of models:</p>
<pre class="brush: bash; gutter: false">$&gt; manage.py startmigration customer initial --initial</pre>
<p>This will create your first migration (initial). The migration will basically creates the tables in your database.<br />
Now, you can apply the migration.</p>
<pre class="brush: bash; gutter: false">$&gt; manage.py migrate</pre>
<p>Now, let&#8217;s assume that you want to change it into:</p>
<pre class="brush: python">class Customer(models.Model):
    name = models.CharField(max_length = 60)
    password = models.CharField('this is a clear text password', max_length=60)</pre>
<p>You have to prepare the migration with the following command:</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py startmigration customer add_password --auto</pre>
<p>This creates a migration file that contains your modifications. I let you try to figure out what forward and backward methods are for. Once again, when you think that your migration file is good, you can apply the changes :</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py migrate</pre>
<p>At this point, your database is totally synced with your model, so let&#8217;s create some data into it:</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py shell
&gt; from customer.models import Customer
&gt; c = Customer()
&gt; c.name="sebastien requiem"
&gt; c.password = "secret"
&gt; c.save()
&gt; Customer.objects.all()
[\]</pre>
<h3>A more complex example with DATA migration</h3>
<p>You now decide to split the field <em>name</em> into <em>firstname</em> and <em>lastname</em>. The natural way would be to delete the field name and create two fields named <em>firstname</em> and <em>lastname</em>. And this is Wrong for many reasons:</p>
<ol>
<li>South will not understand that you want to split the name into two distinct fields</li>
<li>South won&#8217;t be able to migrate your data forward AND backward if you want to roll back</li>
</ol>
<p>The good (and ONLY) way to do it is to so it in three steps:</p>
<ol>
<li>modify your model so you add <em>firstname</em> and <em>lastname</em> fields and migrate the schema</li>
<li>create a migration that migrate your DATA (while name, <em>name</em>, <em>firstname</em> and <em>lastname</em> are all accessible)</li>
<li>delete the <em>name</em> field</li>
</ol>
<p>Now, let&#8217;s assume that you want to change you previous model into the following :</p>
<pre class="brush: python">class Customer(models.Model):
    name = models.CharField(max_length = 60)
    firstname = models.CharField(max_length = 60)
    lastname = models.CharField(max_length = 60)
    password = models.CharField('this is a clear text pasword', length=60)

    def __unicode__(self):
        return self.firstname + ", " + self.lastname</pre>
<h3>Migrating the schema</h3>
<p>Nothing fancy here:</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py startmigration customer add_first_last_name --auto
$&gt; ./manage.py migrate</pre>
<h3>Migrate the data</h3>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py startmigration customer first_last_data
now edit the migration file newly created and add the following lines :</pre>
<pre class="brush: python">    def forwards(self, orm):
        for customer in orm.Customer.objects.all():
            try:
                customer.first_name, customer.last_name = adopter.name.split(" ", 1)
            except ValueError:
                customer.first_name, customer.last_name = customer.name, ""
            customer.save()

    def backwards(self, orm):
        for customer in orm.Customer.objects.all():
            customer.name = customer.firstname + " " + customer.lastname
            customer.save()</pre>
<p>As you can see, the variable &#8220;orm&#8221; is in fact the real django ORM. you can use it to write data migration in python with the usual django syntax, which is VERY convenient.</p>
<p>run now you data migration:</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py migrate</pre>
<p>A quick django shell will ensure that we have the data present in the database where we expect it to be :</p>
<pre class="brush: bash; gutter: false">$&gt;./manage shell
&gt; from customer.models import Customer
&gt; Customer.objects.all()
[]</pre>
<p>We now just need to delete the remaining an unused field.</p>
<p>Change your model :</p>
<pre class="brush: python">class Customer(models.Model):
    firstname = models.CharField(max_length = 60)
    lastname = models.CharField(max_length = 60)
    password = models.CharField('this is a clear text password', length=60)</pre>
<p>and run a simple migration with &#8211;auto</p>
<pre class="brush: bash">$&gt; ./manage.py startmigration customer remove_name --auto</pre>
<p>and apply</p>
<pre class="brush: bash; gutter: false">$&gt; ./manage.py migrate</pre>
<p>Voila.</p>
<p>References:</p>
<ul>
<li><a title="South migration tool" href="http://south.aeracode.org">The South migration tools</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2010/02/12/how-to-migrate-django-models-with-south/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to extend django&#039;s user class and change authentication middleware.</title>
		<link>http://www.kolios.dk/2010/01/22/how-to-extend-django-user-class-and-change-authentication-middleware/</link>
		<comments>http://www.kolios.dk/2010/01/22/how-to-extend-django-user-class-and-change-authentication-middleware/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 12:59:39 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.kickban.net/?p=74</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/python-48x48.png" width="48" height="48" alt="" title="python" /><br/>Hi everyone, Welcome for the first edition for python-friday ! This python friday will be dedicated to the so popular django web framework because I really have my hands in it for the time being. Django offers a very nice User class to manage all sort of users, set rights, contact information and so on. [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/python-48x48.png" width="48" height="48" alt="" title="python" /><br/><p>Hi everyone,</p>
<p>Welcome for the first edition for python-friday ! This python friday will be dedicated to the so popular django web framework because I really have my hands in it for the time being.</p>
<p>Django offers a very nice User class to manage all sort of users, set rights, contact information and so on. But sometimes, you want to extend that class to add some extra information.</p>
<p>The problem:<br />
You want to use your  &#8211; let&#8217;s call it &#8211; Customer class as the central user class and authenticate using django&#8217;s user modules.</p>
<p>The solution:<br />
Extend the user classs to add your data and configure django framework to use your new class as a middleware and authenticate on it.</p>
<p><span id="more-347"></span></p>
<h3>Extending the class.</h3>
<pre class="brush: python">

from django.contrib.auth.models import User, UserManager

class Customer(User):
	"""
	Model for customer.Hold administrative information
	"""
	company_name = models.CharField('company name', unique=True, max_length = 50)
	tax_number = models.CharField('tax number', max_length = 12)
	address = models.CharField('address line 1', max_length = 200)
	zip_code = models.IntegerField('zip code', max_length = 10)
	city_name = models.CharField('city name', max_length = 20)
	country = models.CharField('country', max_length = 20)
	edited_on = models.DateTimeField(auto_now=True, auto_now_add=True, editable=False)

	# We setup a manager here.. not really sure this is useful
	objects = UserManager()

	def __unicode__(self):
		return self.company_name

	# In the save function, we implement our own password
	# management. If the password is already hashed in the form
	# we just dont change anything otherwise we call the set_password()
	def save(self):
		password = ""
		r = re.compile('sha1\$.*')
		if not r.match(self.password):
			password = self.password
			self.set_password(self.password)
		User.save(self)
</pre>
<p>Now that we have extended the class, we can play a bit with it to see how things goes :</p>
<pre class="brush: python">
> c = Customer()
> c.username = "mms"
> c.lastname = "sauvage"
> c.firstname = "manumanu"
> c.company_name = "the Corp"
#and so on ...
and finally
> c.save()
</pre>
<p>But wait &#8230;. Haven&#8217;t we said that django has its own authentication methods ? Well, how do you want Django framework to know that it has to authenticate against the <em>customer table</em> and <strong>NOT</strong> against django users&#8217; table ?</p>
<p>Well, django can let us redefine the authentication backend. Doing so will then change the authentication behavior the way we want to be.</p>
<h3>Redefining djjango&#8217;s authentication backend.</h3>
<p>First we have to declare our new authenticate backend in the settings.py. While we are in that file, we will also tell django which class to use to authenticate :</p>
<pre name='code' classe='python'>
AUTHENTICATION_BACKENDS = (
    'project.auth_backend.CustomerModelBackend',
)

CUSTOM_USER_MODEL = 'accounts.Customer'
</pre>
<p>We just say here that the backend will be in the file auth_backen.py and the class will be named CustomerModelBackend.</p>
<p>Then create a file called auth-backend.py in your project directory and add it the following content:</p>
<pre  class='brush: python'>
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_model

class CustomerModelBackend(ModelBackend):
	def authenticate(self, username=None, password=None):
		try:
			user = self.user_class.objects.get(username=username)
			if user.check_password(password):
				return user
		except self.user_class.DoesNotExist:
			return None

	def get_user(self, user_id):
		try:
			return self.user_class.objects.get(pk=user_id)
		except self.user_class.DoesNotExist:
			return None

	@property
	def user_class(self):
		if not hasattr(self, '_user_class'):
			self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 2))
		if not self._user_class:
			raise ImproperlyConfigured('Could not get custom user model')
		return self._user_class
</pre>
<p>The authentication backend is a class with 2 methods (get_user and authenticate). This is well explained in the documentation of <a href="http://docs.djangoproject.com/en/dev/topics/auth/#specifying-authentication-backends">django framework</a>.</p>
<p>Now we have a Class for our Extended users, an authentication backend that is configured through our settings.py.</p>
<p>Yes ! This is what we want. The most lazy of you can stop here and start coding his favorite user management webapp.</p>
<h3>Syncdb / admin problem.</h3>
<p>But .. wait a minute. Do you remember when you do your first syncdb ? manage.py ask you if you want to fill in an administrator. If you say yes at that point, manage.py will create a <strong>django user</strong> and now that we authenticate on Custome&#8217;s table, there is a lot of chances that the admin module will not authenticate properly (for the admin only though &#8230;).</p>
<p>The solution is to modify the authentication backend to authenticate on django users&#8217; table in case of a failed authentication on customer&#8217;s table.</p>
<pre class="brush: python">
       def authenticate(self, username=None, password=None):
               try:
                        user = self.user_class.objects.get(username=username)
                except self.user_class.DoesNotExist:
                        try:
                                user = User.objects.get(username=username)
                        except User.DoesNotExist:
                                return None
</pre>
<p>As you can see, the code is pretty straight forward and self explanatory. The only tricky part is the &#8220;@property&#8221; but I let you dig into that yourself as you will learn a lot of things if you want to understand it completely.</p>
<p>Et voila !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2010/01/22/how-to-extend-django-user-class-and-change-authentication-middleware/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dynamic loading of python module</title>
		<link>http://www.kolios.dk/2010/01/18/dynamic-loading-of-python-module/</link>
		<comments>http://www.kolios.dk/2010/01/18/dynamic-loading-of-python-module/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 09:29:53 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.kickban.net/?p=80</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/python-48x48.png" width="48" height="48" alt="" title="python" /><br/>Sometimes ago, a friend of mine recommended me to have a look at python language. Very quickly I got hooked by how easy and developer friendly is that language. The language is straight forward and the number of loadable modules is absolutely amazing. So we go on our python serie with a small piece of [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/python-48x48.png" width="48" height="48" alt="" title="python" /><br/><p>Sometimes ago, a <a href="http://manu.manusauvage.com" title="manusavage's blog">friend of mine</a> recommended me to have a look at python language. Very quickly I got hooked by how easy and developer friendly is that language. The language is straight forward and the number of <a href="http://pypi.python.org/pypi" title="python package index">loadable modules</a> is absolutely amazing.</p>
<p>So we go on our python serie with a small piece of code that could be useful for python developers who want to dynamically load &#8216;packages&#8217; (called on the fly import)</p>
<p><em>The problem:</em><br />
Being able to load dynamically (at runtime) some packages to extend your code.</p>
<p><em>Solution:</em><br />
in all this tutorial, we will use the so unfamous <a href='http://docs.python.org/library/functions.html#__import__' title='python __import__ function'>__import__</a> python builtin.<br />
<span id="more-348"></span><br />
First, let&#8217;s create a package that we can &#8220;autoload&#8221;.<br />
In fact, it will be a regular (and respectful) package like there is tons for python. A package is a piece of code that realize a specific task. It has also a well defined structure.</p>
<p>The structure of the package will be as follow :<br />
<code><br />
package_name:<br />
		-> __init__.py<br />
		-> mymodule.py<br />
</code></p>
<p>First the file <em>__init__.py</em> is a mandatory file that tells that your directory is in fact a package. The file <em>mymodule.py</em> is a regular python script that contain the class that we want to use.</p>
<p>Here is the code of these two file.</p>
<p>The first file (<em>__init__.py</em>)</p>
<pre class='brush: python'>
"""
This modules should keep help use in the future
"""
__author__ = "sebastien requiem (kolios.dk)"
__license__ = "No License"
__version__ = "0.0.1"

from .mymodule import MyModule

def instantiate():
	return MyModule()
</pre>
<p>and the python module code itself (<em>mymodule.py</em>)</p>
<pre class='brush: python'>
import os
import logging

class MyModule:
	"""
	This class is a very cool and helpful class
	"""
	def __init__(self):
		print "We are initializing MyModule.. w00t !"

	def mymethod(self):
		"""
		Simple routines
		"""
		print "mymethod has been called"
</pre>
<p>As you can see, there is no fancy code here. Just note that the <em>__init__.py</em> script contain a function call <em>instantiate</em> and that return an instance of the class that we need.<br />
Now let&#8217;s see how we can make use of that module.</p>
<p>The following piece of code is meant to be used in a production environment but gives you a clear view on how to load dynamically.</p>
<pre class='brush: python'>
import sys
#first we make sure that the current path is in our path.
	sys.path.append(0, '.')

# we need a placeholder for all our modules
	modules ={}
# we define a list of modules we want to load
	module_list = []
	module_list.append('mymodule')

	for module_name in module_list:
		try:
			modules[module_name] =  __import__(module_name)
			print "Successfully loaded module : %s" % module_name
		except ImportError, e:
			print e
			print "can't load %s module" % module_name)
</pre>
<p>That&#8217;s is folks, as simple as that. Let me know in the comments all the troubles you can have with that piece of code. As I am not a python expert, let me know any improvements and ideas you can have regarding this subject.</p>
<p>For those who want to <em>unload</em> any module, you should be able to do it by deleting the key in <em>sys.modules</em> but I must admit that I haven&#8217;t been able to notice any memory improvement after having released any modules. Does that really works ?</p>
<p>See ya !</p>
<p>references:</p>
<ol>
<li>the __import__ python function : <a href='http://docs.python.org/library/functions.html#__import__' title='python __import__ function'>http://docs.python.org/library/functions.html#__import__</a></li>
<li>Python package structure : <a href='http://docs.python.org/tutorial/modules.html' title='python module tutorial'>http://docs.python.org/tutorial/modules.html</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2010/01/18/dynamic-loading-of-python-module/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New WebSite + New Layout</title>
		<link>http://www.kolios.dk/2010/01/17/new-website-new-layout/</link>
		<comments>http://www.kolios.dk/2010/01/17/new-website-new-layout/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 11:47:58 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kolios.dk/?p=452</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/trash-full-48x48.png" width="48" height="48" alt="" title="Uncategorized" /><br/>New Layout&#8230; w00t.]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/trash-full-48x48.png" width="48" height="48" alt="" title="Uncategorized" /><br/><p><a href="http://www.kolios.dk" alt='kolios.dk' title='kolios.dk'>New Layout&#8230;</a> w00t.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2010/01/17/new-website-new-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Howto install a debian (from scratch) on a Buffalo Terastation Duo</title>
		<link>http://www.kolios.dk/2009/09/07/howto-install-a-debian-from-scratch-on-a-buffalo-terastation-duo-2/</link>
		<comments>http://www.kolios.dk/2009/09/07/howto-install-a-debian-from-scratch-on-a-buffalo-terastation-duo-2/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 22:09:35 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[Research]]></category>
		<category><![CDATA[terastation_wxl]]></category>

		<guid isPermaLink="false">http://www.kickban.net/?p=86</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/research-48x48.png" width="48" height="48" alt="" title="Research" /><br/>Hi everyone, It&#8217;s been a while since I haven&#8217;t post anything here. Well, the truth is I have been pretty busy with some projects. And I&#8217;ve been able to play with a Buffalo TeraStation Duo with 2x512GB. But let&#8217;s dig in what we are here for, Debian Install. A bit of specs : cpu : [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/research-48x48.png" width="48" height="48" alt="" title="Research" /><br/><p>Hi everyone,</p>
<p>It&#8217;s been a while since I haven&#8217;t post anything here. Well, the truth is I have been pretty busy with some projects. And I&#8217;ve been able to play with a Buffalo TeraStation Duo with 2x512GB.</p>
<p>But let&#8217;s dig in what we are here for, Debian Install.<br />
<span id="more-359"></span></p>
<p>A bit of specs :</p>
<ul>
<li> cpu : Arm9 at 800Mhz</li>
<li> memory : 512MB</li>
<li> Flash : 512MB</li>
<li> Net : 2 Ethernet ports.</li>
</ul>
<p>Hey ! But why the hell do you want Debian on it ??? It&#8217;s already pretty smooth and neat !<br />
First, it&#8217;s funny, secondly, I learnt a lot by doing that and third .. well &#8230; if Buffalo Administration software<br />
does enough for your needs, why are you reading this ??? Hmmmm ?</p>
<p>Well, enough ! Let&#8217;s go.</p>
<h3>How does the buffalo works ?</h3>
<p><img class="alignleft size-full wp-image-107" title="ts-wxl-r1_sm" src="http://www.kickban.net/wp-content/uploads/2009/09/ts-wxl-r1_sm.jpg" alt="ts-wxl-r1_sm" width="170" height="170" /><br />
The NAS use u-boot bootloader to boot. u-boot is a pretty well documented bootloader and is able to boot nearly everything.</p>
<p>In the normal case (99% of the time), it boots from the RAID1 array and load the kernel (and an initrd image).<br />
In a non-normal case (the so infamous 1% &#8211; for exemple, in case of a hard disk crash), it boots another kernel (and initrd image) from the NAND device. This mode is pretty useful when you have screwed up your NAS.</p>
<blockquote><p>If I was rich and patient, I&#8217;d bought a serial cable with a usb-serial converter to use the serial plug located in front of the device<br />
but I am fairly poor at the moment and really excited to play with the baby.<br />
We would have put the initrd from debian-installer and enjoy seeing the installation going smoothly.</p>
<p>But no, I am poor&#8230; and hopefully, we&#8217;ll find another way.</p></blockquote>
<h3>A bit of theory : How does Debian Lenny netboot works ?</h3>
<p><img class="size-full wp-image-103 alignright" title="logo debian" src="http://www.kickban.net/wp-content/uploads/2009/09/bouton.jpg" alt="logo debian" width="204" height="82" /><br />
Well, pretty easy. The installation disc load a kernel together with an initrd image. This initrd has a script and launch some required scripts that setup everything and finally launch debian-installer. debian-installer will then guide you through the complete process of a clean and neat debian installation.</p>
<h3>Here is the summary of what we will do:</h3>
<ul>
<li>Gain shell access to you TeraStation Duo</li>
<li>Backup the actual kernel and initrd image</li>
<li>Modify the initrd image to make sure that we will boot correctly</li>
<li>Package the Debian Installer for an easy use</li>
<li>Upload the necessary files</li>
<li>Screwup your nas to make it start in EM mode</li>
<li>Gaining access to your NAS (in EM mode)</li>
<li>Prepare the chroot environment and launch the debian-installer</li>
<li>a dirty Hack !</li>
<li>Install DEBIAN (YEAH !)</li>
<li>restore the kernel and initrd</li>
<li>install the WatchDog monitor</li>
<li>rebooting (and praying !)</li>
</ul>
<h3>Gaining access to you NAS:</h3>
<p>Some (very) nice people have seen an security hole in Buffalo ACP protocol and have made a tool to exploit and thus, gain access to your NAS by resetting the root password and starting a telnet deamon.</p>
<p>You can find <a href="http://downloads.nas-central.org/TOOLS/ALL_LS_KB_ARM9/ACP_COMMANDER/acp_commander.jar">acp_commander</a> by clicking on the link. And because you all want to gain shell access to your NAS, here is the command to use :</p>
<pre>java -jar acp_commander.jar -t &lt;ip_of_your_nas&gt; -o</pre>
<p>This should launch a telnet.</p>
<p>If this doesn&#8217;t work, the try the following:</p>
<pre>java -jar acp_commander.jar -t &lt;ip_of_your_nas&gt; -ip &lt;ip_of_your_nas&gt; -pw  -o</pre>
<p>You can now connect by issuing the following command:</p>
<pre>telnet &lt;ip_of_your_nas&gt;</pre>
<h3>Backup the actual kernel and initrd image</h3>
<p>Now that we are in, we have many possibilities. You could install the <a href="http://home.prea.net/hacking/TSLive">OPTWARE packages</a> and live the rest of your life happy and in peace, or we can go further and install a Debian system.  Let&#8217;s backup the kernel and the initrd image as this tutorial covers the Debian Installation but not the installation of a custom kernel.</p>
<pre>$&gt; scp /boot/uImage.buffalo &lt;someone&gt;@&lt;somewhere&gt;:
$&gt; scp /boot/initrd.buffalo &lt;someone&gt;@&lt;somewhere&gt;:</pre>
<h3>Modify the initrd image to make sure that we will boot correctly</h3>
<p>The initrd that we have just backed up, will be used when we will boot our new Debian. But if we use it has it is, the scripts contained in the image will probably do a lot of annoying things (like populating a /etc for no reason, saving the configuration, checking the filesystem). We don&#8217;t want that. So we use the technique described here ( <a href="http://buffalo.nas-central.org/index.php/How_to_modify_an_initrd">How to modify an initrd</a> ) to modify the linuxrc script.</p>
<pre class="brush: bash">HddRoot()
{
    echo "-HddRoot-"
    if [ "${SUPPORT_RAID}" = on ] ; then
    AssembleSysMd boot
    fi
    fsck_disks
#    HasUpdatedFile
#    if [ $? != 0 ]; then
#        echo "** has Updated Files **"
#        echo "** Creating system hotadd pending flag **"
#        touch /tmp/need_firmup
#        echo "0x100" &gt;/proc/sys/kernel/real-root-dev
#        return
#    fi
    if [ "${SUPPORT_RAID}" = on ] ; then
    AssembleSysMd
    fi
#    TestRootfs
#    if [ $? != 0 ]; then
#        echo "0x100" &gt; /proc/sys/kernel/real-root-dev
#    else
    if [ "${SUPPORT_RAID}" = on ] ; then
    echo "0x901" &gt; /proc/sys/kernel/real-root-dev
    else
    echo "0x802" &gt; /proc/sys/kernel/real-root-dev
    fi
    IS_HDDROOT=1
#    fi
}</pre>
<p>Note : 0&#215;901 represent /dev/md1 &#8230; the partition that contain the real-root&#8230;</p>
<pre>$&gt; umount INITRD
$&gt; rmdir INITRD
$&gt; mv initrd.buffalo initrd.stock [backup just in case]
$&gt; gzip initrd
$&gt; mkimage -A arm -O linux -T ramdisk -C gzip -a 0x0 -e 0x0 -n initrd -d initrd.gz initrd.buffalo</pre>
<h3>Package the Debian Installer for an easy use</h3>
<p>Now, we want to launch the debian-installer but &#8230; we have booted in EM mode which mean that we have booted with Buffalo&#8217;s initrd. Fortunately, Debian always do things the right way. Let&#8217;s get the Debian-Installer package, extract it and put in in a tar.gz file that we will be able to extract once booted in EM mode.</p>
<pre>$&gt; wget http://ftp.debian.org/dists/lenny/main/installer-armel/current/images/versatile/netboot/initrd.gz
$&gt; gunzip initrd.gz
$&gt; mkdir deb_init
$&gt; cd deb_init
$&gt; cpio -i &lt; ../initrd
$&gt; tar cf ../deb_init.tar *</pre>
<p>Now we can upload that new archive file on the NAS.</p>
<pre>$&gt; scp &lt;someone&gt;@&lt;somewhere&gt;:/sompath/deb_init.tar /boot</pre>
<h3>Screwup your nas to make it start in EM mode</h3>
<p>u-boot will fall back into booting the EM mode in case  of three unsucessful boot of the normal mode. Let&#8217;s now make sure that the NAS will never boot again <img src='http://www.kolios.dk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre>$&gt; rm /sbin/init</pre>
<p>now it&#8217;s time to REBOOT !</p>
<h3>Gaining access to your NAS (in EM mode)</h3>
<p>After three failed reboots, the NAS will enter the EM mode.</p>
<p>Same procedure :</p>
<pre>java -jar acp_commander.jar -t &lt;ip_of_your_nas&gt; -o</pre>
<h3>Preparing the chroot environment and launching the debian installer</h3>
<p>To be able to install Debian, we have to make a bit of preparation</p>
<pre>$&gt; miconapl -a system_set_watchdog 0
$&gt; killall daemonwatch
$&gt; killall miconmon clientUtil_server kernelmon errormon cat

# if /boot is not mounted yet
$&gt; mdadm -A /dev/md0 /dev/sda1 /dev/sdb1
$&gt; mount /dev/md0 /boot
$&gt; mkdir /debian
$&gt; mount -t tmpfs tmpfs /debian
$&gt; cd /debian
$&gt; cp /boot/uImage.buffalo /boot/new.initrd.buffalo /debian
$&gt; mv /debian/new.initrd.buffalo /debian/initrd.buffalo
$&gt; tar xf /boot/deb_init.tar
$&gt; mount -t proc proc proc/
$&gt; mount -t sysfs sysfs sys/
$&gt; cp /boot/uImage.buffalo initrd.buffalo /debian
$&gt; umount /boot
$&gt; mdadm -S /dev/md0
$&gt; chroot .

$&gt; /lib/debian-installer/start-udev
$&gt; sh /lib/debian-installer-startup.d/S01mount
$&gt; sh /lib/debian-installer-startup.d/S10syslog
$&gt; sh /lib/debian-installer-startup.d/S15lowmem
$&gt; sh /lib/debian-installer-startup.d/S20templates</pre>
<h3>a dirty Hack !</h3>
<p>Here is an awful hack. If you attend to kill dhcpcd to make sure that the debian installer will not get confused, then it will shutdown your interface and you will lose your telnet session. If you kill -9 dhcpcd, everything is fine until the debian-installer try to setup your iface again (with dhcp or manually).</p>
<p>So I opened another telnet session and wrote this dirty little hack that will do the job:</p>
<pre>while true; do ifconfig ethX &lt;ip&gt; netmask &lt;netmask&gt;; done</pre>
<p>Yes, this is an active loop <img src='http://www.kolios.dk/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Let this script run, go back to your previous telnet session and</p>
<pre>$&gt; killall dhcpcd</pre>
<p> <img src='http://www.kolios.dk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Yeah !</p>
<h3>Installing DEBIAN (YEAH !)</h3>
<pre>$&gt; debian-installer</pre>
<p>Let&#8217;s launch the debian installer and follow the instructions. It will complain that it can&#8217;t find a suitable kernel, can&#8217;t find a suitable bootloader neither, just ignore everything. When it comes to the Partition manager, proceed as follow :</p>
<p>Delete ALL partitions of the two disks.</p>
<ul>
<li>Create a new partition (of ~ 512M/1GB) and choose use as physical volume for RAID</li>
<li>Create another partition of (5GB for exemple) and choose use as physical volume for RAID</li>
<li>Finally do the same for the rest of the disk (except the last GB)</li>
<li>Create a swap partition using the last GB of available free space on the disk</li>
</ul>
<p>Do EXACTLY the same for the second disk.</p>
<p>Once this is done, you can see that on top of the disk#1, you know have a menu called &#8220;Configure RAID&#8221;. Go into it, accept the warning message (by selecting YES)</p>
<p>The Disk Partionner restarts again and now we have the RAID devices.</p>
<ul>
<li>Select the first one and assign it to /boot using ext3</li>
<li>Select the second one ad assign it to / using ext3</li>
<li>Select the last one using it for /mnt/array1 using XFS for example.</li>
</ul>
<p>Write the changes to disks. The debian-installer may complain about not being able to re-read the partition table. DO NOT REBOOT. Just press continue to re try reading the partition table. After some tries, it should be ok.</p>
<p>Make sure that you don&#8217;t reboot the NAS at the end of the installation. Instead, open a new telnet session.</p>
<h3>restoring the kernel and initrd</h3>
<pre>$&gt; cp /debian/uImage.buffalo /debian/initrd.buffalo /debian/target/boot</pre>
<h3>installing the WatchDog monitor</h3>
<p>A watchdog is running on the NAS to reboot it in case of a Hanged system. Buffalo&#8217;s firmware was running a small piece of code to manage it. Fortunately, the people from nas-central.org have made it available for ourt debian installation.</p>
<p>Download the tar file and extract it in the new environement.</p>
<pre>$&gt; cd /debian/target
$&gt; chroot .
$&gt; cd /tmp
$&gt; wget http://buffalo.nas-central.org/download/Users/gnyf/micro_evtd_TSP.tar.gz
$&gt; cd /
$&gt; tar zxvf micro_evtd_TSP.tar.gz</pre>
<h3>Install SSH server on the NAS</h3>
<p>While we are here, we want to install SSH server to make sure that we can connect back to the NAS.</p>
<pre>$&gt; apt-get install openssh-server.
$&gt; exit</pre>
<h3>rebooting (and praying !)</h3>
<p>You can now reboot and &#8230; pray !</p>
<p>Leave me any comments on improvement of this method that you can find.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2009/09/07/howto-install-a-debian-from-scratch-on-a-buffalo-terastation-duo-2/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Inkscape module to generate SVG drawings with Python</title>
		<link>http://www.kolios.dk/2009/04/14/inkscape-module-to-generate-svg-drawings-with-python/</link>
		<comments>http://www.kolios.dk/2009/04/14/inkscape-module-to-generate-svg-drawings-with-python/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 09:30:00 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[inkscape]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[svg]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.kickban.net/?p=36</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/coding-48x48.png" width="48" height="48" alt="" title="Coding" /><br/>As a new freelancer, I decided to create my own business cards using moo services. This website allow you to create collectors business cards. The principle is simple, you can upload one image per card so the Verso of the card will be different each time. My problem : How to create a business card [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/coding-48x48.png" width="48" height="48" alt="" title="Coding" /><br/><p><img class="alignleft size-full wp-image-42" title="inkscape" src="http://www.kickban.net/wp-content/uploads/2009/04/inkscape.png" alt="inkscape" width="134" height="106" />As a new <a title="Kolios Unix freelancer" href="http://www.kolios.dk" target="_blank">freelancer</a>, I decided to create my own business cards using moo services. This website allow you to create collectors business cards. The principle is simple, you can upload one image per card so the Verso of the card will be different each time.</p>
<blockquote><p>My problem : How to create a business card that  match my website layout and make it uniq at the same time ?</p></blockquote>
<p><span id="more-358"></span><br />
<img class="alignleft" title="python powered" src="http://www.python.org/community/logos/python-powered-w-140x56.png" alt="" width="140" height="56" />This is when Python and <a title="Inkscape, the beautiful editor" href="http://www.inkscape.org" target="_blank">Inkscape</a> came to rescue me. Inkscape is a well know (GPL&#8217;ed) SVG graphic editor. If you have never tried it, consider doing it. It is amazing what this soft can produce within a couple of minutes. Beside Inkscape, the website <a title="command line fu is a website referencing unix commands" href="http://commandlinefu.com" target="_blank">commandlinfu.com</a> is a (cool) website providing Unix Commands and explanations of what they do (be careful some commands may be dangerous or invalid though).</p>
<p>So I had an idea. Why not using the website <a href="http://commandlinefu.com" target="_blank">commandlinefu</a>, extract commands from the RSS feed and generate images for my Collector Business cards ?</p>
<p><strong>How ?</strong></p>
<p>Inkscape support plugins and offer a nice python module to help you to create SVG objects.</p>
<p><strong>Let&#8217;s go !</strong></p>
<p>Inkscape expect a couple of things from the module structure.</p>
<pre class="brush: python">#!/usr/bin/env python

# These two lines are only needed if you don't put the script directly into
# the installation directory
import sys
from xml.dom import minidom
import urllib
import re

# This import is for MAc os X only. In GNU systems it should
# be somewhere in /usr/share/inkscape/extensions

sys.path.append('/Applications/Inkscape.app/Contents/Resources/extensions')

# We will use the inkex module with the predefined Effect base class.
import inkex
# The simplestyle module provides functions for style parsing.
from simplestyle import *

class BusinessCard(inkex.Effect)
    """
    Example Inkscape effect extension. It reads an RSS feed and create objects according to the content.
    """
    def __init__(self):
        """
        Constructor.
        Defines the "--what" option of a script.
        """
        # Call the base class constructor.
        inkex.Effect.__init__(self)

        # Define string option "--what" with "-w" shortcut and default value "World".
        self.OptionParser.add_option('-w', '--what', action = 'store',
        type = 'integer', dest = 'cards_number', default = '10',
        help = 'How many images do you want to create?')</pre>
<p>The <em>optionparser</em> is required by Inkscape as it will pass some arguments to the script. We could, for example use this argument to know how many images we want to generate. In our case, the argument will be stored in the variable call cards_number. I let you have a closer look to this <a title="Inkscap Python tutorial" href="http://wiki.inkscape.org/wiki/index.php/PythonEffectTutorial" target="_blank">Wiki Page</a> for any further explanation.</p>
<p>Now that we have the basis for creating an Inkscape plugin, we should define the main actions that this plugin is gonna do:</p>
<ol>
<li>Read the RSS feed</li>
<li>Extract the usefull information (and filter)</li>
<li>Create the SVG objects</li>
<li>Add them to the SVG Layer</li>
<li>Loop to 1</li>
</ol>
<p>Let&#8217;s use Python wonderful XML parser to read our RSS feed</p>
<pre class="brush: python">    # Open the XML ressource and read it
    socket = urllib.urlopen("http://feeds2.feedburner.com/Command-line-fu?format=xml");
    # Create an object representing the XML structure
    self.xmldoc = minidom.parse(socket).documentElement
    socket.close();</pre>
<p>Create the function that will do the loop</p>
<pre class="brush: python">    def effect(self):
        """
        Effect behaviour.
        Overrides base class' method and inserts "Hello World" text into SVG document.
        """
        # Get script's "--what" option value.
        cards_number = self.options.cards_number

        # Get access to main SVG document element and get its dimensions.
        svg = self.document.getroot()

        # Create a new layer.
        layer = inkex.etree.SubElement(svg, 'g')
        layer.set(inkex.addNS('label', 'inkscape'), 'Hello %s Layer' % (what))
        layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')

        # Create text element from the RSS feed
        itemlist = self.xmldoc.getElementsByTagName('item')

        #we will loop so better initialize variables
        item_x = 0
        item_y = 0

        # in the RSS feed, the iformation we want in contained in between
        # the &lt;code&gt;&lt;/code&gt; markup. Let's use a regexp to get it.
        regexp = re.compile('&lt;code&gt;.*&lt;/code&gt;');

        # Note that here, we should use the cards_number instead of reading
        # the complete rss feed.
        for node in itemlist:
            title = node.getElementsByTagName('title')[0].firstChild.data
            command = regexp.search(node.getElementsByTagName('description')[0].firstChild.data)

            # Get ride of the markup
            command = command.group()
            command = command.replace("&lt;code&gt;", "");
            command = command.replace("&lt;/code&gt;", "");

            # filter in case the comman is too long...
            if len(command) &gt; 40:
                continue</pre>
<p>Ok so now we have to start creating the objects. For this, Inkscape offer us a nice way to do it. Use the inkex extension. the function inkex.addNS is usefull to create everything you need in SVG.</p>
<pre class="brush: python">        #Design the background grey business card
        background = inkex.etree.Element(inkex.addNS('rect', 'svg'))
        background.set('x', str(item_x))
        background.set('y', str(item_y))
        background.set('width', str(520))
        background.set('height', str(348))
        background.set('fill', 'rgb(32, 32, 32)')

        #Our lovely ornge square will fit here
        square = inkex.etree.Element(inkex.addNS('rect', 'svg'))
        square.set('x', str(item_x + 30))
        square.set('y', str(item_y + 30))
        square.set('width', str(84))
        square.set('height', str(84))
        square.set('rx', str(20))
        square.set('ry', str(20))
        square.set('fill', 'rgb(224, 121, 26)')

        #Insert the "K" letter. K stands for Kolios
        K_logo = inkex.etree.Element(inkex.addNS('text','svg'))
        K_logo.text = ("K")
        # Set text position to center of document.
        K_logo.set('x', str(item_x + 61))
        K_logo.set('y', str(item_y + 95))
        K_logo.set('fill', "white")

        # Center text horizontally with CSS style.
        style = {'text-align' : 'left',
            'font-family': 'MammaGamma',
            'font-size': '56'
        }
        K_logo.set('style', formatStyle(style))

        #Insert the Unix Tip
        tip = inkex.etree.Element(inkex.addNS('text','svg'))
        tip.text = (title)
        # Set text position to center of document.
        tip.set('x', str(item_x + 40))
        tip.set('y', str(item_y + 200))
        tip.set('fill', 'rgb(170, 170, 170)')

        # Center text horizontally with CSS style.
        style = {'text-align' : 'left',
            'font-family': 'terminal',
            'font-style': 'italic'
        }
        tip.set('style', formatStyle(style))

        #Insert the Unix Command
        unix = inkex.etree.Element(inkex.addNS('text','svg'))
        unix.text = (command)
        # Set text position to center of document.
        unix.set('x', str(item_x + 30))
        unix.set('y', str(item_y + 180))
        unix.set('fill', 'rgb(224, 121, 26)')

        # Center text horizontally with CSS style.
        style = {'text-align' : 'left',
            'font-family': 'Monaco',
            'font-size': '20'
        }
        unix.set('style', formatStyle(style))

        # Connect elements together.
        layer.append(background)
        layer.append(square)
        layer.append(K_logo)
        layer.append(kolios)
        layer.append(slogan)
        layer.append(unix)
        layer.append(tip)
        item_y = item_y + 360

    # Create effect instance and apply it.
    effect = BusinessCard()
    effect.affect()</pre>
<p>You can notice that we use css-style for the text. This is possible with the use of the module <em>simplestyle.</em></p>
<p>Basically, you create an object and THEN add it to the layer. Pay attention that the order you add objects MATTERS for the rendering depth. In this case the background will be rendered first, then the square&#8230; and so on. All type of objects can be created and the entire list is available at the <a title="W3C - SVG definition" href="http://www.w3.org/TR/SVG/shapes.html" target="_blank">W3c webpage</a>.</p>
<p>But how do I add my plugin to Inkscape ?</p>
<p>Well, last thing but not the least. You python script should be placed in .inkscape/extensions with a description file</p>
<pre class="brush: xml">&lt;inkscape-extension&gt;
    &lt;_name&gt;Business Card&lt;/_name&gt;
    &lt;id&gt;org.ekips.filter.business_card&lt;/id&gt;
    &lt;dependency type="executable" location="extensions"&gt;card.py&lt;/dependency&gt;
    &lt;dependency type="executable" location="extensions"&gt;inkex.py&lt;/dependency&gt;
    &lt;param name="what" type="integer" _gui-text="How many business cards ?"&gt;10&lt;/param&gt;
    &lt;effect&gt;
    &lt;object-type&gt;all&lt;/object-type&gt;
    &lt;effects-menu&gt;
        &lt;submenu _name="Examples"/&gt;
    &lt;/effects-menu&gt;
    &lt;/effect&gt;
    &lt;script&gt;
        &lt;command reldir="extensions" interpreter="python"&gt;card.py&lt;/command&gt;
    &lt;/script&gt;
&lt;/inkscape-extension&gt;</pre>
<p>The file should be named with a .inx extension. I won&#8217;t explain this as this is pretty obvious.</p>
<p>At last, you can take a llok at the final output. The first picture is NOT generated but &#8230; it gives a good example.</p>
<p><a href="http://www.kickban.net/wp-content/uploads/2009/04/cards.jpg"><img class="aligncenter size-full wp-image-148" title="cards" src="http://www.kickban.net/wp-content/uploads/2009/04/cards.jpg" alt="cards" width="529" height="362" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2009/04/14/inkscape-module-to-generate-svg-drawings-with-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to mount (or at least convert) .bin/.cue images on Mac OSX</title>
		<link>http://www.kolios.dk/2009/04/13/how-to-mount-or-at-least-convert-bincue-images-on-mac-osx/</link>
		<comments>http://www.kolios.dk/2009/04/13/how-to-mount-or-at-least-convert-bincue-images-on-mac-osx/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 14:54:05 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[Research]]></category>
		<category><![CDATA[bin image file]]></category>
		<category><![CDATA[iso image file]]></category>
		<category><![CDATA[mac os x]]></category>

		<guid isPermaLink="false">http://www.kickban.net/?p=25</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/research-48x48.png" width="48" height="48" alt="" title="Research" /><br/>A long time ago, I downloaded a .bin/.cue file on my Mac and Suprize ! the famous (un)popular format is not handled by Mac os X (10.5 at least &#8230; ) so I couldn&#8217;t mount it properly. As this format is not really a standard, I understand Apple policy to not include any filesystem that [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/research-48x48.png" width="48" height="48" alt="" title="Research" /><br/><p><img class="alignleft size-full wp-image-29" title="iso-image" src="http://www.kickban.net/wp-content/uploads/2009/04/iso-image.png" alt="iso-image" width="69" height="71" />A long time ago, I downloaded a .bin/.cue file on my Mac and Suprize ! the famous (un)popular format is not handled by Mac os X (10.5 at least &#8230; ) so I couldn&#8217;t mount it properly.<br />
<span id="more-357"></span><br />
As this format is not really a standard, I understand Apple policy to not include any filesystem that support it but it bugs me everytime I want to play around with this kind of file. Of course, the Licensed Software addicts would jump on <a title="Toast, the licensed burning software for mac os x" href="http://www.roxio.com/enu/products/toast/titanium/overview.html" target="_blank">Toast </a>because it has such feature.</p>
<p>Instead I propose you a (GPL&#8217;ed) softwaree that will convert your .bin/.cue file to an <a title="iso9660 at Wikipedia" href="http://en.wikipedia.org/wiki/Iso9660">.iso image</a>. This format is a supported nearly everywhere and you just have to open the file in Mac os X to mount it and browse the content. This magic software is called <a title="bchunk, the magic tool" href="http://he.fi/bchunk/" target="_blank">bchunk </a>and a version compiled for Mac os X is available <a href="http://jamesnsears.com/code/bchunk.zip">here.</a></p>
<p>Just type the following in your favorite terminal application :</p>
<blockquote><p>$&gt; bchunk myfile.bin myfile.cue mydestination.iso</p></blockquote>
<blockquote><p>$&gt; open mydestination.iso</p></blockquote>
<p>And voila ! This should do the work.</p>
<p>Refer to <a title="James weblog" href="http://www.jamesnsears.com/2007/04/convert_bin_cue_iso_on_mac_osx.php" target="_blank">James blog</a> for a proper installation of this tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2009/04/13/how-to-mount-or-at-least-convert-bincue-images-on-mac-osx/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>the so confusing line-height</title>
		<link>http://www.kolios.dk/2008/11/23/the-so-confusing-line-height-2/</link>
		<comments>http://www.kolios.dk/2008/11/23/the-so-confusing-line-height-2/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 22:32:26 +0000</pubDate>
		<dc:creator>sebastien</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[css line-height]]></category>

		<guid isPermaLink="false">http://www.kickban.net/?p=19</guid>
		<description><![CDATA[<img src="http://www.machezdanois.com/icons/internet-48x48.png" width="48" height="48" alt="" title="Web" /><br/>Eric A. Meyer explain the line-height CSS property. And it does it well. Feel free to check the w3c documentation for further (usefull) information.]]></description>
			<content:encoded><![CDATA[<img src="http://www.machezdanois.com/icons/internet-48x48.png" width="48" height="48" alt="" title="Web" /><br/><p>Eric A. Meyer explain the line-height CSS property. <a title="line-height explanations" href="http://archivist.incutio.com/viewlist/css-discuss/7678" target="_blank">And it does it well</a>. Feel free to check the <a title="Visual formatting model" href="http://www.w3.org/TR/CSS2/visudet.html#propdef-line-height" target="_blank">w3c documentation</a> for further (usefull) information.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kolios.dk/2008/11/23/the-so-confusing-line-height-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
