Oct 5
Neo 1973 arrived!
icon1 Mikkel Meyer Andersen | icon4 October 5, 2007 at 08:20 (UTC) | icon3 15 Comments »
icon3

For just half an hour ago my (hopefully) sweet little new toy arrived! I’m really not going to say much – yet. So I’ll just give you some pictures which barely left the camera (click to enlarge):

cimg0783-medium.JPG cimg0789-medium.JPG cimg0794-medium.JPG cimg0795-medium.JPG cimg0798-medium.JPG cimg0801-medium.JPG cimg0802-medium.JPG cimg0803-medium.JPG cimg0806-medium.JPG cimg0812-medium.JPG cimg0817-medium.JPG cimg0820-medium.JPG

What an excellent timing receiving such a sweetheart on a Friday!

Oct 4
MySQL Backup Script without mysqldump
icon1 Mikkel Meyer Andersen | icon4 October 4, 2007 at 21:47 (UTC) | icon3 No Comments »
icon3

In a long time I’ve looked for a simple backup script to backup an entire database. I’ve actually not managed to find one script not relying on a system(“mysqldump [...]“) or similar nor a script that wasn’t a part of a huge solution and hence depended on a lot of other code.

So what’s a man to do? “Steal” a bit and make the rest himself. Precisely, but I did it reversely.

But here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php	
/**
 * Taken partially from wp-db-backup [1] and is partially self-made [2].
 *
 * [1] uses some libraries, whereas I [2] don't. This is possibly slower and less fail
 * tolerant, but then it doesn't depent on anything other than PHP and MySQL.
 *
 * I [2] am fully aware that it could be done nice with more functions, classes
 * and so on. But this is ment to be simple and do nothing else, so I've
 * permitted myself [2] to write these lines so "messy" :-).
 *
 * [1] : http://www.ilfilosofo.com/blog/wp-db-backup/
 * [2] : Mikkel Meyer Andersen (aka. mikl-dk), http://www.scienco.org 
 */
 
/*
 * Here a MySQL-connection is made and the database chosen
 */
require('../top.php');
 
/*
 * Just a nice little function seperated from the other mess
 */
function secure_addslashes($str = '') 
{
	return str_replace('\'', '\\\'', str_replace('\\', '\\\\', $str));
} 
 
$output = '';
 
/* 
 * From [1]: ensures that the different non-printable chars are printed, e.g. newline
 */
$search = array("\x00", "\x0a", "\x0d", "\x1a");
$replace = array('\0', '\n', '\r', '\Z');
 
/*
 * All the tables from the selected database are selected
 */
$result = @mysql_query("SHOW TABLES") or exception(mysql_error());
 
while ($data = mysql_fetch_array($result))
{
	/* From [1]: Used to differ between using ' to non-integer types 
	 * and use nothing to integer types
	 */
	$result_f = @mysql_query("DESCRIBE `" . $data[0] . "`") or exception(mysql_error());
 
	$ints = array();
 
	while ($data_f = mysql_fetch_assoc($result_f))
	{
		if (
				(false !== strpos(strtolower($data_f['Type']), 'tinyint')) 		||
				(false !== strpos(strtolower($data_f['Type']), 'smallint')) 	||
				(false !== strpos(strtolower($data_f['Type']), 'mediumint')) 	||
				(false !== strpos(strtolower($data_f['Type']), 'int')) 			||
				(false !== strpos(strtolower($data_f['Type']), 'bigint')) 		||
				(false !== strpos(strtolower($data_f['Type']), 'timestamp')) 
			) 
		{
				$ints[strtolower($data_f['Field'])] = "1";
		}
	}	
 
	$result_t = @mysql_query("SHOW CREATE TABLE `" . $data[0] . "`") or exception(mysql_error());
	$data_t = mysql_fetch_array($result_t);
 
	$output .= "DROP TABLE IF EXISTS `" . $data[0] . "`;";
	$output .= "\n\n";
	$output .= $data_t[1] . " ;\n";
	$output .= "\n\n";
 
	$result_d = @mysql_query("SELECT * FROM `" . $data[0] . "`") or exception(mysql_error());
	$entries = 'INSERT INTO `' . $data[0] . '` VALUES (';
 
	while ($data_d = mysql_fetch_assoc($result_d))
	{		
		$values = array();
 
		foreach ($data_d as $key => $value) 
		{		
			if ($ints[strtolower($key)]) 
			{
				$values[] = $value;
			} 
 
			else 
			{
				$values[] = "'" . str_replace($search, $replace, secure_addslashes($value)) . "'";
			}
		}
 
		$output .= " \n" . $entries . implode(', ', $values) . ') ;';
	}
 
	$output .= "\n\n\n";
}
 
echo $output;
?>

And you can add some functionality like this in order to have a compressed file (requires zlib):

100
101
102
103
$filename = date("Y-m-d") . '.gz';
$zp = gzopen($filename, "w9");
gzwrite($zp, $output);
gzclose($zp);
Oct 4
IEnumerable versus implicit conversion
icon1 Mikkel Meyer Andersen | icon4 at 20:02 (UTC) | icon3 No Comments »
icon3

Maybe it’s really just a sick thought, but who cares?! What is actually going to happen if one is enumerating an object which implements both an enumerator-interface and an implicit conversion to a type also implementing an enumerator-interface? At this time I actually know the answer (for Mono at least), but if we should reason about it, it’s almost given that it should use the direct implementation of the enumarator-interface and in that way avoid an implicit conversion.

Now it’s time to shower this post with some code (inspired by [1]):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using System;
using System.Collections;
using System.Collections.Generic;
 
namespace experiments
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			C<int> c = new C<int>(1, 2, 3, 4, 5);
 
			Console.WriteLine("IEnumerable<T>:");
			foreach (int e in c)
			{				
				Console.WriteLine(e);
			}
			Console.WriteLine();
 
			Console.WriteLine("Implicit conversion to List<T>:");			
			foreach (int e in (List<int>)c)
			{
				Console.WriteLine(e);
			}
			Console.WriteLine();
 
			Console.WriteLine("Implicit conversion to T[]:");
			foreach (int e in (int[])c)
			{
				Console.WriteLine(e);
			}
		}
	}	
 
	class C<T> : IEnumerable<T> 		
	{		
		protected List<T> list;
 
		public C(params T[] elements)
		{		
			this.list = new List<T>();
 
			for (int i = 0; i < elements.Length; ++i)
			{
				this.list.Add(elements[i]);
			}
		}
 
		public IEnumerator<T> GetEnumerator() 
		{
			for (int i = this.list.Count - 1; i >= 0; --i)
			{
				yield return this.list[i];
			}
		}
 
		IEnumerator IEnumerable.GetEnumerator() 
		{
			return GetEnumerator();
		}
 
		public static implicit operator List<T>(C<T> c)
		{
			return new List<T>(c.list);
		}		
 
		public static implicit operator T[](C<T> c)
		{
			T[] arr = new T[c.list.Count];			
 
			if (c.list.Count > 0)
			{
				int j = 0;
 
				for (int i = c.list.Count / 2; i >= 0; --i)
				{
					arr[j++] = c.list[i];
				}
 
				for (int i = (c.list.Count / 2) + 1; i < c.list.Count; ++i)
				{
					arr[j++] = c.list[i];
				}
			}
 
			return arr;
		}		
	}
}

And the result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
IEnumerable<T>:
5
4
3
2
1
 
Implicit conversion to List<T>:
1
2
3
4
5
 
Implicit conversion to T[]:
3
2
1
4
5

..gets as expected – still a interesting test (in my opinion), though.

[1]: “C# Precisely” by Peter Sestoft and Henrik I. Hansen

Oct 4

The other day I had to use a web service from a C# 2.0 application. No problem – the .NET 2.0-frameworks provides tons of functionality. To jump into the exciting issue, I’d generated the proxy classes using WSDL, and started communicating with the WS. When no errors occured everything worked fine, but if something went wrong I just got an standard non-informative SoapHeaderException with no details whatsoever. Certainly less useful than a wet newspaper.

The problem was that a SOAP-fault (this name avoids mixing up the concepts of SOAP- and run-time exceptions) occurred, but the actual description of the error in the SOAP-response was not deserialized properly and was therefore not included in the run-time exception. The SOAP-response looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<soapenv:envelope
	xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns="http://tews6/wsdl"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
	<soapenv:body>
		<soapenv:fault>
			<faultcode>soapenv:Client</faultcode>
			<faultstring>Error performing operation.</faultstring>
			<detail>
				<imsexception version="6.0">
					<exception>
						<name>CheckForDuplicates</name>
						<code>500</code>
						<description><!--[CDATA[User id johndoe is a duplicate. ProcessStep::BLTHValidate TabName:  ERRORLEVEL::Error]]--></description>
					</exception>
				</imsexception>
			</detail>
		</soapenv:fault>
	</soapenv:body>
</soapenv:envelope>

I read about this several places, and all these said that it was just the way .NET worked in that area. Sounds a bit odd, but nevertheless I instead started to figure out how to solve it.

The solution is actually quite simple, but it took some time to figure out how it should be done. It consists of three parts:

  • A custom Exception so that it can be caught separately
  • A SoapExtension that handled serialization and deserialization of the SOAP-messages and in that way were possible to intervene if a SOAP-fault occurred and throw the custom exception instead of a generic SoapException
  • A SoapExtensionAttribute used to mark the web methods should use the SOAP-extension

It actually works very well! The only drawback is that every web method has to be marked with the attribute – but just another opportunity to celebrate sed!

Oct 4
Persistance
icon1 Mikkel Meyer Andersen | icon4 at 13:20 (UTC) | icon3 No Comments »
icon3

With the discussion regarding location-based software as a starting point, I realized that the issue regarding persistence was far from trivial. Of course it’s a problem in the matter of making areas (as in a set of locations) persistent, but in general persistence of data structures often seems to be a problem, not just on OpenMoko.

Some optimal data structure might be quite a mess to make persistent, which lead to the selection of another data structure.

Still, I haven’t read much about this subject in regards to OpenMoko, but I think remembering something about it uses a Evolution Data Server. Well, it’s certainly a subject to investigate further – in particular to location-based reminding which I think is very exciting.

Oh, my Neo 1973 should arrive tomorrow! Yeah!

Oct 4
Creating a SSH-tunnel in Linux
icon1 Mikkel Meyer Andersen | icon4 at 13:11 (UTC) | icon3 No Comments »
icon3

Sometimes I need to make a tunnel through a SSH-server if I’m unable to reach a service beyond the LAN. That’s a SSH-tunnel (clever name!). Actually I’m often having problems remember which arguments to pass to the SSH-client, so just a little reminder to myself. I naturally hope that it can help someone else, too:

1
ssh user@ssh-server -L local-port-to-bind-to:host-to-reach:the-port-on-the-host

Or maybe in a more readable format:

1
ssh user@ssh-server -L x:y:z

where
x = the local port to bind the tunnel to
y = the host that should be at the other end of the tunnel, so to speak
z = the port on the host

Next Entries »