Category Archives: Software Development

This category contains all my posts about software development. Tutorials, solutions to problems I’ve met, interesting things I’ve stumbled over, code samples, stuff I don’t want to forget, et cetera.

PHP: Simple directory recursion

Keep running into scenarios where I need to scan through a file system and it’s actually pretty simple if you just know what classes to use. So… note to self and others:

// This should return false if there is something you want excluded
function filter($file, $key, $iterator)
{
    $exclude = array('.git');
    return ! in_array($file->getFilename(), $exclude);
}

// Recursive directory iterator for current directory, ignoring dots
$it = new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS);
// Wrapped by a filtering iterator with our filter function
$it = new RecursiveCallbackFilterIterator($it, 'filter');
// Wrapped by an iterator which automatically traverses children for us
$it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);

// And then just loop :)
foreach($it as $file)
{
    echo str_repeat("\t", $it->getDepth())
        . $file->getRealPath()
        . PHP_EOL;
}

This skips the annoying dots, properly excludes directories you don’t want and pretty much works the way it should.

XSLT: Load XML or other text from external sources

Just discovered you can pull in external XML and other kinds of text directly through standard XSLT 2.0 methods. So here’s a note to self on how.

Documentation

Example usage

<!-- Single string URI -->
<copy-of select="doc('http://www.w3schools.com/xml/note.xml')"/>

<!-- One or more URI from items, in this case a variable -->
<variable name="uri" select="'http://www.w3schools.com/xml/note.xml'"/>
<copy-of select="document($uri)"/>

<!-- Unparsed text, in this case escaped HTML -->
<copy-of select="unparsed-text('http://example.com')"/>

XSLT: Pull duplicate namespace declarations up towards root node

Sometimes XML becomes a bit weird with namespace declarations all over the place. This XSLT cleans that up. Stumbled upon in a StackOverflow answer I don’t find anymore and put here so I know where to find it in the future.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="@* | text() | processing-instruction() | comment()">
        <xsl:copy/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:copy copy-namespaces="no">
            <xsl:for-each-group group-by="local-name()" select="descendant-or-self::*/namespace::*">
                <xsl:copy-of select="."/>
            </xsl:for-each-group>
            <xsl:apply-templates select="@* , node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Example

Input

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
   <soap:Header>
      <wsa:MessageID soap:mustUnderstand="0">uuid:7fa12310-5db4-11e3-ae24-a3c913f2629d</wsa:MessageID>
      <wsa:To soap:mustUnderstand="0">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
   </soap:Header>
   <soap:Body>
      <ns1:getTicket xmlns:ns1="http://api.example.com/some-webservice">
         <cus:msisdn xmlns:cus="http://api.example.com/some-webservice" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">00000000</cus:msisdn>
         <cus:ticket xmlns:cus="http://api.example.com/some-webservice" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">171</cus:ticket>
      </ns1:getTicket>
   </soap:Body>
</soap:Envelope>

Output

<soap:Envelope xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
       xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
       xmlns:ns1="http://api.example.com/some-webservice"
       xmlns:cus="http://api.example.com/some-webservice"
       xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header>
        <wsa:MessageID soap:mustUnderstand="0">uuid:7fa12310-5db4-11e3-ae24-a3c913f2629d</wsa:MessageID>
        <wsa:To soap:mustUnderstand="0">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
    </soap:Header>
    <soap:Body>
        <ns1:getTicket>
            <cus:msisdn>00000000</cus:msisdn>
            <cus:ticket>171</cus:ticket>
        </ns1:getTicket>
    </soap:Body>
</soap:Envelope>

If anyone know how to adjust it to also merge the duplicated prefixes ns1 and cus, do let me know :)

Tail less

I keep seeing people typing these lines in the console:

$ tail /path/to/some.log
$ tail -f /path/to/some.log

This is often a dumb thing to do. Why? Because you can’t really do anything with tail. What if you discovered you needed to look at something right above the lines you got printed out? Or what if you were -f’ing and something flew past you that you needed to investigate further? You’d have to leave tail and run it again with more lines or use a different tool instead. Not very practical.

What more people should do is to use less tail and more less :)

$ less /path/to/some.log

Things you can do with less

Key

Function

Up one line

Down one line
b

Up one page
space

Down one page
g

Beginning of file
G

End of file
F

Follow
ctrl + c

Stop follow
q

Quit
/

Search forward
?

Search backwards
n

Next search result
N

Previous search result

Much more flexible and handy than tail! Know your tools ;) Now back to work…

Java: Ignore SSL certificate errors

Not that we’d do such a thing of course, but here’s how to ignore all SSL certificate errors in Java.

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
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.*;

/**
 * A {@link X509TrustManager} and {@link HostnameVerifier} which trust everything.
 *
 * @author    Torleif Berger
 * @license   http://creativecommons.org/licenses/by/3.0/
 * @see       http://www.geekality.net/?p=2408
 */

public final class TrustAllCertificates implements X509TrustManager, HostnameVerifier
{
    public X509Certificate[] getAcceptedIssuers() {return null;}
    public void checkClientTrusted(X509Certificate[] certs, String authType) {}
    public void checkServerTrusted(X509Certificate[] certs, String authType) {}
    public boolean verify(String hostname, SSLSession session) {return true;}
   
    /**
     * Installs a new {@link TrustAllCertificates} as trust manager and hostname verifier.
     */

    public static void install()
    {
        try
        {
            TrustAllCertificates trustAll = new TrustAllCertificates();
           
            // Install the all-trusting trust manager
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null,
                    new TrustManager[]{trustAll},
                    new java.security.SecureRandom());         
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // Install the all-trusting host verifier
            HttpsURLConnection.setDefaultHostnameVerifier(trustAll);
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new RuntimeException("Failed setting up all thrusting certificate manager.", e);
        }
        catch (KeyManagementException e)
        {
            throw new RuntimeException("Failed setting up all thrusting certificate manager.", e);
        }
    }
}

Usage

TrustAllCertificates.install();

HttpURLConnection c = (HttpURLConnection) url.openConnection();
// ...and so on and so forth

Order WordPress RSS feed by modified rather than published

Adding the following to the functions.php of your theme should make the posts in your WordPress RSS feed sort by when the post was last modified rather than when it was published. Useful in some cases when you for example want to push out updated posts as well.

function wpse49312_alter_the_query( $request )
{
    $dummy_query = new WP_Query();
    $dummy_query->parse_query($request);

    if($dummy_query->is_feed())
        $request['orderby'] = 'modified';

    return $request;
}
add_filter('request', 'wpse49312_alter_the_query');