<?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>sixserv blog</title>
	<atom:link href="http://sixserv.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://sixserv.org</link>
	<description>A Blog about Linux, Networking, Development and Security.</description>
	<lastBuildDate>Thu, 18 Feb 2010 22:13:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JavaScript: onMouseMove Google Translation</title>
		<link>http://sixserv.org/2010/02/10/javascript-onmousemove-google-translation/</link>
		<comments>http://sixserv.org/2010/02/10/javascript-onmousemove-google-translation/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 15:37:13 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[onMouseMove]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=590</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_web.png" width="50" height="51" alt="" title="Web" /><br/>I wanted to implement a JavaScript onMouseMove Event, that translates the word under the mouse pointer with the Google Translator. I want to share the following solution.
I split this into the following two separate problems:
First: Detect word for an onMouseMove Event
The onMouseMove Event can listen on any Element for mouse movements. To detect the word [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_web.png" width="50" height="51" alt="" title="Web" /><br/><p>I wanted to implement a JavaScript <a href="https://developer.mozilla.org/en/DOM/element.onmousemove">onMouseMove Event</a>, that translates the word under the mouse pointer with the <a href="http://translate.google.com/#">Google Translator</a>. I want to share the following solution.</p>
<p>I split this into the following two separate problems:</p>
<h3>First: Detect word for an onMouseMove Event</h3>
<p>The onMouseMove Event can listen on any Element for mouse movements. To detect the word under the mouse pointers position, I utilize the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html">W3C(DOM-2)</a> specified <a href="http://www.quirksmode.org/dom/range_intro.html">Range Object</a>.</p>
<p>Most modern browsers support the Range object, but the event.rangeParent Attribute seems to be only supported by Firefox. <em>Currently I&#8217;ve no cross-browser solution for this.</em></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * Apply offset to range and extract a single character at position.
 *
 * range -- the range object effected
 * originalOffsetStart, originalOffsetEnd -- Start offsetStart and offsetEnd
 * offset -- the relative offset to apply
 */</span>
<span style="color: #003366; font-weight: bold;">function</span> getRangeCharacter<span style="color: #009900;">&#40;</span>range<span style="color: #339933;">,</span> originalOffsetStart<span style="color: #339933;">,</span> originalOffsetEnd<span style="color: #339933;">,</span> offset<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> character <span style="color: #339933;">=</span> <span style="color: #3366CC;">' '</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
        range.<span style="color: #660066;">setStart</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetStart <span style="color: #339933;">+</span> offset<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setEnd</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetEnd <span style="color: #339933;">+</span> offset<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        character <span style="color: #339933;">=</span> range.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setStart</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetStart <span style="color: #339933;">-</span> offset<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setEnd</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetEnd <span style="color: #339933;">-</span> offset<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>    
&nbsp;
    <span style="color: #000066; font-weight: bold;">return</span> character<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">/**
 * Returns a single word for the given event.
 */</span>
<span style="color: #003366; font-weight: bold;">function</span> getEventWord<span style="color: #009900;">&#40;</span>evt<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>evt.<span style="color: #660066;">rangeParent</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span>document.<span style="color: #660066;">createRange</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> range <span style="color: #339933;">=</span> document.<span style="color: #660066;">createRange</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    range.<span style="color: #660066;">setStart</span><span style="color: #009900;">&#40;</span>evt.<span style="color: #660066;">rangeParent</span><span style="color: #339933;">,</span> evt.<span style="color: #660066;">rangeOffset</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    range.<span style="color: #660066;">setEnd</span><span style="color: #009900;">&#40;</span>evt.<span style="color: #660066;">rangeParent</span><span style="color: #339933;">,</span> evt.<span style="color: #660066;">rangeOffset</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// the word ends when this characters appears</span>
    <span style="color: #003366; font-weight: bold;">var</span> stop_character_pattern <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^[\W]$/m</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// this &quot;overwrites&quot; some characters from the above pattern</span>
    <span style="color: #003366; font-weight: bold;">var</span> ignore_stop_character_pattern <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^['|\-]$/</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// I assume startOffset == endOffset so set 1 character selection ...</span>
    <span style="color: #003366; font-weight: bold;">var</span> originalOffsetStart <span style="color: #339933;">=</span> range.<span style="color: #660066;">startOffset</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> originalOffsetEnd <span style="color: #339933;">=</span> range.<span style="color: #660066;">startOffset</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// test:</span>
        range.<span style="color: #660066;">setStart</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetStart<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setEnd</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetEnd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// out of bounds</span>
        originalOffsetStart <span style="color: #339933;">-=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
        originalOffsetEnd <span style="color: #339933;">-=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setStart</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetStart<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setEnd</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> originalOffsetEnd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// First Step: Find left end of word:</span>
    <span style="color: #003366; font-weight: bold;">var</span> leftCharacterPos <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> iChar <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> iOffStart <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> iOffStart <span style="color: #339933;">&lt;=</span> originalOffsetStart<span style="color: #339933;">;</span> iOffStart<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        iChar <span style="color: #339933;">=</span> getRangeCharacter<span style="color: #009900;">&#40;</span>range<span style="color: #339933;">,</span> originalOffsetStart<span style="color: #339933;">,</span> originalOffsetEnd<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span> <span style="color: #339933;">*</span> iOffStart<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        leftCharacterPos <span style="color: #339933;">=</span> iOffStart<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>stop_character_pattern.<span style="color: #660066;">test</span><span style="color: #009900;">&#40;</span>iChar<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>ignore_stop_character_pattern.<span style="color: #660066;">test</span><span style="color: #009900;">&#40;</span>iChar<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// remove the stop character!</span>
            leftCharacterPos <span style="color: #339933;">-=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span> leftCharacterPos <span style="color: #339933;">=</span> originalOffsetStart <span style="color: #339933;">-</span> leftCharacterPos<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Last Step: Find right end of word:</span>
    <span style="color: #003366; font-weight: bold;">var</span> rightCharacterPos <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>iOffStart <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span> iOffStart<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        iChar <span style="color: #339933;">=</span> getRangeCharacter<span style="color: #009900;">&#40;</span>range<span style="color: #339933;">,</span> originalOffsetStart<span style="color: #339933;">,</span> originalOffsetEnd<span style="color: #339933;">,</span> iOffStart<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>stop_character_pattern.<span style="color: #660066;">test</span><span style="color: #009900;">&#40;</span>iChar<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>ignore_stop_character_pattern.<span style="color: #660066;">test</span><span style="color: #009900;">&#40;</span>iChar<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            rightCharacterPos <span style="color: #339933;">=</span> iOffStart <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span> rightCharacterPos <span style="color: #339933;">=</span> originalOffsetEnd <span style="color: #339933;">+</span> rightCharacterPos<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
        range.<span style="color: #660066;">setStart</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> leftCharacterPos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        range.<span style="color: #660066;">setEnd</span><span style="color: #009900;">&#40;</span>range.<span style="color: #660066;">startContainer</span><span style="color: #339933;">,</span> rightCharacterPos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>e1<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        range.<span style="color: #660066;">detach</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> retWord <span style="color: #339933;">=</span> range.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    range.<span style="color: #660066;">detach</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">return</span> retWord<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>Second: Translate Text with Google Translator</h3>
<p>This is very easy because Google provides an very easy to use <a href="http://code.google.com/apis/ajaxlanguage/documentation/#Examples">Ajax API</a> for this (attend the possible google user tracking!):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// read onMoveTranslate()</span>
<span style="color: #003366; font-weight: bold;">var</span> last_word <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> timeout <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> word_cache <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">/**
 * Translate text For onmousemove events.
 */</span>
<span style="color: #003366; font-weight: bold;">function</span> onMoveTranslate<span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// get element the translation should appear in:</span>
    <span style="color: #003366; font-weight: bold;">var</span> translation <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'translation'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> word <span style="color: #339933;">=</span> getEventWord<span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>word <span style="color: #339933;">||</span> word <span style="color: #339933;">==</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>word_cache<span style="color: #009900;">&#91;</span>word<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        translation.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> word_cache<span style="color: #009900;">&#91;</span>word<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//+&quot; (cached)&quot;;</span>
        <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>word <span style="color: #339933;">!=</span> last_word<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            window.<span style="color: #660066;">clearTimeout</span><span style="color: #009900;">&#40;</span>timeout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        translation.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'Translating ... '</span> <span style="color: #339933;">+</span> word<span style="color: #339933;">;</span>
        timeout <span style="color: #339933;">=</span> window.<span style="color: #660066;">setTimeout</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            google.<span style="color: #660066;">language</span>.<span style="color: #660066;">translate</span><span style="color: #009900;">&#40;</span>word<span style="color: #339933;">,</span> <span style="color: #3366CC;">'en'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'de'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>result.<span style="color: #660066;">error</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    translation.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> result.<span style="color: #660066;">translation</span><span style="color: #339933;">;</span>
                    word_cache<span style="color: #009900;">&#91;</span>word<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> result.<span style="color: #660066;">translation</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">800</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    last_word <span style="color: #339933;">=</span> word<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
google.<span style="color: #660066;">load</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;language&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>At last I assign the onMouseMove Event to the onMoveTranslate() function:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;div id=&quot;content&quot; onmousemove=&quot;onMoveTranslate(event);&quot;&gt;</pre></td></tr></table></div>

<p><a href="http://apoc.sixserv.org/translate_onmousemove.html">Here is an full Example for this.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2010/02/10/javascript-onmousemove-google-translation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mtget: ZDF Mediathek Download/Stream</title>
		<link>http://sixserv.org/2009/12/21/mtgetzdf-mediathek-downloadstream/</link>
		<comments>http://sixserv.org/2009/12/21/mtgetzdf-mediathek-downloadstream/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 08:54:41 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[mediathek]]></category>
		<category><![CDATA[web scraping]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=565</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_python.png" width="50" height="51" alt="" title="Python" /><br/>Nachdem die ZDF Mediathek nun ihr lang erwartetes relaunch &#8216;feiern&#8217; kann, habe ich mich daran gemacht mtget zu überarbeiten. Die neue, für Linux Anwender besonders interessante, &#8220;HTML Version&#8221;, macht, da ohne Flash, die ZDF Mediathek nun erstmals halbwegs benutzbar. =)
Die asx-Links fürs mms streaming werden jetzt auch nicht mehr versteckt, so im großen und ganzen [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_python.png" width="50" height="51" alt="" title="Python" /><br/><p>Nachdem die <a href="http://www.zdf.de/ZDFmediathek/hauptnavigation/startseite?flash=off">ZDF Mediathek</a> nun ihr <a href="http://sixserv.org/2009/05/12/zdf-mediathek-fail/">lang erwartetes</a> relaunch &#8216;feiern&#8217; kann, habe ich mich daran gemacht mtget zu überarbeiten. Die neue, für Linux Anwender besonders interessante, <a href="http://www.zdf.de/ZDFmediathek/hauptnavigation/startseite?flash=off">&#8220;HTML Version&#8221;</a>, macht, da ohne Flash, die ZDF Mediathek nun erstmals halbwegs benutzbar. =)</p>
<p>Die asx-Links fürs mms streaming werden jetzt auch nicht mehr versteckt, so im großen und ganzen also ein ziemlicher Fortschritt. Für die Nerds unter euch die dennoch gern eine Shell-Lösung hätten, pflege ich mtget trotzdem weiter.<br />
Bei der Gelegenheit habe ich mtget in Python komplett neu geschrieben. <a href="http://apoc.sixserv.org/code/mtget.py">Version 0.5</a> kommt ohne zusätzliche Libraries aus, es müssen lediglich Python(bei mir läuft 2.6) sowie die in CMD_STREAM und CMD_DOWNLOAD eingetragenen Programme(per default: mplayer) installiert sein. In der neuen Version werden erstmals Kanäle erkannt und können im interaktiven Modus(-i) ausgewählt werden, andernfalls wird ihnen automatisch gefolgt und die Einträge abgespielt. Anders als die vorigen Versionen lädt 0.5 nur die mms-Streams. <a href="http://apoc.sixserv.org/code/mtget.py">mtget.py</a>:</p>
<div id="attachment_585" class="wp-caption aligncenter" style="width: 500px"><img class="size-full wp-image-585" title="mtget.py: Screenshot" src="http://sixserv.org/wp-content/uploads/2009/12/mtget_screenshot.png" alt="mtget.py: Interaktive Auswahl der Videos und Kanäle" width="490" height="279" /><p class="wp-caption-text">mtget.py: Interaktive Auswahl der Videos und Kanäle</p></div>
<pre>ZDF Mediathek Download/Streaming Skript
v0.5 &lt;apoc@sixserv.org&gt; http://apoc.sixserv.org/
Stand: 2009-12-20

Syntax: ./mtget.py &lt;URL/ID&gt; [OPTIONS]
<pre>  &lt;URL/ID&gt;                   mediathek video/kanal url oder id
  -1                         qualitaet DSL 1000
  -2                         qualitaet DSL 2000 (Standard)
  -m, --mode &lt;d/s&gt;           download(d) oder streaming(s)
  -d, --dir &lt;directory&gt;      das verzeichnis wohin gespeichert werden soll(.)
  -t, --title                benutzt nicht den stream dateinamen sondern titel
  -s, --search &lt;topic&gt;       suche in der mediathek
  -l, --maxr &lt;max&gt;           wieviele ergebnisse verarbeiten(suche/kategorie)
  -c, --ignore-channel       ignoriert kanaele
      --no-colors            deaktiviert die kursiv und fettschrift
  -i                         interaktiv, auswahl der zu spielenden videos
  -v                         erweiterte ausgabe, zu debugging zwecken
  -h, --help                 zeigt diese hilfe</pre>
</pre>
<p>Mir sind übrigens noch zwei weitere Projekte bekannt die ebenfalls Mediathek streaming bieten: <a href="http://bb.xnull.de/projects/mtscrape/">mtscrape</a> und <a href="http://zdfmediathk.sourceforge.net/">zdfmediathk</a>.</p>
<p>Für Vorschläge, Bugreports und alles andere hinterlasst mir ein Kommentar oder schreibt eine eMail an <a href="mailto:apoc@sixserv.org">apoc@sixserv.org</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/12/21/mtgetzdf-mediathek-downloadstream/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Content Extraction Algorithmen: Density/CCB</title>
		<link>http://sixserv.org/2009/11/09/content-extraction-algorithmen-densityccb/</link>
		<comments>http://sixserv.org/2009/11/09/content-extraction-algorithmen-densityccb/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 19:31:09 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[ccb]]></category>
		<category><![CDATA[ce]]></category>
		<category><![CDATA[density]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=550</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_python.png" width="50" height="51" alt="" title="Python" /><br/>Im Artikel, &#8220;Web scraping mit Ruby/Mechanize&#8221; zeigte ich wie man Webseiten von einem Ruby Skript laden lässt und definierte Inhalte daraus extrahieren kann. Diese Verfahren, z.B.: Regular expression, XPath oder CSS Selektoren, funktionieren nur für Seiten deren Struktur während der Implementierung bekannt sind. Diesmal allerdings geht es um Algorithmen die den Hauptinhalt(z.B. den Text einer [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_python.png" width="50" height="51" alt="" title="Python" /><br/><p>Im Artikel, <a href="http://sixserv.org/2009/05/27/webscripting-mit-ruby-und-mechanize/">&#8220;Web scraping mit Ruby/Mechanize&#8221;</a> zeigte ich wie man Webseiten von einem Ruby Skript laden lässt und definierte Inhalte daraus extrahieren kann. Diese Verfahren, z.B.: <a href="http://en.wikipedia.org/wiki/Regular_expression">Regular expression</a>, <a href="http://en.wikipedia.org/wiki/XPath">XPath</a> oder <a href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets#Syntax">CSS Selektoren</a>, funktionieren nur für Seiten deren Struktur während der Implementierung bekannt sind. Diesmal allerdings geht es um Algorithmen die den Hauptinhalt(z.B. den Text einer Nachricht) von jeder beliebigen Seite erkennen und extrahieren können. Diese Möglichkeit ist vor allem für Suchmaschinen/Datamining oder für Anwendungen die die Lesbarkeit erhöhen wollen, z.B. für kleine Bildschirme(Handhelds) oder Screen Reader, interessant.</p>
<p>Auch wenn es ein recht neues Forschungsfeld der Informatik ist, gibt es schon einige Veröffentlichungen zu dem Thema. Für den Einstieg am Interessantesten ist wohl die Dissertation von <a href="http://www.informatik.uni-mainz.de/~gotti/publications.php">Thomas Gottron</a>, &#8220;<a href="http://ubm.opus.hbz-nrw.de/volltexte/2009/1859/pdf/diss.pdf">Content Extraction: Identifiying the Main Content in HTML Documents</a>&#8220;, die einen Überblick über die Algorithmen gibt, eine Möglichkeit der Evaluation beschreibt und einige neue Algorithmen einführt. Das erfolgversprechendste dieser Verfahren, der <a href="http://www.informatik.uni-mainz.de/~gotti/paper/TIR-2008.pdf "><strong>CCB</strong>(Content Code Blurring) Algorithmus</a> ist auch Thema dieses Artikels.</p>
<p>Einen weiteren interessanten Ansatz liefern Arias Moreno, Deschacht und Moens in Ihrem Paper &#8220;<a href="https://www2.cs.kuleuven.be/cwis/research/liir/publication_files/978AriasEtAl2009.pdf ">Language Independent Content Extraction from Web Pages</a>&#8221; deren Verfahren(<strong>Density</strong>) hier auch besprochen wird.</p>
<p>Natürlich kann man von keinem der Algorithmen Perfektion erwarten, dafür sind die Webseiten zu unterschiedlich strukturiert. Auch will ich nicht vergessen zu erwähnen das diese Algorithmen nur auf Seiten mit klar erkennbarem Hauptinhalt(Main Content) funktionieren, Weblogs z.B. verwirren so gut wie alle Verfahren die darauf Basieren die höchste &#8220;Text Konzentration&#8221; auf einer Seite zu finden, da die Kommentare unter dem Artikel nicht selten wesentlich umfangreicher als der Hauptinhalt sind(z.B. Slashdot).</p>
<p><strong>Content Code Blurring</strong> (<a href="http://apoc.sixserv.org/code/ccbce.py">Python Skript / Modul</a>)</p>
<p>Der CCB Algorithmus von Thomas Gottron stellt ein Verfahren dar, um die Teile einer HTML-Seite zu identifizieren die aus viel Text und nur wenigen Tags besteht. Dazu wird die Seite in eine Sequenz aus Tokens oder Zeichen aufgeteilt: Die TCCB Variante teilt die Sequenz in Tokens aus Tags oder Wörtern ein, sonst werden Zeichen unterschieden die sich innerhalb(Code) oder außerhalb(Inhalt/Content) eines Tags befinden. Der so entstandene Content Code Vektor(CCV) speichert für jeden Code ein 0 und für jeden Inhalt eine 1.</p>
<p>Jetzt wird der CCV verwischt(Blurring) dazu wird ein Gaussian Blur Filter verwendet, der im Prinzip einer Gaussian Distribution/<a href="http://en.wikipedia.org/wiki/Normal_Distribution#Definition">Normal Distribution</a> entspricht. Anders gesagt werden die Inhalts(1)-Elemente des CCV auf ihre Nachbar-Elemente verstreut oder verwischt. Dieser Vorgang wird n-mal wiederholt oder bis sich der Prozess normalisiert hat(wobei ich es leider nicht geschafft habe das zu implementieren(kA. woran das liegt, GERNE FEEDBACK!)). Meine Beispielimplementierung kann ein Diagramm des CCV &#8220;plotten&#8221;:</p>
<div id="attachment_554" class="wp-caption aligncenter" style="width: 725px"><img class="size-full wp-image-554" title="CCV Plot" src="http://sixserv.org/wp-content/uploads/2009/11/test.png" alt="Dieser Plot zeigt, dass man schon auf der richtigen Spur ist. Klar erkennbare Spitze wo der Hauptinhalt liegt." width="715" height="255" /><p class="wp-caption-text">Dieser Plot zeigt, dass man schon auf der richtigen Spur ist. Klar erkennbare Spitze wo der Hauptinhalt liegt.</p></div>
<p>Am Ende werden die Teile des CCV welche über einen bestimmten Schwellwert liegen mit ziemlicher Sicherheit zum Hauptinhalt der Seite gehören. (Im Diagramm sehr leicht zu erkennen.)</p>
<p>Der CCB Algorithmus funktioniert sehr gut und gilt als einer der besten Algorithmen für Content Extraction überhaupt. Ein Nachteil besteht darin das Teile der Seite die ebenfalls viel Text enthalten mitunter zum Hauptinhalt gezählt werden, auch wenn sich diese Bereiche weit entfernt vom eigentlichen Inhalt befinden.</p>
<p><strong>Density</strong> (<a href="http://apoc.sixserv.org/code/ce_density.rb">Ruby Beispiel</a>)</p>
<p>Der Density Algorithmus von Arias Moreno, Deschacht und Moens folgt einem ähnlichen Ansatz, die HTML-Seite wird durch einen (möglichst robusten) XML-Parser geparsed. Dann wird jeder (XML-)Node des Dokuments der Text enthält an den letzten String eines Arrays angehängt. Handelt es sich bei dem Node um einen HTML-Tag der die Struktur des Dokuments verändert(z.B. p, table, br, div, h1-6, li usw.) wird das Array um einen leeren String erweitert.</p>
<p>Wurde dieses Array fertig erstellt, wird ein Algorithmus angewandt, der den Bereich mit der größten Textdichte im Array zu bestimmen versucht(siehe Paper). Am Ende wird das Array nur noch sortiert und das Ergebnis steht als Plaintext fest.</p>
<p>Density arbeitet in der Praxis sehr gut, jedoch wird das Ergebnis sehr stark von den beiden Parametern beeinflusst, die den Algorithmus zum erkennen des Bereichs einstellen(besonders wieviele Absätze am Stück erkannt werden).</p>
<p><strong>Update:</strong> Ich habe eine <a href="http://apoc.sixserv.org/code/ce_density.rb">Implementierung</a> für Density in Ruby eingefügt, er versucht den Hauptinhalt dieses Artikels zu extrahieren <img src='http://sixserv.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/11/09/content-extraction-algorithmen-densityccb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zensursula: Teil 2 &#8211; Cleanfeed, DNS, DPI</title>
		<link>http://sixserv.org/2009/10/05/zensursula-teil-2-cleanfeed-dns-dpi/</link>
		<comments>http://sixserv.org/2009/10/05/zensursula-teil-2-cleanfeed-dns-dpi/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 15:32:52 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Censorship]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[vpn]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=500</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_censorship.png" width="67" height="51" alt="" title="Censorship" /><br/>Die mit Lügen und Erpressung der Provider gegen alle Vernunft durchgepeitschte, grundgesetzwidrige unkontrollierbare deutsche Zensurinfrastruktur wird gerade vom &#8220;zuständigen&#8221; BKA in aller Heimlichkeit geplant und wird genauso heimlich von den Providern implementiert werden. Das die erstmals angedachten DNS-Sperren vollständig wirkungslos sind, darüber sind sich wohl alle einig, genauso eindeutig ist es wohl das die DNS-Sperren [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_censorship.png" width="67" height="51" alt="" title="Censorship" /><br/><p>Die mit Lügen und Erpressung der Provider gegen alle Vernunft durchgepeitschte, grundgesetzwidrige unkontrollierbare deutsche Zensurinfrastruktur wird gerade vom &#8220;zuständigen&#8221; BKA in aller <a href="http://www.heise.de/netze/meldung/Umsetzungsvorgaben-fuer-Web-Sperren-sollen-geheim-bleiben-Update-753549.html">Heimlichkeit geplant</a> und wird genauso heimlich von den Providern implementiert werden. Das die erstmals angedachten DNS-Sperren vollständig wirkungslos sind, darüber sind sich wohl alle einig, genauso eindeutig ist es wohl das die DNS-Sperren nur den Einstieg hin zur Schaffung eines ausgefeilten Zensursystems mit Vorbild der <a href="http://www.greatfirewallofchina.org/">Great Firewall of China</a> sein wird. Schon jetzt vermuten einige das ein <a href="http://en.wikipedia.org/wiki/Cleanfeed_%28content_blocking_system%29">Cleanfeed</a> Modell nach britischen Vorbild <a href="http://www.netzpolitik.org/2009/zensursula-richtlinie-fuer-web-sperren-sollen-geheim-bleiben/">geplant ist</a>.<br />
Die Befristung auf 3 Jahre hilft natürlich auch nicht, entweder nach 3 Jahren stellt sich heraus, das es nur wenig gegen &#8220;Kinderpornographie&#8221; geholfen hat, dann muss noch mehr und tief greifender gesperrt werden, oder die Verbrechensstatistik (die im übrigen ohnehin vom BKA &#8220;erstellt&#8221; wird) geht zurück, dann war es ein Erfolg und muss genauso weitergeführt werden.</p>
<div id="attachment_504" class="wp-caption alignleft" style="width: 310px"><a href="/wp-content/uploads/2009/10/URL_Filtering.png" rel="lightbox[500]"><img class="size-medium wp-image-504" title="URL_Filtering" src="/wp-content/uploads/2009/10/URL_Filtering-300x51.png" alt="bla" width="300" height="51" /></a><p class="wp-caption-text">Cleanfeed - Bildquelle: <a href='http://en.wikipedia.org/wiki/File:URL_Filtering_%282%29.svg'>Wikimedia Commons</a></p></div>
<p>Das <strong>Cleanfeed</strong> System wird von Providern in England eingesetzt um z.B.: bestimmte <a href="http://www.redorbit.com/news/technology/1607705/uk_blocks_wikipedia_page_over_child_image/">Wikipedia Artikel zu blockieren</a>. Welche wahrscheinlich regimekritischen Seiten noch so alles gesperrt werden weiß man natürlich nicht, da die geheimen Listen(der <a href="http://en.wikipedia.org/wiki/Internet_Watch_Foundation">IWF</a>), natürlich nicht unabhängig kontrolliert werden. Cleanfeed filtert nach der IP und URL, was durch eine Kombination aus konventionellen IP-Filtern und Proxy-Servern ermöglicht wird. Zunächst wird der Traffic nur nach IP-Adressen gefiltert, bestimmte Verbindungen werden schon hier blockiert, andernfalls wird der fragwürdige Traffic durch ein Arsenal an transparenten Proxy-Servern geleitet(<a href="http://de.wikipedia.org/wiki/Man-in-the-middle-Angriff">Man-in-the-middle-Angriff</a> auf HTTP) die mit einer Blacklist ausgerüstet bestimmte URLs blockieren.</p>
<p>In China z.B. wird noch einen Schritt weiter gegangen, so wird jedes IP-Paket von DPI-Hardware genau untersucht, enthält es unerwünschte Suchbegriffe oder Inhalte wird von dem zensierenden Backbone TCP-RST-Pakete gesendet, die so die fragliche TCP-Verbindung sofort beendet. So implementiert die chinesische Suchmaschine <a href="http://de.wikipedia.org/wiki/Baidu">Baidu</a> dies bereits auf Server-Seite. Wer auf <a href="http://www.baidu.com/">Baidu.com</a> nach &#8220;Falun Gong&#8221; sucht, dessen Verbindung wird für einige Minuten gesperrt.<br />
Beim <strong><a href="http://en.wikipedia.org/wiki/Deep_packet_inspection">Deep Packet Inspection</a></strong> wird jedes vorbeikommende Paket auseinandergenommen, so kann beispielsweise festgestellt werden ob es sich um eine HTTP Verbindung handelt und welche URL angefordert wird oder welche Daten gesendet werden. Das allein ist natürlich ein krasser verstoß gegen die Netzneutralität sowie gegen jedes noch so aufgeweichtes Fernmeldegeheimnis. Zum Vergleich, das wäre wie wenn die Post jeden Brief unbemerkt öffnet und nach bestimmten Stichworten durchsucht. Wenn es schon unbedingt DPI seien muss, dann wenigstens Open Source, dachten sich wahrscheinlich die Entwickler des <a href="http://www.opendpi.org/">OpenDPI</a> Projektes <img src='http://sixserv.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Im letzten <a href="http://sixserv.org/2009/06/27/zensursula-teil-1-dns/">Zensursula-Artikel</a> habe ich mich mit den DNS-Filtern beschäftigt, insbesondere wie man einen eigenen DNS-Cache-Server betreibt der die Zensur über DNS verhindert. Wie erwähnt handelt es sich dabei nur um den Einstieg, die Einführung von Cleanfeed/DPI kann die Zensur wieder akut werden lassen, selbst mit eigenem DNS-Server. Wie es technisch geht hat jüngst <a href="http://www.zdnet.de/sicherheit_in_der_praxis_sperre_von_freien_dns_servern_so_umgeht_man_die_blockade_story-39001543-41502966-1.htm">Vodafone in ihrem UMTS Netz</a> gezeigt, sie fangen jede Anfrage über Port 53 ab und leiten sie an ihre eigenen DNS-Server weiter.</p>
<p>Das Einzige wirksame Mittel gegen diese fortgeschrittenen Zensur Bemühungen, ist es den eigenen Traffic möglichst zu verschleiern, im einfacheren Fall seinen Traffic verschlüsselt über Rechner im Ausland zu leiten, bspw. über <strong>HTTP oder Socks4/5-Proxy-Server</strong>. Die Meisten Zensur-Regime sperren deshalb ebenfalls bekannte Ausländische Proxy bzw. Anonymisierungs-Dienste(Socks, VPN-Dienstleister oder Tor-Nodes) auf IP-Ebene.<br />
Mittlerweile gibt es eine ganze Flut von VPN-Providern die bezahlte Zugänge zu Ausländischen VPN-Servern bereitstellen, <a href="http://sixserv.org/2009/01/24/ivacy-vpn-unter-linux-pptp-und-socks5">Ivacy war hier auch schon Thema</a>. Explizit erwähnen will ich hier außerdem <a href="http://www.perfect-privacy.com/">Perfect-Privacy</a> die zwar etwas teurer sind, aber dafür sehr schnell und Zugriff zu über 20 weltweit verteilten Servern bieten. </p>
<p>Auf <a href="http://filesharefreak.com/2008/10/18/total-anonymity-a-list-of-vpn-service-providers/">FileShareFreak</a> und <a href="http://www.daten-speicherung.de/index.php/test-internet-anonymisierungsdienste/">Daten-Speicherung.de</a> gibt es Listen von VPN-Providern. Wem es statt einer Zensur zu umgehen, um wirkliche Anonymität geht, reichen diese Anbieter nicht aus. Nur ein <a href="http://de.wikipedia.org/wiki/Onion_Routing">Onion Routing</a> kann wirkliche Anonymität gewährleisten, z.B.: <a href="http://de.wikipedia.org/wiki/Tor_(Netzwerk)">Tor</a> oder <a href="http://de.wikipedia.org/wiki/Java_Anon_Proxy">JAP/JonDo</a>. Diese haben natürlich den Nachteil, extrem Langsam und unzuverlässig zu sein. Daneben gibt es mit <a href="https://xerobank.com/">Xerobank</a> einen Bezahl-Anbieter für schnelles Onion Routing.</p>
<p><strong>Update:</strong> Auf ZDNet gibt es einen guten <a href="http://www.zdnet.de/sicherheits_analysen_internet_per_umts_so_faelschen_deutsche_provider_webinhalte_story-39001544-41515603-1.htm">Artikel</a> darüber, wie weit die DPI-Manipulationen bei den UMTS-Anbietern, wie Vodafone mittlerweile gehen. (<a href="http://www.netzpolitik.org/2009/dpi-so-faelschen-deutsche-provider-webinhalte/">via Netzpolitik</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/10/05/zensursula-teil-2-cleanfeed-dns-dpi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>implementing bittorrent &#8211; DHT  (teil 3)</title>
		<link>http://sixserv.org/2009/10/02/implementing-bittorrent-dht-teil-3/</link>
		<comments>http://sixserv.org/2009/10/02/implementing-bittorrent-dht-teil-3/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 16:35:16 +0000</pubDate>
		<dc:creator>nks</dc:creator>
				<category><![CDATA[Torrent]]></category>
		<category><![CDATA[bittorrent]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[dht]]></category>
		<category><![CDATA[distributed hash table]]></category>
		<category><![CDATA[hash tale]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[p2p]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=466</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_bittorrent.png" width="50" height="51" alt="" title="Torrent" /><br/>Eigentlich wollte ich ja was über den BitTorrent Message-Flow schreiben, aber aus aktuellem Anlass gibt es heute einen "kleinen" Artikel über DHT.

DHT

Aus gegebenem Anlass schreibe ich nun etwas früher als geplant über DHT. Die ThePirateBay-Tracker sind nun schon etwas länger Down, es sind zwar etliche Ersatz-Tracker aus dem Boden gesprießt, aber meiner Meinung nach ist das dezentrale Tracking nun an der Reihe. Die Tracker waren bis jetzt einer der grössten Angriffs/Schwachpunkte der BitTorrent Technologie/ des BitTorrent Protokolls.
Doch das muss nicht so sein, denn es gibt ja DHT (BEP005). Ich will mich hier mal etwas näher mit DHT beschäftigen und das DHT Protokoll näher erklären.

Die Technologie hinter DHT im BitTorrent-Protokoll basiert auf Kademlia. Kademlia wurde von Petar Maymounkov und David Mazières entwickelt und "implementiert" bzw spezifiziert Distributed Hastables in P2P-Netzen. Verschaffen wir uns erstmal einen kleinen Überblick über Kademlia.

BEP005 spezifiziert das die Daten per UDP übertragen werden. Zuerst generiert der Client eine Node ID, diese wird genauso wie der BitTorrent Infohash errechnet, bzw nutzt den selben Bit-raum (160Bit). Danach beginnt das Bootstrapping, der Client muss sich ja erstmal im DHT zurechtfinden und einen anderen Client finden dieser Teilt dann weitere IPs mit. Meist ist die erste Node "router.bittorrent.com" da ein Scannen durch die eigene IP-Range oder willkürliches suchen nach anderen Nodes nicht so erfolgversprechend ist.
Zur Indizierung von BitTorrent-Hashes wie es ein Tracker macht trägt bei DHT jeder Peer/Node bei.
Wenn wir nun einen bestimmten Hash suchen kann die Entfernung zu diesem Hash ausgerechnet werden. Dafür werden entweder Node IDs und Node IDs verglichen, oder Infohashes und Node IDs, durch den "Algorithmus" lässt sich die "nähe" der Node ID zur gesuchten ID (Infohash oder Node ID) errechnen. Die Routing Tabelle die der Client nun erstellt wird immer detaillierter je näher wir an den gesuchten ID-Wert kommen und die Node mit der gewünschten Information gefunden haben. Jede Node hat "Kontaktdaten" zu den Nodes mit "nahen" IDs.]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_bittorrent.png" width="50" height="51" alt="" title="Torrent" /><br/><p>Eigentlich wollte ich ja was über den BitTorrent Message-Flow schreiben, aber aus aktuellem Anlass gibt es heute einen &#8220;kleinen&#8221; Artikel über DHT.</p>
<p><strong>DHT</strong></p>
<p>Aus gegebenem Anlass schreibe ich nun etwas früher als geplant über DHT. Die ThePirateBay-Tracker sind nun schon etwas länger Down, es sind zwar etliche Ersatz-Tracker aus dem Boden gesprossen, aber meiner Meinung nach ist das dezentrale Tracking nun an der Reihe. Die Tracker waren bis jetzt einer der grössten Angriffs/Schwachpunkte der BitTorrent Technologie/ des BitTorrent Protokolls.<br />
Doch das muss nicht so sein, denn es gibt ja DHT (<a href="http://bittorrent.org/beps/bep_0005.html">BEP005</a>).  Ich will mich hier mal etwas näher mit DHT beschäftigen und das DHT Protokoll näher erklären.</p>
<p>Die Technologie hinter DHT im BitTorrent-Protokoll basiert auf Kademlia. Kademlia wurde von Petar Maymounkov und David Mazières entwickelt und &#8220;implementiert&#8221; bzw spezifiziert Distributed Hashtables in P2P-Netzen. Verschaffen wir uns erstmal einen kleinen Überblick über Kademlia.</p>
<p>BEP005 spezifiziert das die Daten per UDP übertragen werden. Zuerst generiert der Client eine Node ID, diese wird genauso wie der BitTorrent Infohash errechnet, bzw nutzt den selben Bit-raum (160Bit). Danach beginnt das Bootstrapping, der Client muss sich ja erstmal im DHT zurechtfinden und einen anderen Client finden dieser Teilt dann weitere IPs mit. Meist ist die erste Node &#8220;router.bittorrent.com&#8221; da ein Scannen durch die eigene IP-Range oder willkürliches suchen nach anderen Nodes nicht so erfolgversprechend ist.<br />
Zur Indizierung von BitTorrent-Hashes wie es ein Tracker macht trägt bei DHT jeder Peer/Node bei.<br />
Wenn wir nun einen bestimmten Hash suchen kann die Entfernung zu diesem Hash ausgerechnet werden. Dafür werden entweder Node IDs und Node IDs verglichen, oder Infohashes und Node IDs, durch den &#8220;Algorithmus&#8221; lässt sich die &#8220;nähe&#8221; der Node ID zur gesuchten ID (Infohash oder Node ID) errechnen. Die Routing Tabelle die der Client nun erstellt wird immer detaillierter je näher wir an den gesuchten ID-Wert kommen und die Node mit der gewünschten Information gefunden haben. Jede Node hat &#8220;Kontaktdaten&#8221; zu den Nodes mit &#8220;nahen&#8221; IDs.</p>
<p>Die Distanz zwischen 2 IDs wird per XOR berechnet:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">distanz<span style="color: #7a0874; font-weight: bold;">&#40;</span>A,B<span style="color: #7a0874; font-weight: bold;">&#41;</span> = <span style="color: #000000; font-weight: bold;">|</span>A xor B<span style="color: #000000; font-weight: bold;">|</span></pre></div></div>

<p>Je kleiner das Ergebnis desto näher Liegen sich A und B.</p>
<p>Wenn nun eine Node (im DHT) Peers (für BitTorrent) finden will passiert folgendes:<br />
Ich gehe davon aus das das Bootstrapping schon fertig ist, wir also ein  Paar Nodes schon in unserer Routing-Tabelle haben. Unser Client nimmt nun den Infohash aus der Torrent-File.  Wir nehmen Beispielsweise den Hash<br />
<strong> 362b0a1151013916896a9c98b52e0ead803c4ac3</strong> (ubuntu-7.10-alternate-hppa.iso). Unser Client wird die Node mit dem  geringstem Abstand zum Infohash nun Kontaktieren und diese Node nach  Peer-Kontaktdaten Fragen. Wenn diese Node Peer-Kontaktdaten besitzt werden diese zu unserem Client übermittelt und dieser baut dann über das BitTorrent-Protokoll eine Verbindung zum Peer auf. Wenn die Node keine Peer-Kontaktdaten hat wird sie uns Kontaktdaten zu den Nodes aus ihrer Routing-Tabelle geben die am Nächsten an unserer ID liegen, und so weiter und so fort! <img src='http://sixserv.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Die Antwort der Nodes auf die Anfrage nach Peers zu einem Infohash beinhaltet immer einen &#8220;token&#8221;. Wenn wir nun dem Node von dem wir die Peer-Kontaktdaten bekommen haben mitteilen wollen (wie beim Tracker ein sogenannter &#8220;announce&#8221;), müssen wir dem Node neben dem Announce auch den Token schicken den wir zuvor<br />
von ihm erhalten haben.<br />
Es liegt auf der Hand das dies eine Sicherheitsmaßnahme ist, damit nicht irgendwelche unbekannten Hosts (Bots von der MI) den DHT verseuchen. Die BEP005 spezifiziert das die Tokens alle 5 Minuten neu generiert  werden, sie bestehen aus einem SHA1-Hashes auf die IP Adresse verknüpft mit einem Salt (welches alle 5 Minuten wechselt).</p>
<p><strong>Routing</strong><br />
Kommen wir nun zum Aufbau der Routing Tabelle unseres Nodes. Die Routing Tabelle ist beinhaltet alle Bekannten Nodes die noch errechbar sind (das wird in einem Zeitraum von 15 Minuten getan) und diese Nodes dienen als Startpunkte für neue anfragen im DHT.</p>
<p>Die Nodes in unserer Routing Tabelle werden je nach ihrer Erreichbarkeit eingestuft. Die Erreichbarkeit jeder Node wird alle 15 Minuten überprüft. Eine Node wird als &#8220;good&#8221; eingestuft wenn sie uns eine Anfrage geschickt oder beantwortet hat innerhalb der letzten 15 Minuten. Wenn eine Node innerhalb von 15 Minuten nicht aktiv war wird sie  &#8220;questionable&#8221; also Fragwürdig eingestuft. Ein Node wird als &#8220;bad&#8221; eingestuft wenn er auf mehrere Anfragen nicht geantwortet hat. Unsere Routing-Tabelle sollte nur &#8220;good&#8221;-Einträge enthalten.</p>
<p>Die Routing Tabelle deckt den kompletten Raum an möglichen IDs ab (von 0 bis zu 2^160). Die Routing-Tabelle ist in &#8220;Buckets&#8221; (Eimer) unterteilt. Eine leere Routing-Tabelle enthält einen Bucket mit dem ID-Raum von 0 (min) bis 2^169 (max). Wenn wir nun eine Node mit der hypothetischen ID &#8220;A&#8221; (normal ist die ID natürlich 20byte lang wie beim Infohash) dann wird diese in einen Bucket eingefügt der min &lt; A &lt; max ist. Also in einem Bereich bei dem<br />
min kleiner als A ist und A kleiner als max <img src='http://sixserv.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /><br />
In einer leeren Routing-Tabelle ist nur ein Bucket also passen in diesen Bucket alle möglichen IDs rein. Allerdings kann ein Bucket nur K verschiedene Einträge enthalten, im Moment ist K=8. Wenn der Bucket voll mit &#8220;good&#8221;-Nodes ist, werden keine Nodes mehr hinzugefügt &#8211; AUßER die eigene Node ID fällt in den Bereich, in diesem Fall wird der Bucket durch zwei neue Buckets ersetzt und die Nodes aus dem Vorherigem Bucket werden auf die zwei neuen Buckets aufgeteilt. Diese zwei Buckets könnten bei einer Routing-Tabelle mit nur einem Bucket dann jeweils die Bereiche vor und nach unserer ID abdecken (min/max werte).</p>
<p>Jeder Bucket sollte (das ist natürlich jedem selbst überlassen, wenn man es denn Implementiert) eine &#8220;last changed&#8221; Eigenschaft haben um die &#8220;frische&#8221; des Buckets ablesen zu können. Auch hier sollte alle 15 Minuten die Erreichbarkeit der enthaltenen Nodes überprüft werden. Laut BEP005 wird dies folgendermaßen gemacht:<br />
Eine zufällig ausgewählte ID aus dem Bereich des Buckets (min/max) wird mit einer &#8220;find_nodes&#8221; (dazu weiter unten im Protokoll-Bereich mehr) Anfrage kontaktiert &#8211; bei Antwort ist die Node noch zu gebrauchen, wenn<br />
nicht sollte die Node aus dem Bucket entfernt werden. Wenn eine Node Anfragen von anderen Nodes nicht beantworten kann, z.B. wegen schlechten Router-Settings, dann sollte Sie ihre Buckets öfter Auffrischen als eine Node die auf Anfragen antworten kann, den eine solche Node erhält ja eh immer wieder neue Node IDs.<br />
Die Node sollte zudem versuchen ihr selbst nahe liegende Nodes zu finden.</p>
<p><strong>BitTorrent Protokoll</strong></p>
<p>Wenn unser BitTorrent-Client DHT unterstützt, wird bei den Protokoll-Flags im Handshake das letzte Byte gesetzt. Wenn nun ein anderer Peer uns beim Handshake das er DHT Supported, senden wir ihm mit der PORT-Message des BitTorrent-Protokolls unseren UDP-Port auf dem unsere DHT-Implementierung lauscht. Die DHT-Implementierung Pingt dann die neue Node und wenn eine Antwort kommt wird diese nach den oben definierten Regeln in einen Bucket eingefügt oder auch nicht (bei keiner Antwort).</p>
<p><strong>Torrent File</strong></p>
<p>Die Torrent-File enthält keine &#8220;announce&#8221;-URL mehr, sondern einen &#8220;nodes&#8221;-Key. Dieses Nodes Dictionary enthält die K (K=8) nähsten bekannten Nodes von dem Client der die .torrent-File erstellt hat. Oder halt eine Liste mit K  bekannten &#8220;good&#8221;-Nodes. Das Nodes-Dictionary ist wie folgt aufgebaut:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">nodes = <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #ff0000;">&quot;&quot;</span>,<span style="color: #7a0874; font-weight: bold;">&#93;</span>, <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #ff0000;">&quot;&quot;</span>,<span style="color: #7a0874; font-weight: bold;">&#93;</span>, ...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
nodes = <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #ff0000;">&quot;127.0.0.1&quot;</span>, <span style="color: #000000;">6881</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>, <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #ff0000;">&quot;your.router.node&quot;</span>, <span style="color: #000000;">4804</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

<p><strong>Protokolle</strong></p>
<p><strong>Kademlia RPC Protololl</strong></p>
<p>KRPC ist relativ schnelle und einfach erklärt. Die Einzelnen Messages sind wie bei BitTorrent üblich BEncoded. Auf einen Request kommt eine Antwort/Response. Es gibt drei Message-Typen: query, reponse und error.<br />
Beim DHT-Protokoll sind es vier: ping, find_node, get_peers und announce_peer. Eine KPRC-Message besteht aus einem Dictionary mit zwei Keys, sowie zusätzlich je nach Message-Typ zusätzliche Felder.<br />
Der Key &#8220;t&#8221; beinhaltet die &#8220;transaction id&#8221;, die &#8220;tansaction id&#8221; wird beim Query errechnet und dient dazu Anfragen und Antworten zuzuordnen. Sie besteht meistens nur aus 2 Buchstaben, da diese vollkommen ausreichen um eine große Anzahl von Anfragen abzudecken.<br />
Der andere Key ist &#8220;y&#8221; und beinhaltet als Wert nur einen einzigen Buchstaben:</p>
<ul>
<li> q: query</li>
<li>r: response</li>
<li>e: error</li>
</ul>
<p>Um die Kontaktdaten von Peers zu übertragen werden diese  Kodiert. Hier kommt die selbe Kodierung wie beim Compact-Encoding bei BitTorrent zum Einsatz, ein 6-Byte String &#8211; wobei die ersten 4 Byte die IP repräsentieren und die letzten 2 den Port.<br />
Um die Kontaktdaten von anderen Nodes zu übertragen werden diese ebenfalls Kodiert, dies geschieht jedoch mit dem &#8220;Compact Node Encoding&#8221;. Hier ist es ein 26-Byte String. Die ersten 20byte enthalten die Node ID die restlichen 6 sind die Compact-Encodierte IP und der Port wie oben.</p>
<p><strong>Queries/Anfragen</strong><br />
Der &#8220;y&#8221; Key enthält als Wert &#8220;q&#8221; wie weiter oben schon erklärt. Zusätzlich noch die die zwei Keys &#8220;a&#8221; und &#8220;q&#8221;.</p>
<ul>
<li> q: enthält den Methodennamen des Queries (DHT Protokoll z.B. Ping)</li>
<li> a: enthält die Argumente</li>
</ul>
<p><strong>Responses/Antworten</strong><br />
Der &#8220;y&#8221; Key enthält hier den Wert &#8220;r&#8221; für Response.<br />
Zusätzlich enthält diese Message den Key &#8220;r&#8221;:</p>
<ul>
<li> r: ist ein Dictionary mit den Ergebnissen der Anfrage</li>
</ul>
<p><strong>Errors/Fehler</strong><br />
Der &#8220;y&#8221; Key enthält den Key &#8220;e&#8221; für Error.</p>
<ul>
<li> e: enthält eine Liste:
<ul>
<li>das erste Element der Liste enthält den Fehler Code</li>
<li>das zweite Element die Fehlermeldung</li>
</ul>
</li>
</ul>
<p>Mögliche Fehler und ihre Entsprechenden Messages:</p>
<table border="1px">
<tbody>
<tr>
<th>Code</th>
<th>Beschreibung</th>
</tr>
<tr>
<th>201</th>
<th>Generic Error</th>
</tr>
<tr>
<th>202</th>
<th>Server Error</th>
</tr>
<tr>
<th>203</th>
<th>Protocol Error, such as a malformed packet, invalid arguments, or bad token</th>
</tr>
<tr>
<th>204</th>
<th>Method Unknown</th>
</tr>
</tbody>
</table>
<p>Beispielhaftes Error Packet aus BEP005:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">generic error = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;e&quot;</span>, <span style="color: #ff0000;">&quot;e&quot;</span>:<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">201</span>, <span style="color: #ff0000;">&quot;A Generic Error Ocurred&quot;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:eli201e23:A Generic Error Ocurrede1:t2:aa1:y1:ee</pre></div></div>

<p><strong>DHT Queries</strong></p>
<p>Bei den DHT Anfragen enthält jeder Query einen &#8220;id&#8221;-Dictionary als Argument, neben etwaigen anderen Argumenten, welcher die Node ID der anfragenden Node beinhaltet (20-Byte String in Network Byte<br />
Order) die Antworten enthalten natürlich die Node ID der antwortenden Node.</p>
<p>Hier die Möglichen Queries:</p>
<p><strong>ping</strong><br />
Der Key &#8220;q&#8221; für den Query-Typ beinhaltet hier den Wert &#8220;ping&#8221;. Der Key &#8220;a&#8221; für die Argumente enthält einen Dictionary mit dem Key &#8220;id&#8221; und als Wert wie oben schon erklärt die Node ID in Network Byte Order.</p>
<p>Example Packets aus BEP005:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ping</span> Query = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;q&quot;</span>, <span style="color: #ff0000;">&quot;q&quot;</span>:<span style="color: #ff0000;">&quot;ping&quot;</span>, <span style="color: #ff0000;">&quot;a&quot;</span>:<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;abcdefghij0123456789&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe
&nbsp;
Response = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;r&quot;</span>, <span style="color: #ff0000;">&quot;r&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;mnopqrstuvwxyz123456&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re</pre></div></div>

<p><strong>find_node:</strong><br />
Dieser Query wird benutzt um die Kontaktinformationen zu einer bestimmten Node anhand ihrer ID herauszufinden. Der &#8220;q&#8221;-Key enthält hier logischerweise &#8220;find_node&#8221;.<br />
Die Argumente im &#8220;a&#8221;-Key enthalten wie immer die eigene Node ID und hier noch das Target-Dictionary welches folgende Keys enthält:</p>
<ul>
<li>&#8220;target&#8221;: 	ID der gesuchten Node</li>
</ul>
<p>Als Antwort auf einen &#8220;find_node&#8221;-Query sollte die Antwort einen Key namens &#8220;nodes&#8221; enthalten der die Compact-Encoded-Node Informationen der gesuchten Node oder 8 (K) der nähsten bekannten &#8220;good&#8221;-Nodes enthalten.</p>
<p>Beispiel aus BEP005:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">find_node Query =<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;q&quot;</span>, <span style="color: #ff0000;">&quot;q&quot;</span>:<span style="color: #ff0000;">&quot;find_node&quot;</span>,<span style="color: #ff0000;">&quot;a&quot;</span>:<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;abcdefghij0123456789&quot;</span>,<span style="color: #ff0000;">&quot;target&quot;</span>:<span style="color: #ff0000;">&quot;mnopqrstuvwxyz123456&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe
&nbsp;
Response = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;r&quot;</span>, <span style="color: #ff0000;">&quot;r&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;0123456789abcdefghij&quot;</span>, <span style="color: #ff0000;">&quot;nodes&quot;</span>: <span style="color: #ff0000;">&quot;def456...&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re</pre></div></div>

<p><strong>get_peers:</strong><br />
Mit diesem Query erhält man Peers für den Torrent Download. &#8220;q&#8221; entspricht hier &#8220;get_peers&#8221;. Die Argumente sind &#8220;id&#8221; mit der Node ID und &#8220;info_hash&#8221; mit dem Infohash des Torrents. Die Antwort enthält den Key &#8220;values&#8221; der eine Liste von Strings enthält die entweder Compact-Encoded IP der Peers enthält, oder wenn keine Peers bekannt sind: einen Key &#8220;nodes&#8221; der eine Liste mit 8 (K) Nodes im Compact-Encoded Format enthält. In jedem Fall wird bei der Antwort ein Key &#8220;token&#8221; übertragen (der Token wird bei einem &#8220;announce&#8221; gebraucht).</p>
<p>Beispiele aus BEP005:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">get_peers Query = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;q&quot;</span>, <span style="color: #ff0000;">&quot;q&quot;</span>:<span style="color: #ff0000;">&quot;get_peers&quot;</span>, <span style="color: #ff0000;">&quot;a&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;abcdefghij0123456789&quot;</span>, <span style="color: #ff0000;">&quot;info_hash&quot;</span>:<span style="color: #ff0000;">&quot;mnopqrstuvwxyz123456&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe
&nbsp;
Response with peers = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;r&quot;</span>, <span style="color: #ff0000;">&quot;r&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;abcdefghij0123456789&quot;</span>, <span style="color: #ff0000;">&quot;token&quot;</span>:<span style="color: #ff0000;">&quot;aoeusnth&quot;</span>, <span style="color: #ff0000;">&quot;values&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #ff0000;">&quot;axje.u&quot;</span>, <span style="color: #ff0000;">&quot;idhtnm&quot;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re
&nbsp;
Response with closest nodes = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;r&quot;</span>, <span style="color: #ff0000;">&quot;r&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;abcdefghij0123456789&quot;</span>, <span style="color: #ff0000;">&quot;token&quot;</span>:<span style="color: #ff0000;">&quot;aoeusnth&quot;</span>, <span style="color: #ff0000;">&quot;nodes&quot;</span>: <span style="color: #ff0000;">&quot;def456...&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re</pre></div></div>

<p><strong>announce_peer:</strong><br />
Der &#8220;q&#8221; Key enthält logischerweise den String &#8220;announce_peer&#8221;. Dazu kommen noch 4 Argumente in &#8220;a&#8221;, die da wären:</p>
<ul>
<li> id: Node ID</li>
<li> info_hash: Infohash des Torrents</li>
<li> port: BitTorrent Client Port (zb 6881)</li>
<li> token: der token der beim vorherigem query nach peers vomentsprechendem Node gesendet wurde (dem Node welches usn die Peers geschickt hat)</li>
</ul>
<p>Beispiel aus BEP005:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">announce_peers Query = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;q&quot;</span>, <span style="color: #ff0000;">&quot;q&quot;</span>:<span style="color: #ff0000;">&quot;announce_peer&quot;</span>, <span style="color: #ff0000;">&quot;a&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;abcdefghij0123456789&quot;</span>, <span style="color: #ff0000;">&quot;info_hash&quot;</span>:<span style="color: #ff0000;">&quot;mnopqrstuvwxyz123456&quot;</span>, <span style="color: #ff0000;">&quot;port&quot;</span>: <span style="color: #000000;">6881</span>, <span style="color: #ff0000;">&quot;token&quot;</span>: <span style="color: #ff0000;">&quot;aoeusnth&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe
&nbsp;
Response = <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;t&quot;</span>:<span style="color: #ff0000;">&quot;aa&quot;</span>, <span style="color: #ff0000;">&quot;y&quot;</span>:<span style="color: #ff0000;">&quot;r&quot;</span>, <span style="color: #ff0000;">&quot;r&quot;</span>: <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">&quot;id&quot;</span>:<span style="color: #ff0000;">&quot;mnopqrstuvwxyz123456&quot;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re</pre></div></div>

<p>Ich hoffe das war ein Verständlicher &#8220;kleiner&#8221; Überblick uber DHT im BitTorrent-Protokoll. Und im naechstem teil gehts dann ueber den Message-Flow im BitTorrent-Protokoll xxD Bevor wir dann auch zu anfassbarem Code kommen, bzw einem Release <img src='http://sixserv.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Links:</p>
<ul>
<li> <a href="http://bittorrent.org/beps/bep_0005.html">BitTorrent Enhancement Proposal 005 / BEP005 </a></li>
<li> <a href="http://de.wikipedia.org/w/index.php?title=Kademlia&amp;oldid=64630482">Wikipedia/DE zu Kademlia</a></li>
<li> <a href="http://de.wikipedia.org/w/index.php?title=Verteilte_Hashtabelle&amp;oldid=64994840">Wikipedia/DE zu DHT</a></li>
</ul>
<p>Trotzallem noch tolle Ersatz-Indexer <img src='http://sixserv.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<ul>
<li> <a href="http://www.torrentbox.com/">torrentbox</a> Hier finde ich vor allem das Global-Search Feature ganz nettm da dort auch Torrentbox-Verified Torrents angezeigt werden</li>
<li><a href="http://1337x.org/">1337x </a>Noch etwas kleines aber sympathisches Projekt</li>
<li><a href="http://www.h33t.com/">h33t</a> Die Oberfläche ist gewöhnungsbedürftig, ansonsten auch sehr nice xD</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/10/02/implementing-bittorrent-dht-teil-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Neues Theme</title>
		<link>http://sixserv.org/2009/10/01/neues-theme/</link>
		<comments>http://sixserv.org/2009/10/01/neues-theme/#comments</comments>
		<pubDate>Thu, 01 Oct 2009 16:48:59 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[sixserv]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=473</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_wordpress.png" width="50" height="51" alt="" title="Wordpress" /><br/>Endlich hat Sixserv ein eigenes Wordpress-Theme. Ich arbeite da schon seit einigen Wochen dran, es basiert in der Grundstruktur auf dem Standard Wordpress Theme(GPLv2), der Kommentarbereich ist aus Monochrome(GPLv3) mit einigen kleinen Änderungen übernommen. Die Kategorie-Icons entstammen hauptsächlich verschiedener Icon-Sets: Discovery(CC), Crystal Project(LGPL) und Crystal Clear(LGPL).
Fehler, Kritik, Verbesserungsvorschläge, usw. bitte in die Kommentare.
]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_wordpress.png" width="50" height="51" alt="" title="Wordpress" /><br/><p>Endlich hat Sixserv ein eigenes Wordpress-Theme. Ich arbeite da schon seit einigen Wochen dran, es basiert in der Grundstruktur auf dem <a href="http://binarybonsai.com/wordpress/kubrick/">Standard Wordpress Theme</a>(GPLv2), der Kommentarbereich ist aus <a href="http://wordpress.org/extend/themes/monochrome">Monochrome</a>(GPLv3) mit einigen kleinen Änderungen übernommen. Die Kategorie-Icons entstammen hauptsächlich verschiedener Icon-Sets: <a href="http://hbons.deviantart.com/art/Discovery-Icon-Theme-77399781">Discovery</a>(CC), <a href="http://www.everaldo.com/crystal/?action=license">Crystal Project</a>(LGPL) und <a href="http://www.kde-look.org/content/show.php/Crystal+Clear?content=25668">Crystal Clear</a>(LGPL).</p>
<p>Fehler, Kritik, Verbesserungsvorschläge, usw. bitte in die Kommentare.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/10/01/neues-theme/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Zensursula: Teil 1 &#8211; DNS</title>
		<link>http://sixserv.org/2009/06/27/zensursula-teil-1-dns/</link>
		<comments>http://sixserv.org/2009/06/27/zensursula-teil-1-dns/#comments</comments>
		<pubDate>Sat, 27 Jun 2009 20:40:41 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Censorship]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[zensursula]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=447</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_censorship.png" width="67" height="51" alt="" title="Censorship" /><br/>&#8220;Sie werden sich noch wünschen wir wären Politikverdrossen&#8221; (@343max)
Ich hatte in den letzten Wochen den Eindruck, als ob die gesamte Internet-Gemeinschaft in Deutschland Sturm lief, überall gab und gibt es nur ein Thema: Die Internetzensur Bestrebungen der großen Koalition. Dabei hatte man am Ende den Eindruck gegen eine Mauer von Unkenntnis, Ignoranz aber vielleicht auch [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_censorship.png" width="67" height="51" alt="" title="Censorship" /><br/><blockquote><p><em style="font-size: 21px;">&#8220;Sie werden sich noch wünschen wir wären Politikverdrossen&#8221;</em> (<a href="http://twitter.com/343max/status/2228357957">@343max</a>)</p></blockquote>
<p><img src="/wp-content/uploads/2009/06/zensursula-300x292.jpg" alt="zensursula-300x292" title="zensursula-300x292" width="300" height="292" class="alignleft size-full wp-image-453" style="margin-right: 8px;" />Ich hatte in den letzten Wochen den Eindruck, als ob die gesamte Internet-Gemeinschaft in Deutschland Sturm lief, überall gab und gibt es nur ein Thema: Die Internetzensur Bestrebungen der großen Koalition. Dabei hatte man am Ende den Eindruck gegen eine Mauer von Unkenntnis, Ignoranz aber vielleicht auch einfach blanker böswilliger Berechnung einfach nichts ausrichten zu können.<br />
Besonders Enttäuschend empfand ich die Medien, überraschend war es freilich nicht dass sie praktisch ausschließlich Parteipropaganda nachplapperten und die Mainstream Meinung nach dem Willen der Regierung formten. Von investigativem Journalismus jedenfalls war in den Holzmedien nichts zu sehen, das überlässt man offenbar <a href="http://ak-zensur.de/2009/05/loeschen-funktioniert.html">anderen</a>.</p>
<p>Ein wenig Ironisch ist es schon, ist doch gerade das Internet die einzige breit zugängliche alternative Informationsquelle(wie wir eindrucksvoll sehen konnten), die mit der jetzt beschlossenen Infrastruktur möglicherweise schon bald stark eingeschränkt wird. Dabei geht es auch um die Frage ob wir der Regierung soweit vertrauen, nach der Installation einer bis dato einmaligen Infrastruktur für Zensur, bei der Sperrung von Kinderpornographischen Inhalten zu bleiben. In den letzten Jahren hat uns die große Koalition keinen Grund geliefert das zu glauben.</p>
<p>Die eigentliche Kluft wie häufig Thematisiert, liegt nicht zwischen den Internet-Natives und den &#8220;Internet-Ausdruckern&#8221; sondern vielmehr in dem Teil der Bevölkerung der sich unabhängig Informiert und dem Teil, der den großen Medien und Agenturen(auch im Internet) blind vertaut und als einzige Informationsquelle zur eigenen Meinungsbildung heranzieht, also den überwiegenden Teil der Gesellschaft.</p>
<p>Gestern nun hat die <a href="http://www.dradio.de/kulturnachrichten/200906261600/3">EU die Zensur in China gerügt</a>(so Merkwürdig wie das auch immer ist), demnach vergessen wir einfach alles was die EU-Länder sonst so treiben und beschäftigen uns nun, <b>offensichtlich im Wohlwollen der EU</b>, um die aktiven technischen Möglichkeiten der Umgehung jedweder Zensur-Infrastruktur, außerdem kann es nicht schaden die von den Zensoren eingesetzte Technologie mal etwas genauer zu beleuchten.</p>
<p><strong>In diesem ersten Teil soll es um die Zensur durch DNS Manipulationen gehen.</strong></p>
<p>Es ist noch die leichteste Form der Zensur, die Einstiegsdroge der Staaten sozusagen, denn DNS Manipulationen lassen sich Kinderleicht aushebeln was wohl schnell den Wunsch nach härteren Mitteln wecken dürfte. Bei dieser Form der Zensur installieren die ISP&#8217;s die Sperrlisten in ihren DNS-Servern, ist doch zumindest anzunehmen, das die Mehrheit der Internet Nutzer die Server ihres Providers verwenden, wobei das bei leibe nicht immer der Fall ist. So war und ist es schon immer möglich seinen eigenen DNS-Server zu betreiben. Jetzt wo man allen Grund hat den DNS-Servern der Provider zu misstrauen, ist das eine sehr praktikable Möglichkeit, zumindest für diejenigen die sich mit dem Internet auskennen.<br />
Doch der Reihe nach, im Prinzip reicht es statt eines Domain-Namens in der Adresszeile die Ip-Adresse einzugeben um diese Zensur zu umgehen, besser ist es da schon einen alternativen DNS-Server zu verwenden, vorzugsweise im Ausland, aber auch der <a href="http://ccc.de/">CCC</a> und der <a href="http://www.foebud.org/datenschutz-buergerrechte/gegen-internetsperren-in-einer-freien-gesellschaft-foebud-richtet-anti-zensur-dns-server-ein/?searchterm=DNS">Foebud</a> stellen unzensierte DNS-Server (noch) frei zur Verfügung. Listen mit freien Servern gibt es z.B. bei <a href="http://wikileaks.org/wiki/Alternative_DNS">Wikileaks</a>, dem <a href="http://ccc.de/censorship/dns-howto/">CCC</a> oder die Server des <a href="http://www.opennicproject.org/index.php?view=category&#038;id=51%3Amigrate-to-opennic&#038;option=com_content&#038;Itemid=82">Open NIC Projektes</a>.</p>
<p><strong>DNS Caching Server</strong></p>
<p>Nützlich ist auch das Einrichten eines eigenen Caching DNS-Servers der zufällig aus einer Liste, öffentliche Servern abfragt. Ich verwende dafür den <a href="http://www.phys.uu.nl/~rombouts/pdnsd/">pdnsd</a>, nicht zu verwechseln mit dem vollwertigen DNS-Server, <a href="http://powerdns.com/">PowerDNS</a>. Je nach Distribution sollte sich die Installation einfach gestalten, z.B. reicht ein <code>pacman -S pdnsd</code> um mit Arch Linux den Server zu installieren. Jetzt sollte man sich die Beispiel Konfiguration kopieren und Anpassungen vornehmen. Hier eine mögliche Beispielkonfiguration, es muss nur die server_ip angepasst werden:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">global <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        <span style="color: #007800;">perm_cache</span>=<span style="color: #000000;">512000</span>; <span style="color: #666666; font-style: italic;"># cache groesse in KB (hier &quot;leicht&quot; uebertriebene 500 MB)</span>
        <span style="color: #007800;">cache_dir</span>=<span style="color: #ff0000;">&quot;/var/cache/pdnsd&quot;</span>;
        <span style="color: #007800;">run_as</span>=<span style="color: #ff0000;">&quot;nobody&quot;</span>;
        <span style="color: #007800;">server_ip</span>=10.0.0.4; <span style="color: #666666; font-style: italic;"># ANPASSEN</span>
        <span style="color: #007800;">status_ctl</span>=on;
        <span style="color: #007800;">paranoid</span>=on; <span style="color: #666666; font-style: italic;"># prevents cache poisoning</span>
        <span style="color: #007800;">query_method</span>=udp_tcp;
        <span style="color: #007800;">min_ttl</span>=15m; <span style="color: #666666; font-style: italic;"># min/max TTL</span>
        <span style="color: #007800;">max_ttl</span>=4w;
        <span style="color: #007800;">timeout</span>=<span style="color: #000000;">15</span>; <span style="color: #666666; font-style: italic;"># global timeout 15 seconds</span>
        <span style="color: #007800;">neg_rrs_pol</span>=auth;
        <span style="color: #007800;">par_queries</span>=<span style="color: #000000;">2</span>; <span style="color: #666666; font-style: italic;"># maximale parallele abfrage von servern</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
server <span style="color: #7a0874; font-weight: bold;">&#123;</span> <span style="color: #666666; font-style: italic;"># ein paar oeffentliche server (alle getestet)</span>
        label = <span style="color: #ff0000;">&quot;random&quot;</span>;
        randomize_servers = on;
        ip = 85.214.73.63, <span style="color: #666666; font-style: italic;"># foebud</span>
        204.152.184.76, <span style="color: #666666; font-style: italic;"># ISC (USA)</span>
        213.73.91.35, <span style="color: #666666; font-style: italic;"># CCC</span>
        194.95.202.198, <span style="color: #666666; font-style: italic;"># DFN</span>
        58.6.115.43, <span style="color: #666666; font-style: italic;"># Westnet (Australien)</span>
        82.229.244.191, <span style="color: #666666; font-style: italic;"># Frankreich</span>
        88.191.77.10, <span style="color: #666666; font-style: italic;"># Frankreich</span>
	216.87.84.209, <span style="color: #666666; font-style: italic;"># OpenNIC</span>
	88.191.77.10; <span style="color: #666666; font-style: italic;"># OpenNIC</span>
        <span style="color: #007800;">timeout</span>=<span style="color: #000000;">10</span>; <span style="color: #666666; font-style: italic;"># 10 sekunden maximal</span>
        <span style="color: #007800;">uptest</span>=<span style="color: #c20cb9; font-weight: bold;">ping</span>;
        <span style="color: #007800;">ping_timeout</span>=<span style="color: #000000;">400</span>; <span style="color: #666666; font-style: italic;">#ms</span>
        <span style="color: #007800;">interval</span>=30m; <span style="color: #666666; font-style: italic;"># uptest der server per ping</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Unveraendert aus Sample Conf:</span>
<span style="color: #666666; font-style: italic;"># This section is meant for resolving from root servers.</span>
server <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        label = <span style="color: #ff0000;">&quot;root-servers&quot;</span>;
        root_server = on;
        randomize_servers = on; <span style="color: #666666; font-style: italic;"># Give every root server an equal chance</span>
                                <span style="color: #666666; font-style: italic;"># of being queried.</span>
        ip =    198.41.0.4
        ,       192.228.79.201
        ,       192.33.4.12
        ,       128.8.10.90
        ,       192.203.230.10
        ,       192.5.5.241
        ,       192.112.36.4
        ,       128.63.2.53
        ,       192.36.148.17
        ,       192.58.128.30
        ,       193.0.14.129
        ,       198.32.64.12
        ,       202.12.27.33
        ;
        timeout = <span style="color: #000000;">5</span>;
        uptest = query;         <span style="color: #666666; font-style: italic;"># Test availability using empty DNS queries.</span>
        interval = 30m;         <span style="color: #666666; font-style: italic;"># Test every half hour.</span>
        ping_timeout = <span style="color: #000000;">300</span>;     <span style="color: #666666; font-style: italic;"># Test should time out after 30 seconds.</span>
        purge_cache = off;
        exclude = .localdomain;
        policy = included;
        preset = off;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># ganz praktisch, damit braucht man nur eine einzige hosts Datei im ganzen LAN zu pflegen:</span>
<span style="color: #7a0874; font-weight: bold;">source</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> 
        <span style="color: #007800;">owner</span>=localhost;
        <span style="color: #007800;">serve_aliases</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span>;
        <span style="color: #007800;"><span style="color: #c20cb9; font-weight: bold;">file</span></span>=<span style="color: #ff0000;">&quot;/etc/hosts&quot;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>Ich habe alle DNS Server getestet. Eventuell die Konfiguration noch auf die eigenen Anforderungen anpassen, eine Dokumentation findet ihr <a href="http://www.phys.uu.nl/~rombouts/pdnsd/doc.html">hier</a>. Die /etc/resolv.conf noch auf die lokale IP-Adresse umstellen dann den Server (neu)starten. Jetzt sollte er funktionieren, testen kann man das z.B. mit nslookup oder: <code>dig 4poc.org [IP des DNS]</code>, dig zeigt auch wie lange er zum resolven brauchte.</p>
<p>Um festzustellen welche DNS-Server verwendet werden habe ich ein kleines Skript geschrieben, eigentlich passt die Thematik(siehe Anmerkung im Script) nicht direkt zum Thema aber den folgenden Artikeln sei schon mal etwas vorgegriffen: <a href="http://nstest.4poc.org/">nstest.4poc.org</a> (DNS Tester, falls jemanden einen besseren Namen dafür einfällt nur her damit.)</p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/06/27/zensursula-teil-1-dns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Kleine Ruby Logger Klasse</title>
		<link>http://sixserv.org/2009/06/13/kleine-ruby-logger-klasse/</link>
		<comments>http://sixserv.org/2009/06/13/kleine-ruby-logger-klasse/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 04:04:09 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=439</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_ruby.png" width="50" height="51" alt="" title="Ruby" /><br/>Normalerweise sind die Artikel hier ja ziemlich umfangreich, was ja auch gut ist schließlich geht das Sixserv Blog ja schon sehr ins technische Detail. Doch diesmal wird es eher kurz, ich möchte eine kleine Logger Klasse vorstellen die ich in Ruby geschrieben habe und seither häufiger benutze.

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
class Logger
  def self.init
    @logfile [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_ruby.png" width="50" height="51" alt="" title="Ruby" /><br/><p>Normalerweise sind die Artikel hier ja ziemlich umfangreich, was ja auch gut ist schließlich geht das Sixserv Blog ja schon sehr ins technische Detail. Doch diesmal wird es eher kurz, ich möchte eine kleine Logger Klasse vorstellen die ich in Ruby geschrieben habe und seither häufiger benutze.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Logger</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">init</span>
    <span style="color:#0066ff; font-weight:bold;">@logfile</span> = LOG_FILE
    <span style="color:#0066ff; font-weight:bold;">@buffer</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#008000; font-style:italic;"># logging lines for buffering</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#006600; font-weight:bold;">&lt;&lt;</span> msg
    msg = <span style="color:#CC0066; font-weight:bold;">format</span> msg
&nbsp;
    <span style="color:#008000; font-style:italic;"># append message to buffer</span>
    <span style="color:#0066ff; font-weight:bold;">@buffer</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> msg
&nbsp;
    <span style="color:#008000; font-style:italic;"># flush the buffer if possible</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">flush</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">flush</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@buffer</span>.<span style="color:#9900CC;">empty</span>?
&nbsp;
    <span style="color:#008000; font-style:italic;"># try to lock the file for writing</span>
    log = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>@logfile, <span style="color:#996600;">'a+'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> log.<span style="color:#9900CC;">flock</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">File::LOCK_EX</span> <span style="color:#006600; font-weight:bold;">|</span> <span style="color:#6666ff; font-weight:bold;">File::LOCK_NB</span><span style="color:#006600; font-weight:bold;">&#41;</span> == <span style="color:#0000FF; font-weight:bold;">false</span>
      <span style="color:#008000; font-style:italic;"># Logfile is locked</span>
      <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Logfile is locked!&quot;</span>
      log.<span style="color:#9900CC;">close</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">false</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ==&gt; not locked, write buffer to logfile</span>
    <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0066ff; font-weight:bold;">@buffer</span>.<span style="color:#9900CC;">length</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">0</span>
      log.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#0066ff; font-weight:bold;">@buffer</span>.<span style="color:#9900CC;">shift</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    log.<span style="color:#9900CC;">flock</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">File::LOCK_UN</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    log.<span style="color:#9900CC;">close</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#CC0066; font-weight:bold;">format</span> msg
    time = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">strftime</span> <span style="color:#996600;">'%H:%M:%S - %d.%m.%Y'</span>
    <span style="color:#996600;">&quot;[#{time}] #{msg}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Nichts großes also, es gibt z.B. keine Log-Level usw. Außerdem kann man sich, wenn man etwas mehr Features braucht, auch eine Logging Bibliothek aus dem Gems bedienen. Die Anwendung ist ganz einfach:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'/pfad/zu/logger.rb'</span>
<span style="color:#CC00FF; font-weight:bold;">Logger</span>.<span style="color:#9900CC;">init</span>
<span style="color:#008000; font-style:italic;"># das kann man dann überall im Code verteilen:</span>
<span style="color:#CC00FF; font-weight:bold;">Logger</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;Irgendeine Nachricht!&quot;</span>
<span style="color:#008000; font-style:italic;"># hat man eine große Anwendung mit vielen Prozessen/Threads</span>
<span style="color:#008000; font-style:italic;"># kann man auch an strategischen Stellen ein</span>
<span style="color:#CC00FF; font-weight:bold;">Logger</span>.<span style="color:#9900CC;">flush</span>
<span style="color:#008000; font-style:italic;"># einbauen :)</span></pre></td></tr></table></div>

<p>Hier noch eine kleine Erweiterung die einen Log-Server implementiert. Er öffnet einen TCP Port, jeder der sich verbindet(z.B. per Telnet/Netcat) kann daraufhin die Log-Nachrichten mitlesen:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Logger</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">init</span>
    ...
    <span style="color:#0066ff; font-weight:bold;">@port</span> = LOG_PORT
    <span style="color:#0066ff; font-weight:bold;">@query</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0066ff; font-weight:bold;">@query_mutex</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#0066ff; font-weight:bold;">@running</span> = <span style="color:#0000FF; font-weight:bold;">false</span>
    <span style="color:#0066ff; font-weight:bold;">@server</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">start_server</span>
    <span style="color:#0066ff; font-weight:bold;">@query_mutex</span> = <span style="color:#CC00FF; font-weight:bold;">Mutex</span>.<span style="color:#9900CC;">new</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Start logging console @ #{LOG_HOST}:#{LOG_PORT}&quot;</span>
&nbsp;
    <span style="color:#0066ff; font-weight:bold;">@server</span> = TCPServer.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>LOG_HOST, LOG_PORT<span style="color:#006600; font-weight:bold;">&#41;</span>
    clients = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0066ff; font-weight:bold;">@running</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
    <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">start</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      client = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0066ff; font-weight:bold;">@running</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          client = <span style="color:#0066ff; font-weight:bold;">@server</span>.<span style="color:#9900CC;">accept_nonblock</span>
          clients <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> client <span style="color:#9966CC; font-weight:bold;">if</span> client != <span style="color:#0000FF; font-weight:bold;">nil</span>
        <span style="color:#9966CC; font-weight:bold;">rescue</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          message = <span style="color:#0000FF; font-weight:bold;">nil</span>
          <span style="color:#0066ff; font-weight:bold;">@query_mutex</span>.<span style="color:#9900CC;">synchronize</span> <span style="color:#006600; font-weight:bold;">&#123;</span> message = <span style="color:#0066ff; font-weight:bold;">@query</span>.<span style="color:#9900CC;">pop</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
          <span style="color:#9966CC; font-weight:bold;">if</span> message != <span style="color:#0000FF; font-weight:bold;">nil</span>
            clients.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>client<span style="color:#006600; font-weight:bold;">|</span>
                <span style="color:#9966CC; font-weight:bold;">begin</span>
                    client.<span style="color:#CC0066; font-weight:bold;">puts</span> message
                <span style="color:#9966CC; font-weight:bold;">rescue</span>
                    clients.<span style="color:#9900CC;">delete</span> client
                <span style="color:#9966CC; font-weight:bold;">end</span> 
            <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#9966CC; font-weight:bold;">not</span> <span style="color:#0066ff; font-weight:bold;">@query</span>.<span style="color:#9900CC;">empty</span>?
        <span style="color:#CC0066; font-weight:bold;">sleep</span> LOG_SERVER_INTERVAL
      <span style="color:#9966CC; font-weight:bold;">end</span>
      clients.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>client<span style="color:#006600; font-weight:bold;">|</span> client.<span style="color:#9900CC;">close</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#0066ff; font-weight:bold;">@server</span>.<span style="color:#9900CC;">close</span>
      <span style="color:#0066ff; font-weight:bold;">@server</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">destroy</span>
    <span style="color:#0066ff; font-weight:bold;">@running</span> = <span style="color:#0000FF; font-weight:bold;">false</span>
    <span style="color:#0066ff; font-weight:bold;">@fs</span>.<span style="color:#9900CC;">close</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># wait until server closed</span>
    <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0066ff; font-weight:bold;">@server</span> != <span style="color:#0000FF; font-weight:bold;">nil</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#006600; font-weight:bold;">&lt;&lt;</span> msg
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@query_mutex</span> != <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@query_mutex</span>.<span style="color:#9900CC;">synchronize</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        <span style="color:#0066ff; font-weight:bold;">@query</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC0066; font-weight:bold;">format</span><span style="color:#006600; font-weight:bold;">&#40;</span>msg<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;&gt;&gt;&gt; #{msg}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>  
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">flush</span>
    <span style="color:#008000; font-style:italic;"># just wait until everything is sent/written</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@query</span>.<span style="color:#9900CC;">length</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">0</span>
      <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0066ff; font-weight:bold;">@query</span>.<span style="color:#9900CC;">length</span> != <span style="color:#006666;">0</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  ...
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>So das wars schon, ich hoffe das ich das mit dem Mutex richtig gemacht habe und das hier überhaupt notwendig war, ich habe auf dem Gebiet nicht viel Erfahrung und würde mich über einen entsprechenden Kommentar freuen.<br />
// I&#8217;m not sure I used the Mutex in this example correctly, I would appreciate a comment about this.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/06/13/kleine-ruby-logger-klasse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web scraping mit Ruby/Mechanize</title>
		<link>http://sixserv.org/2009/05/27/webscripting-mit-ruby-und-mechanize/</link>
		<comments>http://sixserv.org/2009/05/27/webscripting-mit-ruby-und-mechanize/#comments</comments>
		<pubDate>Wed, 27 May 2009 12:44:13 +0000</pubDate>
		<dc:creator>apoc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[mechanize]]></category>
		<category><![CDATA[Networking]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=398</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_ruby.png" width="50" height="51" alt="" title="Ruby" /><br/>Praktisch jede Interaktion mit einer Website oder Webapplikation kann gescriptet, d.h. automatisiert werden. Das Abgrasen von Webseiten nach bestimmten Informationen wird auch als Scraping bezeichnet(für die nicht menschlichen Besucher dieser Seite sei das erwähnt *g*) Scripte können einem eine ganze Menge Arbeit abnehmen und sogar Dinge tun, die manuell unmöglich wären. Ich beschäftige mich mit [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_ruby.png" width="50" height="51" alt="" title="Ruby" /><br/><p>Praktisch jede Interaktion mit einer Website oder Webapplikation kann gescriptet, d.h. automatisiert werden. Das Abgrasen von Webseiten nach bestimmten Informationen wird auch als <a href="http://en.wikipedia.org/wiki/Web_scraping">Scraping</a> bezeichnet(für die nicht menschlichen Besucher dieser Seite sei das erwähnt *g*) Scripte können einem eine ganze Menge Arbeit abnehmen und sogar Dinge tun, die manuell unmöglich wären. Ich beschäftige mich mit dem Thema schon seit einer ganzen Weile und möchte hier nun die von mir favorisierte Methode dafür vorstellen, die Bibliothek <a href="http://mechanize.rubyforge.org/mechanize/">Mechanize</a> für die Scriptsprache <a href="http://www.ruby-lang.org/en/">Ruby</a>.</p>
<p>Mechanize hat seinen <a href="http://search.cpan.org/dist/WWW-Mechanize/">Ursprung</a> in Perl, mittlerweile gibt es jedoch auch Implementierungen der API für <a href="http://wwwsearch.sourceforge.net/mechanize/">Python</a> und eben Ruby. Für PHP gibt es mit <a href="http://sourceforge.net/projects/snoopy/">Snoopy</a> ein ähnliches Projekt, wenn es auch bei weitem nicht so fortgeschritten ist. Mechanize bietet die Möglichkeit mit einfachen Methoden eine art Webbrowser zu simulieren. Alle Beispiele wurden mit Mechanize Version 0.9.2 und Ruby 1.8.7 getestet.</p>
<p><strong>Installation / Initialisierung</strong></p>
<p>Mechanize kann mit <a href="http://rubygems.org/">Gems</a>(ähnlich CPAN oder PEAR) installiert werden(<code># gem install mechanize --remote</code>), einige Distributionen bieten aber auch eigene Pakete an. Ein Ruby-Script kann daraufhin Mechanize inkludieren und ein Objekt erstellen:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span> <span style="color:#008000; font-style:italic;"># ist unter Umständen notwendig</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mechanize'</span>
agent = <span style="color:#6666ff; font-weight:bold;">WWW::Mechanize</span>.<span style="color:#9900CC;">new</span></pre></div></div>

<p>Jetzt ist Mechanize einsatzbereit, die folgenden Beispiele bauen darauf auf. Außerdem können mit dem <code>agent</code> nun noch grundlegende Einstellungen vorgenommen werden:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">agent.<span style="color:#9900CC;">set_proxy</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'localhost'</span>, <span style="color:#996600;">'8000'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
agent.<span style="color:#9900CC;">user_agent</span> = <span style="color:#996600;">'Individueller User-Agent'</span>
agent.<span style="color:#9900CC;">user_agent_alias</span> = <span style="color:#996600;">'Linux Mozilla'</span></pre></div></div>

<p>Die Einstellung &#8216;<code>user_agent_alias</code>&#8216; wählt einen User-Agent String aus dem folgenden Satz von Beispielen aus: Windows IE 6, Windows IE 7, Windows Mozilla, Mac Safari, Mac FireFox, Mac Mozilla, Linux Mozilla, Linux Konqueror, iPhone und Mechanize. Die Timing Einstellungen können ebenfalls sehr wichtig sein:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">agent.<span style="color:#9900CC;">open_timeout</span> = <span style="color:#006666;">3</span> <span style="color:#008000; font-style:italic;"># setzt timeouts</span>
agent.<span style="color:#9900CC;">read_timeout</span> = <span style="color:#006666;">4</span>
agent.<span style="color:#9900CC;">keep_alive</span> = <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#008000; font-style:italic;"># default ist true</span></pre></div></div>

<p>Hier folgen nun einige Beispiele, vielleicht werde ich mit der Zeit auch noch ein paar ergänzen, falls jemand Vorschläge hat, immer her damit. Ich habe auf <a href="http://apoc.sixserv.org/requestinfo">http://apoc.sixserv.org/requestinfo</a> ein kleines Skript am laufen das nützliche Informationen zum HTTP-Request liefert, das kann zum Experimentieren mit Mechanize sehr nützlich sein. Einige Beispiele findet man auch in den <a href="http://mechanize.rubyforge.org/mechanize/GUIDE_rdoc.html">GUIDE</a> und <a href="http://mechanize.rubyforge.org/mechanize/EXAMPLES_rdoc.html">EXAMPLES</a> Dateien des Mechanize Pakets. <span id="more-398"></span></p>
<p><strong>#01 &#8211; Manuelle Get Requests</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">url = <span style="color:#996600;">'http://apoc.sixserv.org/requestinfo/'</span>
page = agent.<span style="color:#9900CC;">get</span> url <span style="color:#008000; font-style:italic;"># einfacher get request</span>
<span style="color:#008000; font-style:italic;"># parameter können auch als Hash mitgeliefert werden:</span>
page = agent.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>url, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;name&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;value&quot;</span>, <span style="color:#996600;">&quot;key&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;val&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p><strong>#02 &#8211; Manuelle Post Requests</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">url = <span style="color:#996600;">'http://apoc.sixserv.org/requestinfo/'</span>
page = agent.<span style="color:#9900CC;">post</span><span style="color:#006600; font-weight:bold;">&#40;</span>url, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;name&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;value&quot;</span>, <span style="color:#996600;">&quot;key&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;val&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>In diesem Fall werden die Post-Daten manuell erzeugt, häufig ist es jedoch besser das eigentliche Formular zu verwenden. z.B. ein Login oder Suchformular:</p>
<p><strong>#03 &#8211; Post Requests(/Submits) aus Formular erzeugen</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">page = agent.<span style="color:#9900CC;">get</span> <span style="color:#996600;">'https://twitter.com/login'</span>
login_form = page.<span style="color:#9900CC;">form_with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'https://twitter.com/sessions'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
login_form<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'session[username_or_email]'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'[Username]'</span>
login_form<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'session[password]'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'[Password]'</span>
page = agent.<span style="color:#9900CC;">submit</span> login_form</pre></div></div>

<p>Dieses kleine Beispiel loggt sich bei Twitter ein.</p>
<p><strong>#04 &#8211; Navigation über Links und der History</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">page = agent.<span style="color:#9900CC;">get</span> <span style="color:#996600;">'http://www.heise.de/'</span>
page = agent.<span style="color:#9900CC;">click</span><span style="color:#006600; font-weight:bold;">&#40;</span>page.<span style="color:#9900CC;">link_with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:text</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>Telepolis<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
page = agent.<span style="color:#9900CC;">click</span><span style="color:#006600; font-weight:bold;">&#40;</span>page.<span style="color:#9900CC;">link_with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:href</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>artikel<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
agent.<span style="color:#9900CC;">back</span>
agent.<span style="color:#9900CC;">back</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> page.<span style="color:#9900CC;">body</span></pre></div></div>

<p><strong>#05 &#8211; Exceptions</strong></p>
<p>Wird z.B. eine nicht vorhandene Seite aufgerufen, wirft Mechanize eine Exception, diese sollte Abgefangen werden da das Skript sonst an dieser Stelle abbricht.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">begin</span>
  page = agent.<span style="color:#9900CC;">get</span> <span style="color:#996600;">'http://apoc.sixserv.org/diese/seite/gibt/es/nicht/'</span>
<span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">WWW::Mechanize::ResponseCodeError</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;ResponseCodeError - Code: #{$!}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p><strong>#06 &#8211; Referer</strong></p>
<p>Mechanize benutzt seine Navigations-History auch zum senden eines passenden Referers, diesen kann man allerdings auch manuell bestimmen, hier für GET und POST Requests:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">page = agent.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://apoc.sixserv.org/requestinfo/'</span>,
<span style="color:#ff3333; font-weight:bold;">:referer</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://google.com/this/is/a/custom/referer'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> page.<span style="color:#9900CC;">body</span></pre></div></div>

<p><strong>#07 &#8211; Headers / HEAD / Redirect</strong></p>
<p>Der Request Header kann manuell erweitert werden, bspw. den &#8220;X-Requested-With&#8221; so zu setzen um einen Ajax-Aufruf zu simulieren. Es gibt leider keine wirklich gute Möglichkeit eigene Header zu setzen, das ganze wurde in den vergangenen Versionen oft geändert, die folgende Methode funktioniert mit älteren Versionen von Mechanize nicht.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">agent.<span style="color:#9900CC;">pre_connect_hooks</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>params<span style="color:#006600; font-weight:bold;">|</span>
  params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:request</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'X-Requested-With'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'XMLHttpRequest'</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Dies ist übrigens auch die einzig wirklich einfache Möglichkeit manuell Cookies zu setzen/ zu übertragen. Die andere Seite, also das Abfragen des Response-Headers ist trivial, hier wird z.B. per HEAD-Request die Server und evtl. der PHP-Version abgefragt:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">page = agent.<span style="color:#9900CC;">head</span> <span style="color:#996600;">'http://sixserv.org'</span>
server_version = page.<span style="color:#9900CC;">header</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'server'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Server: #{server_version}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">if</span> page.<span style="color:#9900CC;">header</span>.<span style="color:#9900CC;">key</span>? <span style="color:#996600;">'x-powered-by'</span>
  php_version = page.<span style="color:#9900CC;">header</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'x-powered-by'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;X-Powered-By: #{php_version}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Will man einen HTTP-Redirect(302) abfragen, muss man zunächst das automatische Weiterleiten im Mechanize deaktivieren, dann kann man den Zielort abfragen ohne das Ziel zu besuchen. (Nützlich z.B. wenn man auf einen Datei-Download weitergeleitet wird)</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">agent.<span style="color:#9900CC;">redirect_ok</span> = <span style="color:#0000FF; font-weight:bold;">false</span>
page = agent.<span style="color:#9900CC;">get</span> <span style="color:#996600;">'http://www.sixserv.org/'</span> <span style="color:#008000; font-style:italic;"># leitet auf http://sixserv.org weiter</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> page.<span style="color:#9900CC;">header</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'location'</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p><strong>#08 &#8211; Threads</strong></p>
<p>Will man ein Script etwas beschleunigen kann man mit Threads arbeiten um mehrere Inhalte gleichzeitig abzufragen. Das folgende Grundgerüst für z.B. Foren mit vielen Seiten, bearbeitet 10 Seiten gleichzeitig und kann so ein Skript erheblich beschleunigen. In diesem Fall würde man allerdings wahrscheinlich eher nicht Mechanize einsetzen sondern eine Low-Level API fürs Netzwerk-Zugriff, das wäre deutlich effektiver ich will nur das Prinzip deutlich machen.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#ff6633; font-weight:bold;">$threads</span> = <span style="color:#006666;">0</span>
last_page = <span style="color:#006666;">200</span>
max_threads = <span style="color:#006666;">10</span>
<span style="color:#9966CC; font-weight:bold;">for</span> page <span style="color:#9966CC; font-weight:bold;">in</span> 1..<span style="color:#9900CC;">last_page</span>
  <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>page<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>page<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#ff6633; font-weight:bold;">$threads</span> <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot; [*] Create new Thread for scanning Page ##{page}&quot;</span>
&nbsp;
    page = <span style="color:#ff6633; font-weight:bold;">$agent</span>.<span style="color:#9900CC;">get</span> <span style="color:#996600;">&quot;http://example.com/datalist.php?page=#{page}&quot;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># process / save received data</span>
&nbsp;
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot; [*] Destroy Thread&quot;</span>
    <span style="color:#ff6633; font-weight:bold;">$threads</span> <span style="color:#006600; font-weight:bold;">-</span>= <span style="color:#006666;">1</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#ff6633; font-weight:bold;">$threads</span> <span style="color:#006600; font-weight:bold;">&gt;</span> max_threads
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot; [*] Next Page&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p><strong>#09 &#8211; Parsing / XPath</strong></p>
<p>Hat man eine Seite empfangen und will bestimmte Inhalte herausfiltern gibt es mehrere Möglichkeiten, meistens werden mehr oder weniger umfangreiche Reguläre Ausdrücke zum parsen verwendet:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">page = agent.<span style="color:#9900CC;">get</span> <span style="color:#996600;">'http://example.com/'</span>
page.<span style="color:#9900CC;">body</span>.<span style="color:#9900CC;">match</span> <span style="color:#006600; font-weight:bold;">/&lt;</span> h3<span style="color:#006600; font-weight:bold;">&gt;</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>^<span style="color:#006600; font-weight:bold;">&lt;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&lt;</span> \<span style="color:#006600; font-weight:bold;">/</span>h3<span style="color:#006600; font-weight:bold;">&gt;/</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Überschrift 3: #{$1}&quot;</span></pre></div></div>

<p>Wesentlich stabiler sind jedoch <a href="http://en.wikipedia.org/wiki/XPath">XPath</a> Ausdrücke die sich direkt auf die Struktur eines XML-Dokuments beziehen. Werden nur Kleinigkeiten am HTML-Code geändert sind RegEx&#8217;s häuft aufgeschmissen und müssen mühsam angepasst werden, XPath ausdrücke dagegen funktionieren häufig auch dann noch. Eine Einführung gibt es z.B. auf <a href="http://www.w3schools.com/XPath/default.asp">w3schools.com</a> oder der offizielle <a href="http://www.w3.org/TR/xpath">Standard der W3C</a>. Allerdings geht das alles auch sehr einfach mit entsprechenden Werkzeugen, so gibt es z.B. eine Menge Firefox-Addons(nützlich ist z.B. der <a href="https://addons.mozilla.org/en-US/firefox/addon/1095">XPath Checker</a>) die einem, zu markierten Elementen einer Seite einen passenden XPath Ausdruck anzeigt oder umgekehrt, wenn auch die nur einfachen Ausdrücke gelegentlich Nachbearbeitung erfordern.</p>
<div id="attachment_427" class="wp-caption aligncenter" style="width: 690px"><img class="size-full wp-image-427" title="XPath mit Firebug" src="http://sixserv.org/wp-content/uploads/2009/05/xpath_mit_firebug_small.png" alt="XPath mit Firebug" width="680" height="585" /><p class="wp-caption-text">Firebug kann einem zu beliebigen Elementen einer Seite einen passenden XPath(Rot unterstrichen) anzeigen.</p></div>
<p>Der von Mechanize verwendete HTML-Parser <a href="http://nokogiri.rubyforge.org/nokogiri/">Nokogiri</a>(鋸) ist sehr robust und kann auch &#8220;kaputtes&#8221; HTML parsen, was XPath zu einem auserordentlich mächtigen Werkzeug macht, um jede beliebige Information aus noch so komplexen Seiten zu extrahieren.</p>
<p>Mit <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a>: Ein beliebiges Element auf einer Seite markieren und im Kontextmenü, &#8220;Inspect Element&#8221; aufrufen. In der oberen Zeile von Firebug(siehe Screenshot) kann im Kontextmenü mit &#8220;Copy XPath&#8221; der XPath geholt werden. Im Beispiel wird der XPath zum Comic-Strip auf <a href="http://xkcd.com/">XKCD</a> angezeigt: <code>/html/body/div/div[2]/div/div[2]/div/div/img</code> In Mechanize kann so der IMG-Tag extrahiert werden:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">page = agent.<span style="color:#9900CC;">get</span> <span style="color:#996600;">'http://xkcd.com/'</span>
img = page.<span style="color:#9900CC;">search</span> <span style="color:#996600;">'/html/body/div/div[2]/div/div[2]/div/div/img'</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> img
<span style="color:#008000; font-style:italic;"># Ausgabe: &lt; img src=&quot;http://imgs.xkcd.com/comics/designated_drivers.png&quot; title=&quot;Calling a cab means cutting into beer money.&quot; alt=&quot;Designated Drivers&quot; &gt;</span></pre></div></div>

<p><em>Das wars damit vorerst. Anmerkungen oder Fragen zu den Beispielen oder Ideen für weitere, bitte in den Kommentaren hinterlassen.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/05/27/webscripting-mit-ruby-und-mechanize/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>ZDF Mediathek FAIL</title>
		<link>http://sixserv.org/2009/05/12/zdf-mediathek-fail/</link>
		<comments>http://sixserv.org/2009/05/12/zdf-mediathek-fail/#comments</comments>
		<pubDate>Tue, 12 May 2009 14:47:35 +0000</pubDate>
		<dc:creator>nks</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[fail]]></category>
		<category><![CDATA[mediathek]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[zdf]]></category>

		<guid isPermaLink="false">http://sixserv.org/?p=387</guid>
		<description><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_web.png" width="50" height="51" alt="" title="Web" /><br/>Bisher habe ich das Öffentlich Rechtliche Projekt ZDF Mediathek nahezu täglich benutzt. ZDF Mediathek benutzte bis vor wenigen Tagen Windows Media Streams, welche sich wunderbar mit mplayerplug-in oder mit der URL des streams auch super mit mplayer etc anschauen ließen, doch damit ist nun Schluss &#8211; die ZDF Mediathek benutzt nun Flash Streaming. Ich kann [...]]]></description>
			<content:encoded><![CDATA[<img src="/wp-content/themes/6stheme/icons/icon_web.png" width="50" height="51" alt="" title="Web" /><br/><p>Bisher habe ich das Öffentlich Rechtliche Projekt ZDF Mediathek nahezu täglich benutzt. ZDF Mediathek benutzte bis vor wenigen Tagen Windows Media Streams, welche sich wunderbar mit mplayerplug-in oder mit der URL des streams auch super mit mplayer etc anschauen ließen, doch damit ist nun Schluss &#8211; die ZDF Mediathek benutzt nun Flash Streaming. Ich kann diesen Schritt nicht nachvollziehen, Flash Videos unter Linux<br />
machen einfach keinen Spaß. Vollbild oder das schauen während dem surfen sind somit Vergangenheit. Mit einem einfachem &#8220;mplayer -dumpstream -playlist URL&#8221; ließen sich hervorragend Aufnahmen machen, der Digitale Videorecorder quasi.</p>
<p>Ich befürchte das genau dies die verantwortlichen des ZDF dazu bewegt hat auf Flash Basiertes Streaming umzustellen. Ich erwarte von den Öffentlich Rechtlichen allerdings das, wenn Sie schon keine offenen Standards nutzen, die zumindest zumutbar nutzbar unter allen System laufen sollten. Im ZDF Forum wird auch heftig diskutiert &#8211; ich stehe nicht alleine mit der Meinung das Flash Streams schlichtweg SCHEISSE sind.</p>
<p>Die Möglichkeit Videos mit externen Playern zu schauen war für mich einer der Gründe mich überhaupt näher mit dem ZDF Programm auseinanderzusetzen. Neben &#8220;heute&#8221; und dem &#8220;Auslandsjournal&#8221; habe ich mir gelegentlich einige andere Sendungen/Dokumentationen angesehen &#8211; damit ist nun Schluss. Ich werde die ZDF Mediathek ab sofort boykottieren.<br />
ZDF schließt so nicht nur Besitzer leistungsschwacher Rechner aus, sondern evtl auch welche die über ihre Set-top Boxen die ZDF Mediathek benutzten &#8211; und das obwohl sie damit die Kompatibilität angeblich steigern wollen.</p>
<p>Ich habe noch nie einen Fernseher besessen und dies ist für mich ein weiterer Schritt weg von diesem Medium. Die TV Sender scheinen es einfach nicht verstanden zu haben. Wahrscheinlich wird Sie in nicht allzu ferner Zeit das selbe Schicksal treffen wie die Musik-Industrie &#8211; die Netz-Generation wird sich ihren Medienkonsum selbst gestalten, mit oder ohne Segen der TV Sender. Die MI hat es wenigstens eingesehen und bietet in ihren Onlineshops<br />
DRM-Freie MP3-Files an. Das Fernsehen von Morgen ist Interaktiv und besteht nur noch zu<br />
geringen Teilen aus redaktionellen Inhalten und Programmplänen &#8211; die Mediathek war ein Schritt in die richtige Richtung, doch nun hat das ZDF wieder einen Schritt zurück gemacht.</p>
<p>@ZDF: Shame on you!</p>
<p>Das war wirklich die falsche Entscheidung!<br />
Ein User weniger&#8230;</p>
<p>Nachtrag aus dem ZDF Forum:</p>
<blockquote><p>&#8220;Wir wollen ein Format verwenden, das auf allen Browsern und Betriebssystemen abspielbar ist &#8211; deshalb Flash. übrigens sind die WMV/H.264-Streams noch abrufbar. Dafür hat jeder Videobeitrag einen eigenen RSS-Feed, in dem die Links auf die Videos enthalten sind.&#8221;</p></blockquote>
<p>- Redaktion ZDFonline (<a href="http://www.zdf.de/ZDFforum/foren/ueberdaszdf/F6738/msg2098581.php" target="_blank">link</a>)<br />
Das überarbeitete ZDF Online Angebot hat scheinbar nicht viele Freunde wie man den ZDF Foren entnehmen kann.</p>
<p>Es bleibt abzuwarten wie das ZDF bzw der Intendant etc reagieren&#8230;</p>
<p>Falls es mich dennoch nach Dokumentationen lüstet werde ich wie bisher<br />
auch das ARTE-Angebot <a href="http://arte.tv/plus7" target="_blank">ARTE Plus7</a> benutzen.</p>
<p>Update:<br />
<a href="http://apoc.sixserv.org">apoc</a> hat nen tolles <a href="http://apoc.sixserv.org/scripts/mtget.rb">Script</a> zum Downloaden/Abspielen der WMV-Streams geschrieben. Diese sind ja NOCH im RSS-Feed zu beziehen. Danke an apoc (ich war zu faul mir da was zu scripten <img src='http://sixserv.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  )</p>
<p>2 .Update:<br />
Das ZDF reagiert scheinbar auf die Kritik:</p>
<blockquote><p>
&#8230;<br />
haben Sie bitte noch etwas Geduld mit der Mediathek. In der nächsten Version läuft diese auch wieder ohne Flash. Daran, dass die Videos nicht bei allen in der gewohnten Qualität laufen, arbeiten wir gerade.<br />
&#8230;</p></blockquote>
<p>- Redaktion ZDFonline (<a href="http://www.zdf.de/ZDFforum/foren/ueberdaszdf/F6738/msg2103068.php" target="_blank">link</a>)</p>
<p>3. Update:<br />
ZDF kündigt folgendes an:</p>
<blockquote><p>Wir nehmen auch die Kritik an der Ladezeit der Seiten und an die Berichte über die Probleme mit dem Abspielen der Videos sehr ernst. Denn natürlich wollen wir schnell und einfach erreichbar sein. Ruckelnde Videos und &#8220;Stream not found&#8221;- Meldungen sind natürlich ärgerlich. Die Ursachen können aber sehr vielfältig sein. Wir arbeiten auf Hochtouren daran. Bei den technischen Fehlern merken Sie hoffentlich schon sehr bald eine Besserung. Bei den Entwicklungsprojekten dauert es in der Tat länger – wie einige User hier im Forum schon treffend angemerkt haben. Deshalb wird es eine Mediathek ohne Flash leider nicht vor Herbst geben können. </p></blockquote>
<p>- Redaktion ZDFonline (<a href="http://www.zdf.de/ZDFforum/ZDFde/inhalt/10/0,1872,5241482,00/ueberdaszdf/F6738/msg2102832.php" target="_blank">link</a>)</p>
<p>Warten bis Herbst aber immerhin&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://sixserv.org/2009/05/12/zdf-mediathek-fail/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>
