<?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>Erning.write() &#187; code</title>
	<atom:link href="http://erning.net/tags/code/feed" rel="self" type="application/rss+xml" />
	<link>http://erning.net</link>
	<description>Reloading</description>
	<lastBuildDate>Thu, 15 Sep 2011 10:04:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>8 puzzle (python)</title>
		<link>http://erning.net/archives/8-puzzle-python</link>
		<comments>http://erning.net/archives/8-puzzle-python#comments</comments>
		<pubDate>Sat, 30 Jul 2011 18:33:29 +0000</pubDate>
		<dc:creator>erning</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://erning.net/?p=461</guid>
		<description><![CDATA[重排九宫 +---+---+---+ +---+---+---+ &#124; 1 &#124; 2 &#124; 3 &#124; &#124; 8 &#124; 7 &#124; 6 &#124; +---+---+---+ +---+---+---+ &#124; 4 &#124; 5 &#124; 6 &#124; ==&#62; &#124; 5 &#124; 4 &#124; 3 &#124; +---+---+---+ +---+---+---+ &#124; 7 &#124; 8 &#124; &#124; &#124; 2 &#124; 1 &#124; &#124; +---+---+---+ +---+---+---+ $ 8puzzle.py -f2 # 30 [...]]]></description>
			<content:encoded><![CDATA[<p>重排九宫</p>
<pre><code>+---+---+---+      +---+---+---+
| 1 | 2 | 3 |      | 8 | 7 | 6 |
+---+---+---+      +---+---+---+
| 4 | 5 | 6 |  ==&gt; | 5 | 4 | 3 |
+---+---+---+      +---+---+---+
| 7 | 8 |   |      | 2 | 1 |   |
+---+---+---+      +---+---+---+

$ 8puzzle.py -f2
# 30
Number of states enqueued = 14754</code></pre>
<p/>
<pre>
#!/usr/bin/env python

import sys
from optparse import OptionParser
import math
from struct import pack
import heapq

class Solver:
    def __init__(self, n):
        self.N = n
        self.L = n * n

        self.GOAL = range(1, self.L)
        self.GOAL.append(0)

        # slide rules
        self.SR = {}
        for i in range(self.L):
            s = []
            if i - self.N &gt;= 0:
                s.append(i - self.N)
            if (i % self.N) - 1 &gt;= 0:
                s.append(i - 1)
            if (i % self.N) + 1 &lt; self.N:
                s.append(i + 1)
            if i + self.N &lt; self.L:
                s.append(i + self.N)
            self.SR[i] = s

        # queue
        self.queue = []
        self.enqueued = {}

        # verbose
        #self.verbose = 104999
        self.verbose = 8963

        # h
        self.w = 1
        self.h = self.heuristics

    def is_solvable(self, tiles):
        x = 0
        for p in range(len(tiles)):
            a = tiles[p]
            if a &lt; 2 :
                continue
            for b in tiles[p:]:
                if b == 0:
                    continue
                if a &gt; b:
                    x = x + 1
        return (x &amp; 1) == 0

    def neighbors(self, tiles):
        n = []
        a = tiles.index(0)
        for b in self.SR[a]:
            n.append(self.swap(list(tiles), a, b))
        return n

    def swap(self, tiles, a, b):
        tiles[a], tiles[b] = tiles[b], tiles[a]
        return tiles

    def display(self, tiles):
        for i in range(self.L):
            if tiles[i]:
                print &#039;%(n)#2d&#039; % {&#039;n&#039;: tiles[i]},
            else:
                print &#039;  &#039;,
            if i % self.N == self.N - 1:
                print

    def enqueue(self, state):
        (tiles, parent, h, g) = state

        if self.verbose &gt; 0 and len(self.enqueued) % self.verbose == self.verbose - 1:
            print &quot; --&gt;&quot;, len(self.enqueued), g

        f = h * self.w + g;
        heapq.heappush(self.queue, (f, state))

    def dequeue(self):
        if len(self.queue) &lt;= 0:
            return None
        (f, state) = heapq.heappop(self.queue)
        return state

    def heuristics(self, tiles):
        return 0;

    def manhattan(self, tiles):
        h = 0
        for i in range(self.L):
            n = tiles[i]
            if n == 0:
                continue
            h += int(abs(n - 1 - i) / self.N) + (abs(n - 1 - i) % self.N)
        return h

    def hamming(self, tiles):
        h = 0
        for i in range(self.L):
            n = tiles[i]
            if n &gt; 0 and n - 1 != i:
                h += 1
        return h

    def solve(self, initial):
        if not self.is_solvable(initial):
            return None

        state = (initial, None, self.h(initial), 0);
        if initial == self.GOAL:
            return state

        self.enqueue(state)

        while True:
            state = self.dequeue()
            if (not state):
                break

            (tiles, parent, h, g) = state
            neighbors = self.neighbors(tiles)
            for n_tiles in neighbors:
                if n_tiles == self.GOAL:
                    return (n_tiles, state, 0, g + 1)

                packed = pack(self.L*&#039;B&#039;, *n_tiles)
                if (packed in self.enqueued):
                    continue;
                self.enqueued[packed] = True                        

                n_state = (n_tiles, state, self.h(n_tiles), g + 1)
                self.enqueue(n_state)

def main(options, args):
    initial = []
    if args:
        for n in args:
            initial.append(int(n))
    else:
        initial = [8,7,6,5,4,3,2,1,0]

    solver = Solver(int(math.sqrt(len(initial))))

    solver.verbose = int(options.verbose)
    solver.w = float(options.weight)
    if int(options.function) == 1:
        solver.h = solver.hamming
    elif int(options.function) == 2:
        solver.h = solver.manhattan

    state = solver.solve(initial)
    if not state:
        print &quot;No solution possible&quot;
        return 1

    solution = []
    while state:
        (tiles, parent, h, g) = state
        solution.insert(0, tiles)
        state = parent

    n = 0
    for tiles in solution:
        print &quot;#&quot;, n
        solver.display(tiles)
        print
        n += 1

    print &quot;Number of states enqueued =&quot;, len(solver.enqueued)
    return 0

if __name__ == &#039;__main__&#039;:
    parser = OptionParser(usage=&quot;usage: %prog [options] [tile] [tile] [tiles ...]&quot;)
    parser.add_option(&quot;-v&quot;, &quot;--verbose&quot;, metavar=&quot;&lt;level&gt;&quot;,
            default=8963)
    parser.add_option(&quot;-f&quot;, &quot;--function&quot;, metavar=&quot;&lt;fid&gt;&quot;,
            help=&quot;heuristics function. 1 for hamming, 2 for manhattan [default: None as breadth first]&quot;,
            default=0)
    parser.add_option(&quot;-w&quot;, &quot;--weight&quot;, metavar=&quot;&lt;n&gt;&quot;,
            help=&quot;weighting of the heuristics function [default: 1]&quot;,
            default=1)
    (options, args) = parser.parse_args()

    sys.exit(main(options, args))
</pre>
<pre><code>+----+----+----+----+       +----+----+----+----+
| 15 | 14 | 13 | 12 |       |  1 |  2 |  3 |  4 |
+----+----+----+----+       +----+----+----+----+
| 11 | 10 |  9 |  8 |       |  5 |  6 |  7 |  8 |
+----+----+----+----+  ==&gt;  +----+----+----+----+
|  7 |  6 |  5 |  4 |       |  9 | 10 | 11 | 12 |
+----+----+----+----+       +----+----+----+----+
|  3 |  1 |  2 |    |       | 13 | 15 | 14 |    |
+----+----+----+----+       +----+----+----+----+

$ 8puzzle.py -f2 -w1.9 15 14 13 12 11 10 9 8 7 6 5 4 3 1 2 0
# 76
Number of states enqueued = 2812200
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://erning.net/archives/8-puzzle-python/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>动态域名解析服务</title>
		<link>http://erning.net/archives/dynamic-domain-service</link>
		<comments>http://erning.net/archives/dynamic-domain-service#comments</comments>
		<pubDate>Sun, 24 Jan 2010 19:21:58 +0000</pubDate>
		<dc:creator>erning</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dns]]></category>

		<guid isPermaLink="false">http://erning.net/?p=205</guid>
		<description><![CDATA[有自己的VPS，很多服务都可以自己来做了，例如我自己安装一个VPN用来穿墙。今天用PowerDNS做了一个动态域名解析服务，替换过去老旧的方法。现在不仅可以自己用，还可以提供给其他有动态域名解析需求的同学。 更新域名的API很简单，一个HTTP请求即可。API地址是: http://dynamic.wacao.com/api/plain.php，参数为， host &#8211; 主机名，FQDN为 ${host}.dynamic.wacao.com time &#8211; unixtime形式的请求时间，时间误差在正负5分钟内有效 sign &#8211; 签名，格式为 sha1(${host}${time}${shared_key}) ip &#8211; 可选。如果未提供IP地址则采用客户端请求的来源地址 其中host和shared_key需要我来提供。这里提供一个的host和shared_key给大家测试。testing d035cdac09dd866ed8f4a244567c4daf。域名为testing.dynamic.wacao.com.。 由于仅是一个HTTP请求，客户端很容易用各种语言实现。我自己用的是一个简单的shell脚本。 #!/bin/bash function usage { echo "Usage: $0 {host} {shared_key}" } if test -z $1 &#124;&#124; test -z $2 then usage exit 1 fi HOST=$1 SHARED_KEY=$2 ENDPOINT="http://dynamic.wacao.com/api/plain.php" TIME=`date +%s` SIGN=`echo -n "${HOST}${TIME}${SHARED_KEY}" &#124; sha1sum -t &#124; [...]]]></description>
			<content:encoded><![CDATA[<p>有自己的VPS，很多服务都可以自己来做了，例如我自己安装一个VPN用来穿墙。今天用<a href="http://www.powerdns.com/">PowerDNS</a>做了一个动态域名解析服务，替换过去<a href="http://erning.net/archives/dynamic-dns-diy">老旧的方法</a>。现在不仅可以自己用，还可以提供给其他有动态域名解析需求的同学。</p>
<p>更新域名的API很简单，一个HTTP请求即可。API地址是: <strong>http://dynamic.wacao.com/api/plain.php</strong>，参数为，</p>
<ul>
<li>host &#8211; 主机名，FQDN为 ${host}.dynamic.wacao.com</li>
<li>time &#8211; unixtime形式的请求时间，时间误差在正负5分钟内有效</li>
<li>sign &#8211; 签名，格式为 sha1(${host}${time}${shared_key}) </li>
<li>ip &#8211; 可选。如果未提供IP地址则采用客户端请求的来源地址</li>
</ul>
<p>其中host和shared_key需要我来提供。这里提供一个的host和shared_key给大家测试。<strong>testing</strong> <strong>d035cdac09dd866ed8f4a244567c4daf</strong>。域名为<strong>testing.dynamic.wacao.com.</strong>。</p>
<p>由于仅是一个HTTP请求，客户端很容易用各种语言实现。我自己用的是一个简单的shell脚本。</p>
<pre>
#!/bin/bash

function usage {
    echo "Usage: $0 {host} {shared_key}"
}

if test -z $1 || test -z $2
then
    usage
    exit 1
fi

HOST=$1
SHARED_KEY=$2
ENDPOINT="http://dynamic.wacao.com/api/plain.php"

TIME=`date +%s`
SIGN=`echo -n "${HOST}${TIME}${SHARED_KEY}" | sha1sum -t | awk '{print $1}'`
URL="${ENDPOINT}?host=${HOST}&#038;time=${TIME}&#038;sign=${SIGN}"
curl "$URL"
</pre>
<p>执行后立即能够解析，TTL为5秒。</p>
<pre>
$ update-dynamic-dns.sh testing d035cdac09dd866ed8f4a244567c4daf
ok. 58.33.69.77
$ host testing.dynamic.wacao.com.
testing.dynamic.wacao.com has address 58.33.69.77
</pre>
<p>我将这个脚本加到crontab里，每5分钟更新一次。</p>
<pre>
*/5 * * * * /usr/local/sbin/update-dynamic-dns.sh ${HOST} ${SHARED_KEY}
</pre>
<p>如果觉得testing.dynamic.wacao.com这样的域名不好看，而且你有自己的域名，可以想我一样，给自己的域名加一个CNAME。例如我把alcohol.swanpan.com做了一个CNAME指到alcohol.dynamic.wacao.com</p>
<pre>
;; ANSWER SECTION:
alcohol.swanpan.com.	86400	IN	CNAME	alcohol.dynamic.wacao.com.
alcohol.dynamic.wacao.com. 5	IN	A	58.33.69.77
</pre>
<p>这样我在各个地方都能用alcohol.swanpan.com这个域名访问家里的机器，方便<a href="http://erning.net/archives/my-linux-gateway">用它穿墙</a>。</p>
<p>想试试的朋友告诉我你要的host，我给你发送shared_key。</p>
]]></content:encoded>
			<wfw:commentRss>http://erning.net/archives/dynamic-domain-service/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>USB硬盘的固定设备名和自动休眠</title>
		<link>http://erning.net/archives/static-device-name-and-auto-spin-down-for-usb-harddisk</link>
		<comments>http://erning.net/archives/static-device-name-and-auto-spin-down-for-usb-harddisk#comments</comments>
		<pubDate>Sat, 23 Jan 2010 18:07:26 +0000</pubDate>
		<dc:creator>erning</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[gentoo]]></category>

		<guid isPermaLink="false">http://erning.net/?p=186</guid>
		<description><![CDATA[AirPort Extreme可以外接USB硬盘提供文件服务，但是和它的路由功能一样，都不够满足我的需求。而作为穿墙路由器的华硕小机器有4个USB口，我还用它兼作文件服务器使用，提供Samba和NFS。 但是Gentoo在这里遇到两个小问题。 第一个问题，USB硬盘是可以热拔插，这样由于载入顺序的问题，每个硬盘设备名称可能会变化。例如这个机器自带一个读卡器，在没有外挂USB硬盘时启动后候设备名为/dev/sdb。之后插入USB硬盘，USB硬盘的设备名为/dev/sdc。但是如果挂着USB硬盘启动，这两个设备的设备名就正好反过来了。我希望是固定的设备名。 第二个问题，USB硬盘长时间不访问的时候不会自动停下来，这样既不省电也不利延长硬盘的寿命。我希望在不用的时候它可以休眠。 设备名的问题可以用udev的rules解决。我加了一个udev配置文件/etc/udev/rules.d/99-external-storages.rules。 KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="0158", ATTRS{serial}=="20071114173400000", SYMLINK+="cardreader%n" KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="0c31", ATTRS{serial}=="20090717090A", SYMLINK+="storage/neso%n" 这样给内置的读卡器添加了一个设备名的符号链接/dev/cardreader；给我的NESO 1T硬盘添加了设备名符号链接/dev/storage/neso。用固定名称访问设备的问题就解决了。 第二个问题稍微复杂些，一直没找到方便的方法。laptop-mode-tools也没能满足我的要求。一番搜索后找到sdparm可以用来控制USB硬盘，还有一段perl脚本用来调度sdparm。这样就可以满足我的需求了。脚本的原始出外我给忘了，这里我稍微修改了一点，增加对设备名符号链接的支持。 #!/usr/bin/perl -w use File::Basename; use Cwd &#039;abs_path&#039;; $statfile = &#34;/proc/diskstats&#34;; die &#34;$0: Cannot read $statfile\n&#34; unless -r $statfile; $&#124; = 1; ($disk, $interval) = (@ARGV); if (-l $disk) { $original_disk = $disk; while (-l [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.apple.com/airportextreme/">AirPort Extreme</a>可以外接USB硬盘提供文件服务，但是和它的路由功能一样，都不够满足我的需求。而作为<a href="http://erning.net/archives/my-linux-gateway">穿墙路由器</a>的华硕小机器有4个USB口，我还用它兼作文件服务器使用，提供Samba和NFS。</p>
<p>但是Gentoo在这里遇到两个小问题。</p>
<p>第一个问题，USB硬盘是可以热拔插，这样由于载入顺序的问题，每个硬盘设备名称可能会变化。例如这个机器自带一个读卡器，在没有外挂USB硬盘时启动后候设备名为/dev/sdb。之后插入USB硬盘，USB硬盘的设备名为/dev/sdc。但是如果挂着USB硬盘启动，这两个设备的设备名就正好反过来了。我希望是固定的设备名。</p>
<p>第二个问题，USB硬盘长时间不访问的时候不会自动停下来，这样既不省电也不利延长硬盘的寿命。我希望在不用的时候它可以休眠。</p>
<p>设备名的问题可以用udev的rules解决。我加了一个udev配置文件/etc/udev/rules.d/99-external-storages.rules。</p>
<pre>
KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="0158", ATTRS{serial}=="20071114173400000", SYMLINK+="cardreader%n"
KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="0c31", ATTRS{serial}=="20090717090A", SYMLINK+="storage/neso%n"
</pre>
<p>这样给内置的读卡器添加了一个设备名的符号链接/dev/cardreader；给我的NESO 1T硬盘添加了设备名符号链接/dev/storage/neso。用固定名称访问设备的问题就解决了。</p>
<p>第二个问题稍微复杂些，一直没找到方便的方法。<a href="http://samwel.tk/laptop_mode/">laptop-mode-tools</a>也没能满足我的要求。一番搜索后找到<a href="http://sg.danny.cz/sg/sdparm.html">sdparm</a>可以用来控制USB硬盘，还有一段perl脚本用来调度sdparm。这样就可以满足我的需求了。脚本的原始出外我给忘了，这里我稍微修改了一点，增加对设备名符号链接的支持。</p>
<pre>
#!/usr/bin/perl -w
use File::Basename;
use Cwd &#039;abs_path&#039;;

$statfile = &quot;/proc/diskstats&quot;;
die &quot;$0: Cannot read $statfile\n&quot; unless -r $statfile;

$| = 1;
($disk, $interval) = (@ARGV);

if (-l $disk) {
    $original_disk = $disk;
    while (-l $disk) {
        $disk = readlink $disk;
    }
    $disk = dirname($original_disk) . &quot;/&quot; . $disk;
    $disk = abs_path($disk);
}

$disk =~ s,/dev/,,;
print &quot;$0: disk: $disk, interval: $interval\n&quot;;

$halted_data = $last_seen = &#039;&#039;;
while (1) {
  open(STATUS, $statfile);
  ($_) = grep(/^\s+\d+\s+\d+\s+$disk\s/o, &lt;STATUS&gt;);
  close STATUS;

  if ($last_seen eq $_ &amp;&amp; $halted_data ne $_) {
    print &quot;Spinning down: $disk\n&quot;;
    system &quot;sync&quot;;
    system &quot;sdparm&quot;, &quot;--command=stop&quot;, &quot;/dev/$disk&quot;;
    $halted_data = $_;
  }
  $last_seen = $_;
  sleep $interval;
}
</pre>
<p>最后在启动脚本里加上</p>
<pre>
ebegin "    - Spindown USB HD"
nohup /usr/local/sbin/spindown-usbhd /dev/storage/neso 1200 >> /var/log/spindown-usbhd.log 2>&#038;1 &#038;
eend $?
</pre>
<p>好了，20分钟这块硬盘没有读写之后自动休眠。</p>
]]></content:encoded>
			<wfw:commentRss>http://erning.net/archives/static-device-name-and-auto-spin-down-for-usb-harddisk/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java String</title>
		<link>http://erning.net/archives/java-string</link>
		<comments>http://erning.net/archives/java-string#comments</comments>
		<pubDate>Thu, 06 Apr 2006 10:33:39 +0000</pubDate>
		<dc:creator>erning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[recruiting]]></category>

		<guid isPermaLink="false">http://www.erning.net/archives/2006/04/06/java-string/</guid>
		<description><![CDATA[挺无聊的题目真的难倒不少人，咳 public class Hello { public static void main(String[] args) { String s = "123"; System.out.println(s); m1(s); System.out.println(s); int i = 123; System.out.println(i); m2(i); System.out.println(i); } private static void m1(String s) { s = "321"; } private static void m2(int i) { i = 321; } } 运行结果是什么？]]></description>
			<content:encoded><![CDATA[<p>挺无聊的题目真的难倒不少人，咳</p>
<pre>
public class Hello {
    public static void main(String[] args) {
        String s = "123";
        System.out.println(s);
        m1(s);
        System.out.println(s);

        int i = 123;
        System.out.println(i);
        m2(i);
        System.out.println(i);
    }

    private static void m1(String s) {
        s = "321";
    }

    private static void m2(int i) {
        i = 321;
    }
}
</pre>
<p>运行结果是什么？</p>
]]></content:encoded>
			<wfw:commentRss>http://erning.net/archives/java-string/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Dynamic DNS-DIY</title>
		<link>http://erning.net/archives/dynamic-dns-diy</link>
		<comments>http://erning.net/archives/dynamic-dns-diy#comments</comments>
		<pubDate>Sun, 02 Apr 2006 05:18:56 +0000</pubDate>
		<dc:creator>erning</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dns]]></category>

		<guid isPermaLink="false">http://www.erning.net/archives/2006/04/02/dynamic-dns-diy/</guid>
		<description><![CDATA[宿舍的宽带好，写了一个简单的python脚本，自动更新域名解析到动态的IP地址，这样我就可以随时访问宿舍里的机器了。 http://swanpan.com/phpsysinfo/ #!/usr/bin/env python import cookielib import urllib import urllib2 import time import sys def ddd_checkip(): response = urllib2.urlopen("http://www.dragonsoft.net/checkip.php") return response.read() def ddd_hello(opener): return opener.open("http://www.dns-diy.com/skin.aspx?skin=api") def ddd_login(opener, username, password): request = urllib2.Request("https://www.dns-diy.com/api/login.aspx") params = urllib.urlencode({"username":username, 'password':password}) request.add_data(params) return opener.open(request) def ddd_logout(opener): request = urllib2.Request("http://www.dns-diy.com/api/logout.aspx?immediately=yes&#038;invalidate=yes") return opener.open(request) def ddd_update_rr(opener, id, name, type, data, aux, ttl): request [...]]]></description>
			<content:encoded><![CDATA[<p>宿舍的宽带好，写了一个简单的python脚本，自动更新域名解析到动态的IP地址，这样我就可以随时访问宿舍里的机器了。<br />
<a href="http://swanpan.com/phpsysinfo/">http://swanpan.com/phpsysinfo/</a></p>
<pre>
#!/usr/bin/env python

import cookielib
import urllib
import urllib2
import time
import sys

def ddd_checkip():
        response = urllib2.urlopen("http://www.dragonsoft.net/checkip.php")
        return response.read()

def ddd_hello(opener):
        return opener.open("http://www.dns-diy.com/skin.aspx?skin=api")

def ddd_login(opener, username, password):
        request = urllib2.Request("https://www.dns-diy.com/api/login.aspx")
        params = urllib.urlencode({"username":username, 'password':password})
        request.add_data(params)
        return opener.open(request)

def ddd_logout(opener):
        request = urllib2.Request("http://www.dns-diy.com/api/logout.aspx?immediately=yes&#038;invalidate=yes")
        return opener.open(request)

def ddd_update_rr(opener, id, name, type, data, aux, ttl):
        request = urllib2.Request("http://www.dns-diy.com/api/zone_rr_update.aspx")
        params = urllib.urlencode({"id":id, "rr_name":name, "rr_type":type, "rr_data":data, "rr_aux":aux, "rr_ttl":ttl})
        request.add_data(params)
        return opener.open(request)

#
#
#

DEBUG = 5
SLEEP_SECONDS = 600

USERNAME = "swanpan.com"
PASSWORD = "secure"
RR_ID    = "secure"
RR_NAME  = ""
RR_TYPE  = "A"
RR_DATA  = "127.0.0.1"
RR_AUX   = "0"
RR_TTL   = "5"

def ddd_process():
        if (DEBUG > 0):
                print "[%(time)s] updating %(host)s.%(zone)s (%(ip)s) ..." % \
                        {"time":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), \
                        "host":RR_NAME, "zone":USERNAME, "ip":RR_DATA}

        opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar()))

        response = ddd_hello(opener)
        if (DEBUG > 5):
                print "HELLO"
                print response.read()

        response = ddd_login(opener, USERNAME, PASSWORD)
        if (DEBUG > 5):
                print "LOGIN"
                print response.read()

        response = ddd_update_rr(opener, RR_ID, RR_NAME, RR_TYPE, RR_DATA, RR_AUX, RR_TTL)
        if (DEBUG > 5):
                print "UPDATE"
                print response.read()

        response = ddd_logout(opener)
        if (DEBUG > 5):
                print "LOGOUT"
                print response.read()

        if (DEBUG > 0):
                print "[%(time)s] Finished!" % \
                        {"time":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}

while True:
        try:
                ip = ddd_checkip()
                if (RR_DATA != ip):
                        RR_DATA = ip
                        ddd_process()
        except:
                if (DEBUG > 4):
                        print "Unexpected error:", sys.exc_info()[0]

        time.sleep(SLEEP_SECONDS)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://erning.net/archives/dynamic-dns-diy/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>My screenshot script</title>
		<link>http://erning.net/archives/my-screenshot-script</link>
		<comments>http://erning.net/archives/my-screenshot-script#comments</comments>
		<pubDate>Tue, 28 Jun 2005 13:56:34 +0000</pubDate>
		<dc:creator>erning</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.erning.net/?p=53</guid>
		<description><![CDATA[Here&#8217;s my screenshot script under linux. ImageMagick is required. #! /bin/bash SSPATH="$HOME/documents/pictures/screenshots" SSDATE="$(date +%Y-%m-%d_%H-%M-%S)" SSNAME="$SSPATH/$SSDATE.png" if [ ! -d "$SSPATH" ]; then mkdir -p "$SSPATH" fi #sleep 10 import -window root "$SSNAME"]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s my screenshot script under linux.<br />
<a href="http://www.imagemagick.org/">ImageMagick</a> is required.</p>
<pre>
#! /bin/bash

SSPATH="$HOME/documents/pictures/screenshots"
SSDATE="$(date +%Y-%m-%d_%H-%M-%S)"
SSNAME="$SSPATH/$SSDATE.png"

if [ ! -d "$SSPATH" ]; then
        mkdir -p "$SSPATH"
fi

#sleep 10
import -window root "$SSNAME"
</pre>
]]></content:encoded>
			<wfw:commentRss>http://erning.net/archives/my-screenshot-script/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

