<?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>Patterns of the Void</title>
	<atom:link href="http://gablog.eu/void/feed/" rel="self" type="application/rss+xml" />
	<link>http://gablog.eu/void</link>
	<description>The Net is indeed vast and infinite...</description>
	<lastBuildDate>Wed, 23 Nov 2011 19:26:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>QAssert: JavaScript assertions with AJAX reporting!</title>
		<link>http://gablog.eu/void/2011/11/16/qassert-javascript-assertions-with-ajax-reporting/</link>
		<comments>http://gablog.eu/void/2011/11/16/qassert-javascript-assertions-with-ajax-reporting/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 16:54:51 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=91</guid>
		<description><![CDATA[QAssert is a powerful, easy-to-use, JavaScript assertion suite. In contrast to console.assert() it enables you to report failures via AJAX. It gives you also powerful assertion functions and is cross-browser compatible. It can be used in both in unit, functional and manual tests, and notably also in production code. QAssert is especially useful for regression [...]]]></description>
			<content:encoded><![CDATA[<p>QAssert is a powerful, easy-to-use, JavaScript assertion suite. In contrast to console.assert() it enables you to report failures via AJAX. It gives you also powerful assertion functions and is cross-browser compatible.<br />
It can be used in both in unit, functional and manual tests, and notably also<br />
in production code.</p>
<p>QAssert is especially useful for regression testing: You can place assertions for any assumption that is made in the JavaScript logic. While running the code assertion violations will be reported via AJAX and regressions become quickly visible. To give you an example how to safeguard against unexpected DOM changes:<br />
<code><br />
var $panel = $("#menuPanel");<br />
$panel.assert().load("/");<br />
$.assert($panel.text().length);<br />
</code></p>
<p>It is a simple drop-in jQuery plugin. It is disabled by default. To enable it and to see assertions:<br />
<code><br />
$.assertSetup("/assertReporter"); // Required only once.<br />
$.assert(false)<br />
</code><br />
As a result:</p>
<ul>
<li>You will se the assertion failure in the console including a full stack trace (Assertion failed: false undefined {anonymous}()@file:///D:/Dropbox/dev/qassert/qassert/qassert.js:708 &#8230;)</li>
<li>You will see an AJAX call being made to the given URL</li>
</ul>
<p>It is highly configurable:<br />
<code><br />
$.assertSetup({<br />
            enabled: true,<br />
            ajax: "/fooBar", // You can also pass a full $.ajax() parameter object here!<br />
            catchGlobalErrors: true, // This will report ALL uncatched exceptions too!<br />
            contextCallback: function(value, message, stacktrace) {return {version: app.version, locale: app.locale}}, // Enhances the reported data<br />
            log: myLogFunction, // Used to log failures locally, by default to the console.<br />
            title: "Assertion sucked up:"<br />
    });<br />
</code></p>
<p>It has a convenient API:</p>
<ul>
<li>$.fn.assert(message, sizeOrCallback): Chained selector assertions.</li>
<li>$.assert(value, message): Boolean assertion.</li>
<li>$.assertDeepEquals(value, expected, message): Recursive equality assertion.</li>
<li>$.assertEmpty(value, message): Empty assertion.</li>
<li>$.assertEquals(value, expected, message): Equality assertion, no recursion.</li>
<li>$.assertIs(value, type, message): Type assertion.</li>
<li>$.assertNot(value, message): Boolean assertion for false.</li>
<li>$.assertNotDeepEquals(value, expected, message): Recursive unequality assertion.</li>
<li>$.assertNotEmpty(value, message): Non-empty assertion.</li>
<li>$.assertNotEquals(value, expected, message): Unequality assertion, no recursion.</li>
<li>$.assertNotIs(value, type, message): Type assertion inverted.</li>
<li>$.assertNotSame(value, expected, message): Strict unequality assertion.</li>
<li>$.assertSame(value, expected, message): Strict equality assertion.</li>
</ul>
<p>See the <a href="https://github.com/gaboom/qassert/blob/master/doc/index.html">documentation</a> and <a href="https://github.com/gaboom/qassert/blob/master/tests/tests.js">test cases</a>.<br />
Join the development: <a href="https://github.com/gaboom/qassert">https://github.com/gaboom/qassert</a></p>
Views: 487]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2011/11/16/qassert-javascript-assertions-with-ajax-reporting/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Instant PHP eval</title>
		<link>http://gablog.eu/void/2011/10/05/instant-php-eval/</link>
		<comments>http://gablog.eu/void/2011/10/05/instant-php-eval/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 22:49:25 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=74</guid>
		<description><![CDATA[Here is the code you get a form with, you can submit php code, it gets evaluated on the server. SECURITY WARNING: command(s) below will be all executed in PHP&#8217;s server context! Deny public acces. &#60;!doctype html&#62; &#60;html lang=&#34;en&#34;&#62; &#60;head&#62; &#60;meta charset=&#34;utf-8&#34;&#62; &#60;title&#62;PHP evaluator&#60;/title&#62; &#60;/head&#62; &#60;body&#62; &#60;div&#62; &#60;?php $function = &#34;eval&#34;; $arguments = &#34;return true&#34;; [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the code you get a form with, you can submit php code, it gets evaluated on the server.<br />
SECURITY WARNING: command(s) below will be all executed in PHP&#8217;s server context! Deny public acces.</p>
<pre class="brush:html">
&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;title&gt;PHP evaluator&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div&gt;
            &lt;?php
            $function = &quot;eval&quot;;
            $arguments = &quot;return true&quot;;
            if ($_SERVER['REQUEST_METHOD'] == &quot;POST&quot;) {
                $result = null;
                $function = $_POST[&quot;function&quot;];
                $arguments = $_POST[&quot;arguments&quot;];
                switch ($function) {
                    case &quot;eval&quot;:
                        $result = eval($arguments . &quot;;&quot;);
                        break;
                    default:
                        $result = $function($arguments);
                }
                echo &quot;&lt;hr/&gt;&quot;;
                var_dump($result);
                echo &quot;&lt;hr/&gt;&quot;;
                print_r($result);
                echo &quot;&lt;hr/&gt;&quot;;
                echo($result);
            }
            ?&gt;
        &lt;/div&gt;
        &lt;hr&gt;
        SECURITY WARNING: command(s) below will be all executed in PHP's server context! Deny public acces.
        &lt;form method=&quot;POST&quot;&gt;
            &lt;textarea name=&quot;arguments&quot; style=&quot;width: 600px; height:200px&quot;&gt;&lt;?php echo $arguments ?&gt;&lt;/textarea&gt;
            &lt;br/&gt;
            Function: &lt;input type=&quot;text&quot; name=&quot;function&quot; value=&quot;&lt;?php echo $function ?&gt;&quot; /&gt;
            &lt;button&gt;EXECUTE&lt;/button&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
Views: 498]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2011/10/05/instant-php-eval/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to write down passwords onto paper safely?</title>
		<link>http://gablog.eu/void/2011/07/18/how-to-write-down-passwords-onto-paper-safely/</link>
		<comments>http://gablog.eu/void/2011/07/18/how-to-write-down-passwords-onto-paper-safely/#comments</comments>
		<pubDate>Mon, 18 Jul 2011 20:46:26 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=70</guid>
		<description><![CDATA[Writing down usernames and passwords with a pen is insecure in so many ways I do not attempt to count. The sheer count of passwords however, forces most persons to store them somewhere, instead of keeping all of them just in your head. The digital solution is to protect the passwords with another password in [...]]]></description>
			<content:encoded><![CDATA[<p>Writing down usernames and passwords with a pen is insecure in so many ways I do not attempt to count.<br />
The sheer count of passwords however, forces most persons to store them somewhere, instead of keeping all of them just in your head.<br />
The digital solution is to protect the passwords with another password in sort of a vault (e.g. in a file on a password protected disk, encrypted volume or file, password storage program) [Please note: browsers store passwords almost cleartext by default!]</p>
<p>Sometimes you are still forced to keep a password written up quick and easily in an unencrypted environment, like a piece of paper. (Developing and memorizing secret code language is rather difficult to accomplish this.)<br />
The trick is to write down the password, but with a simple to remember twist!</p>
<p>For each password pair you can see first an example of a cleartext password, then the transformed version:</p>
<ul>
<li>alaudZAPP1 &#8211; alXZaudZAPP12</li>
<li>persepoleS &#8211; pe9lrsepoleSq
<li>Bo23LOwf3 &#8211; BobT23LOwf34</li>
</ul>
<p>You can insert at the very same position(s) random letters to make the text written down unusable. In this example I choose to insert two the after the first two letters, then one at the end.<br />
Looking at the passwords on the right, remembering your scheme, you can easily re-type (decode) the original passwords but leaving an attacker with an obfuscated one.</p>
<p><strong>WARNING:</strong> This method is by far not as safe as a fully encrypted password, and offers only a better-than-nothing protection. Common patterns in your password will become visible by this! Never re-use a password, this method reveals any such mistake, also making it obvious how you encoded all your other passwords written down.</p>
Views: 715]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2011/07/18/how-to-write-down-passwords-onto-paper-safely/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Three questions for an architect</title>
		<link>http://gablog.eu/void/2011/07/15/three-questions-for-an-architect/</link>
		<comments>http://gablog.eu/void/2011/07/15/three-questions-for-an-architect/#comments</comments>
		<pubDate>Fri, 15 Jul 2011 00:25:49 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=65</guid>
		<description><![CDATA[For a release sign-off Do all unit, automated and regression tests run? What is the status of outstanding bugs? Are all changes demonstrated to stakeholders? For a design sign-off Are all transformations from the input domain to the output domain possible? Identify first risky and/or complex ones. Are all our needs supported by an API? [...]]]></description>
			<content:encoded><![CDATA[<p><strong>For a release sign-off</strong></p>
<ul>
<li>Do all unit, automated and regression tests run?</li>
<li>What is the status of outstanding bugs?</li>
<li>Are all changes demonstrated to stakeholders?</li>
</ul>
<p><strong>For a design sign-off</strong></p>
<ul>
<li>Are all transformations from the input domain to the output domain possible? Identify first risky and/or complex  ones.</li>
<li>Are all our needs supported by an API?</li>
<li>Is our API supporting all requirements?</li>
<li>BONUS: If it takes more than two days to complete, does a task breakdown exist?
</ul>
Views: 435]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2011/07/15/three-questions-for-an-architect/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Business Software Development</title>
		<link>http://gablog.eu/void/2011/04/27/business-software-development/</link>
		<comments>http://gablog.eu/void/2011/04/27/business-software-development/#comments</comments>
		<pubDate>Wed, 27 Apr 2011 21:46:45 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Teaching]]></category>
		<category><![CDATA[elte]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=60</guid>
		<description><![CDATA[Business Software Development Eötvös Loránd University Budapest, Faculty of Informatics Eötvös Collegium Informatics Workshop 2011- Syllabus What is business, software and development? Goals, realization and measuring success. Sustaining a business. Software lifecycle, development as a process. Planning and executing projects: Lean, Agile, Scrum. Architecture, design and documentation. Requirements: functional and non functional. User interaction and [...]]]></description>
			<content:encoded><![CDATA[<p>Business Software Development<br />
<a href="http://www.inf.elte.hu/">Eötvös Loránd University Budapest, Faculty of Informatics</a><br />
<a href="http://eotvos.elte.hu/">Eötvös Collegium Informatics Workshop 2011-</a></p>
<p><strong>Syllabus</strong></p>
<ul>
<li>What is business, software and development?</li>
<li>Goals, realization and measuring success. Sustaining a business.</li>
<li>Software lifecycle, development as a process.</li>
<li>Planning and executing projects: Lean, Agile, Scrum.</li>
<li>Architecture, design and documentation.</li>
<li>Requirements: functional and non functional. User interaction and interface design.</li>
<li>Version control and configuration management. Integration and release.</li>
<li>Testing and bug tracking, support and customer awareness.</li>
<li>Understanding different company cultures and roles.</li>
<li>Copyright and intellectual property.</li>
</ul>
<p><strong>Literature</strong></p>
<p>Real Software Engineering [Glenn Vanderburg; Lone Star Ruby Conference; 2010]</p>
<p>Code as Design [Jack W. Reeves; Developer.*; 1995]</p>
<p>No Silver Bullet: Essence and Accidents of Software Engineering [Frederick P. Brooks, Jr.; Computer Magazine; April 1987, University of North Carolina at Chapel Hill]</p>
<p>Design Patterns: Elements of Reusable Object-Oriented Software [Erich Gamma et al.; Addison-Wesley Professional; 1994; ISBN: 978-0201633610]</p>
<p>The Mythical Man-Month: Essays on Software Engineering [Frederick P. Brooks; Addison-Wesley Professional; 1995; Anniversary edition; ISBN: 978-0201835953]</p>
<p>The Pragmatic Programmer [Andrew Hunt, David Thomas; Addison-Wesley Professional; 1999; ISBN: 978-0201616224]</p>
Views: 893]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2011/04/27/business-software-development/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to archive Drupal as a static site?</title>
		<link>http://gablog.eu/void/2011/03/27/how-to-archive-drupal-as-a-static-site/</link>
		<comments>http://gablog.eu/void/2011/03/27/how-to-archive-drupal-as-a-static-site/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 19:01:35 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[drupal]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=50</guid>
		<description><![CDATA[Here is the summary how I&#8217;ve managed to archive my Drupal weblog before migrating to WordPress. To do this, you should never put your blog/site to the root of your URL, i.e. example.com/ . Instead, put it under a directory like example.com/foo so you can it archive it under this address and put up your [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the summary how I&#8217;ve managed to archive my <a href="http://gablog.eu/online">Drupal weblog</a> before migrating to <a href="http://gablog.eu/void">WordPress</a>. To do this, you should never put your blog/site to the root of your URL, i.e. example.com/ .<br />
Instead, put it under a directory like example.com/foo so you can it archive it under this address and put up your new site at example.com/bar . The root address should always redirect to the current site.<br />
Thanks to <a href="http://drupal.org/node/27882">http://drupal.org/node/27882</a> and <a href="http://www.starbowconsulting.com/blog/tao/replacing-live-drupal-site-static-archive">http://www.starbowconsulting.com/blog/tao/replacing-live-drupal-site-static-archive</a> .</p>
<p>Steps to make the site ready being archived:</p>
<ul>
<li>Disabled all commenting with <code>update node set comment = '1'</code></li>
<li>For each content-type, set the comment controls to &#8220;Do not display.&#8221;</li>
<li>Disable search completely, also in the theme</li>
<li>Remove all dynamic blocks, login, register, who&#8217;s online, actual links, feed links etc.</li>
<li>Put up a static block and a sticky post stating this is a static archive with a link to the new one.</li>
<li>Remove all spam comments and spam links before archiving or search engines will ignore you.
</ul>
<p>Then I used <a href="http://www.httrack.com/">httrack</a> to archive my site:<br />
<code>httrack http://example.com/foo -W -O "~/static_archive"  -%v --robots=0</code></p>
<p>That&#8217;s it. Double check your logs, I&#8217;ve had some old nodes giving a server error because of an outdated plugin.<br />
Now you can remove your Drupal site and drop the corresponding tables. But there is one thing left:<br />
If you used pretty URLs, like /node/4, you will need to set up redirects to show the archived html files instead (/node/4.html).<br />
You might also want to redirect the RSS feeds to migrate your RSS subscribers to your new site and its feed.</p>
<p><code lang="htaccess"><br />
<IfModule mod_rewrite.c><br />
RewriteEngine on<br />
# If we are accessing root, redirect to index.html<br />
RewriteCond %{REQUEST_URI} ^/foo/$<br />
RewriteRule ^(.*)$ index.html [L]<br />
# Redirect RSS feeds<br />
RewriteCond %{REQUEST_URI} ^/foo/rss.xml$<br />
RewriteRule ^(.*)$ http://example.com/foo/feed/ [L]<br />
RewriteCond %{REQUEST_URI} /foo/feed$<br />
RewriteRule ^(.*)$ http://example.com/foo/feed/ [L]<br />
RewriteCond %{REQUEST_URI} /foo/.*/feed$<br />
RewriteRule ^(.*)$ http://example.com/foo/feed/ [L]<br />
# If we are accessing a page without a "." in it, append .html to  the end.<br />
RewriteCond %{REQUEST_URI} !\.<br />
RewriteRule ^(.*)$ $1.html<br />
</IfModule><br />
</code></p>
Views: 8452]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2011/03/27/how-to-archive-drupal-as-a-static-site/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Import XLS/CSV into MS SQL</title>
		<link>http://gablog.eu/void/2010/10/18/import-xlscsv-into-ms-sql/</link>
		<comments>http://gablog.eu/void/2010/10/18/import-xlscsv-into-ms-sql/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 12:44:04 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=44</guid>
		<description><![CDATA[What about the simple task of importing a tabular Microsoft Excel Sheet into a Microsoft Transact SQL table? After paying thousands of dollars in license fees, this will take you a day! And you will need OpenOffice to do that :) First google &#8220;import xls into mssql&#8221; will give you a simple solution: SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>What about the simple task of importing a tabular Microsoft Excel Sheet into a Microsoft Transact SQL table?<br />
After paying thousands of dollars in license fees, this will take you a day! And you will need OpenOffice to do that :)</p>
<p>First google &#8220;import xls into mssql&#8221; will give you a simple solution:</p>
<pre class="brush:sql">
SELECT * INTO XLImport5 FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database=C:\test\xltest.xls', 'SELECT * FROM [Customers$]')
</pre>
<p>That will not work! Jet provider is not supported on 64bit! Yeah, Microsoft is not supporting 64bit users of its enterprise database solution. Thank you very much. (Just google how many ppl are ranting about the lack of this&#8230;)</p>
<p>OK! No problem I&#8217;m going to write a program that generates INSERT INTO statements from a CSV export, here you go:</p>
<pre class="brush:java">
package eu.gablog.csv2sql;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.LinkedList;
import java.util.List;

import au.com.bytecode.opencsv.CSVReader;

public class CSV2SQL {

    private static final boolean truncate = false;
    private static final String src = "D:\\tmp\\src.csv";
    private static final String dst = "D:\\tmp\\dst.sql";
    //private static final String DB = "HCOM_EMEA.dbo.HCOM_BOOKING_POSTPAY_MAPPING";
    private static final String DB = "MHOTEL.dbo.PROPERTY";

    // GENERIC VERSION: first row contains column names
    public static void main(String[] args) throws IOException {
        // PARSE ALL ROWS
        CSVReader csvRows = new CSVReader(new FileReader(src), ';', '"', 0);
        String[] nextLine;
        List<String[]> rows = new LinkedList<String[]>();
        while ((nextLine = csvRows.readNext()) != null) {
            rows.add(nextLine);
        }

        // PREPARE OUTPUT SQL
        BufferedWriter out = new BufferedWriter(new FileWriter(new File(dst), false));
        if (truncate) {
            out.write("DELETE FROM " + DB + ";");
            out.newLine();
        }

        // INSERT STATMENT
        int rowCount = 0;
        String insertInto = "";
        for (String[] row : rows) {
            if (rowCount == 0) {
                insertInto = parseColumns(row);
            } else {
                String insert = parseRow(row);
                out.write(insertInto + " VALUES " + insert + ";");
                out.newLine();
            }
            rowCount++;
        }
        out.close();
        System.out.println("DONE: " + rowCount + " lines parsed from " + src + " to " + dst);
    }

    private static String parseColumns(String[] columns) throws IOException {
        StringBuilder result = new StringBuilder();
        result.append("INSERT INTO " + DB + " (");
        boolean first = true;
        for (String column : columns) {
            if (!first) {
                result.append(", ");
            }
            result.append("[" + column + "]");
            first = false;
        }
        result.append(")");
        return result.toString();
    }

    private static String parseRow(String[] row) throws IOException {
        StringBuilder result = new StringBuilder();
        result.append("(");
        boolean first = true;
        Double d;
        for (String column : row) {
            if (!first) {
                result.append(", ");
            }
            if (column.isEmpty()) {
                column = "NULL";
            }
            if ("NULL".equalsIgnoreCase(column)) {
                // NULL
                result.append(column);
            } else if (isLong(column) != null) {
                // LONG
                result.append(column);
            } else if ((d = isDouble(column)) != null) {
                // DOUBLE
                result.append(d.toString());
            } else {
                // STRING VALUE
                result.append("'" + escape(column) + "'");
            }
            first = false;
        }
        result.append(")");
        return result.toString();
    }

    private static Long isLong(String str) {
        try {
            return Long.parseLong(str);
        } catch (NumberFormatException nfe) {
            return null;
        }
    }

    private static Double isDouble(String str) {
        try {
            DecimalFormat df = new DecimalFormat();
            DecimalFormatSymbols dfs = new DecimalFormatSymbols();
            dfs.setDecimalSeparator(',');
            df.setDecimalFormatSymbols(dfs);
            Double d = df.parse(str).doubleValue();
            if (!d.toString().replace('.', ',').equals(str)) {
                d = null;
            }
            return d;
        } catch (ParseException e) {
            return null;
        }
    }

    private static String escape(String str) {
        String result;
        result = str.replaceAll("'", "''");
        return result;
    }

}
</pre>
<p>You think you can use that just this easily? Of course not! Microsoft Excel does not know anything about UTF-8 in 2010 AD!<br />
CSV export has some random encoding just to fuck with you for the fun. No option for having it in UTF-8.<br />
Just fire up OpenOffice, go to Sava As, and enjoy the beautiful options of selecting the export&#8217;s encoding. Now use the converter on this input.</p>
Views: 1122]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2010/10/18/import-xlscsv-into-ms-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Captcha for CakePHP 1.3 with KCAPTCHA</title>
		<link>http://gablog.eu/void/2010/09/08/captcha-for-cakephp-1-3-with-kcaptcha/</link>
		<comments>http://gablog.eu/void/2010/09/08/captcha-for-cakephp-1-3-with-kcaptcha/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 12:49:41 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=4</guid>
		<description><![CDATA[We are going to use KCAPTCHA to generate Captchas and verify them in form submissions in CakePHP. Look at phpinfo(), you will need First, download KCAPTCHA and put the directory &#8220;kcaptcha&#8221; from the .zip into app/vendors/. Insert this into any view you want to have a captcha on: We load the image with a semi-random [...]]]></description>
			<content:encoded><![CDATA[<p>We are going to use KCAPTCHA to generate Captchas and verify them in form submissions in CakePHP. Look at phpinfo(), you will need </p>
<p>First, download <a href="http://www.captcha.ru/en/kcaptcha/">KCAPTCHA</a> and put the directory &#8220;kcaptcha&#8221; from the .zip into app/vendors/.</p>
<p>Insert this into any view you want to have a captcha on:</p>
<pre class="brush:html">
<div>
<div style="float: left;">
        <img alt="captcha" class="captcha" />
    </div>
<div style="float: left;">
<?php echo $form->input('captcha', array('label' => __('Nem vagyok robot: <br/>', true))); ?>
    </div>
</div>

<script type="text/javascript">
    $(function() { // jQuery, onload
        $(".captcha").attr('src', forUrl('/ajax/captcha/' + new Date().getTime()));
    }
</script>
</pre>
<p>We load the image with a semi-random URL, ensuring to always load a new one. In my case, it will be loaded from AjaxController:</p>
<pre class="brush:php">
function captcha($random = null) {
        $this->layout = null;
        $thiy->$autoRender = false;
        //$this->RequestHandler->setContent('jpeg', 'image/jpeg'); // use this if your mime-type is incorrect

        App::import('Vendor', 'kcaptcha/kcaptcha');
        $kcaptcha = new KCAPTCHA(); // renders the captcha image fully here
        $this->Session->write('captcha', $kcaptcha->getKeyString());
    }
</pre>
<p>As you can see, displaying a captcha by fetching it, immediately stores the captcha&#8217;s solution in the &#8216;captcha&#8217; session variable.</p>
<p>When you process the submitted form, where you have included the captcha, use this (Component) function to check the submitted value against the one stored in the session. </p>
<pre class="brush:php">
function checkCaptcha($text) {
        $captcha = $this->Session->read("captcha");
        $this->Session->delete("captcha"); // SECURITY: must clear captcha to avoid repatcha
        if (empty($captcha) || $captcha != $text) {
            return false;
        }
        return true;
    }
</pre>
<p>Be aware, that upon checking, regardless of the match, the captcha must be destroyed (removed from the session). Otherwise recaptcha is possible (re-submission over and over again with a first valid captcha).</p>
<p> At last, kcaptcha_config.php to finetune your images.</p>
Views: 1563]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2010/09/08/captcha-for-cakephp-1-3-with-kcaptcha/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Twitter OAUTH</title>
		<link>http://gablog.eu/void/2010/07/02/twitter-oauth/</link>
		<comments>http://gablog.eu/void/2010/07/02/twitter-oauth/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 00:13:53 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=15</guid>
		<description><![CDATA[Twitter will phase out the widely-used HTTP basic authentication by August 2010. The amount of working examples online makes me believe that most applications that make use of the Twitter API is not migrated yet. Even the simplest action will requires to use OAUTH. This tutorial will guide you through the authentication process. In the [...]]]></description>
			<content:encoded><![CDATA[<p>Twitter will <a href="http://apiwiki.twitter.com/Authentication">phase out</a> the widely-used HTTP basic authentication by August 2010. The amount of working examples online makes me believe that most applications that make use of the Twitter API is not migrated yet. Even the simplest action will requires to use <a href="http://oauth.net/core/1.0/#anchor9">OAUTH</a>.</p>
<p>This tutorial will guide you through the authentication process. In the end of our example we will get hold four secret keys in our hands that can be used at any later time to access the API with the same credentials again. You can download all files <a href="http://gablog.eu/void/?attachment_id=26">here</a>. (You&#8217;ll need CURL to be enabled in PHP.)<br />
The walk through corresponds to the &#8220;Desctop Clients&#8221; scenario in the first <a href="http://apiwiki.twitter.com/Authentication">link</a>.</p>
<p>1. Go to <a href="http://twitter.com/apps/">http://twitter.com/apps/</a> and click &#8220;Register new application&#8221;. For Application Type choose Browser and for the callback URL, the URL of confirm.php.<br />
Now you receive a Consumer Key and a Consumer Token. Put them into secret.php.</p>
<p>2. Fire up index.php. You can double check your Consumer credentials here. First you&#8217;ll see only one link to authorize via twitter. Follow that, confirm the access.</p>
<p>3. Twitter&#8217;ll redirect you back to confirm.php. But you also gained now the <strong>Provider Token and Secret</strong>! Put them as printed on the screen into secret.php.</p>
<p>4. Going back to index.php you&#8217;ll see that you have no all the keys you need. You can check it on random.php, that uses them. Store this four keys securely. They won&#8217;t be revoked, unless the twitter profile explicitly removes the app. It&#8217;ll work even after changing the password.</p>
<p>Having just this four keys, using the same API classes, updating the status is as easy as this:</p>
<pre class="brush:php">
<?php

include 'EpiCurl.php';
include 'EpiOAuth.php';
include 'EpiTwitter.php';

class Twitter {

    var $consumer_key = '';
    var $consumer_secret = '';
    var $provider_token = '';
    var $provider_secret = '';
    var $twitterObj;
    var $maxLength = 140;

    function __construct() {
        $this->twitterObj = new EpiTwitter($this->consumer_key, $this->consumer_secret, $this->provider_token, $this->provider_secret);
    }

    /** Tweets the message with '...' shortening. If $url given, appends it.
     *
     * @param <type> $message
     * @param <type> $url
     */
    function tweet($message, $url = null) {
        $length = $this->maxLength - (empty($url) ? 0 : mb_strlen($url)+1);
        if (mb_strlen($message)>$length) {
            $length -= 3;
            $fix = "...";
        } else $fix = "";
        $message = mb_strcut($message, 0, $length).$fix;
        if (!empty($url)) {
            $message .= " ".$url;
        }
        return $this->twitterObj->post_statusesUpdate(array('status' => $message));
    }

}
?>
</pre>
<p>If you don&#8217;t store the Provider&#8217;s token and secret, instead storing it in the session, you can use Twitter accounts to authenticate profiles on your site.</p>
Views: 722]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2010/07/02/twitter-oauth/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Hello world!</title>
		<link>http://gablog.eu/void/2010/06/21/hello-world/</link>
		<comments>http://gablog.eu/void/2010/06/21/hello-world/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 21:46:50 +0000</pubDate>
		<dc:creator>GaB</dc:creator>
				<category><![CDATA[Hacks]]></category>

		<guid isPermaLink="false">http://gablog.eu/void/?p=1</guid>
		<description><![CDATA[It&#8217;s about time. Finally I managed to migrate my blog engine to WordPress instead of Drupal. This is mainly a technical decision: Blog engines regularly receive software updates. Updating Drupal is a real royal pain in the ass. Every two weeks you need to disable your site, disable all plugins, unzip the core and all [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s about time. Finally I managed to migrate my blog engine to WordPress instead of Drupal.</p>
<p>This is mainly a technical decision:</p>
<ul>
<li>Blog engines regularly receive software updates. Updating Drupal is a real royal pain in the ass. Every two weeks you need to disable your site, disable all plugins, unzip the core and all plugins individually, copy them into place, run update tasks on the database, enable site, fix broken plugins&#8230; I prefer just to click on update in the admin panel of WordPress.</li>
<li>Input filters in Drupal allow you to configure all sort of orders, priorities, exceptions and more. Unfortunately I never found a combination where all these filters work together not messing up included source code in my posts.</li>
<li>Druapl is a heavyweight platform for arbitrary web applications, community pages, forums etc. I need only simple blog engine.</li>
<li>WordPress has all the customization I need, its admin panel even allows me to edit any plugin code in the browser. But once configured I do not want to spend any time on updates and integration.</li>
</ul>
<p>New posts will be available at <a href="http://gablog.eu/void">http://gablog.eu/void</a>. Unfortunately I can&#8217;t migrate my posts. I&#8217;ll make a static page out of what I have in Drupal, available at the original URL: <a href="http://gablog.eu/online">http://gablog.eu/online</a>.</p>
Views: 552]]></content:encoded>
			<wfw:commentRss>http://gablog.eu/void/2010/06/21/hello-world/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

