All posts by cp

A simple WordPress plugin

As you may noticed I use WordPress for my blog. This is an unbelievable great piece of software. It has uncountable possibilities for enhancements and as soon as you begin to explore these, you start adding some of them to your own blog. One of the plugins I added was WPtouch. This plugin wraps your blog into a theme for mobile devices if they are detected. This works for the iPhone, the Android platform or even Palms webOS. The theme is styled in a way it makes the content more readable on such (screen) limited devices and moves the menus to some extra place.

Why writing a plugin if there are so many

On our web server we are using Power PHLogger for a simple user statistic tracking. Unfortunately this software isn’t maintained anymore, but it does it job very well. To use it you have to embed some JavaScript code and a blind image to every website you want to track. My first try was to add this code to the theme I use. This worked ok, but I soon realized that this has to be done on every update of the theme. Additionally this doesn’t work with plugins like WPtouch, as there the whole theme is replaced. I searched for a plugin which takes this job, but I didn’t find one. So what, I’m a programmer, time for writing it myself.

Creating the necessary bits of code

Plugins in WordPress are located at the wp-content/plugins directory below the WordPress installation path. You have to choose a name, I used phlogger, and create a directory with that name. The plugin itself is written in PHP and named like the directory with the php extension. As the title says, it’s a simple plugin with one public method only, as shown in the following code.

<?php
/*
Plugin Name: phlogger
Plugin URI:
Description: Adds the power phlogger code to the footer.
Version: 0.1
Author: Christian Pötzsch
Author URI: http://www.64k-tec.de
*/

add_filter('wp_footer', 'phlogger_footer');

function phlogger_footer()
{
 $l = '<script type="text/'."n".'mce:1'."n";

 echo $l;
}
?>

The method just outputs the code for the phlogger tracking. WordPress executes this method because of the add_filter call. wp_footer is the filter keyword for content which should be added to the footer of a webpage, just before the </body> tag. The comment on the top of the file isn’t only there for cosmetic reasons. It’s parsed by WordPress and shown in the Plugin admin page of your blog settings. So it have to be there.

Of course I could have been adding methods for setting the phlogger link or the user name, but for my case this wasn’t necessary. For more information on writing WordPress plugins have a look at the good documentation.

Conclusion

Starting to write WordPress plugins is easy. It makes even sense for so simple tasks like this, because it offers the possibility to inject code (and functionality) without changing WordPress or the theme itself.

FRITZ!Box tuning part 1: Enable remote access over ssh

Recently I changed my Internet service provider to Kabel Deutschland which offers some really good bandwidth for a reasonable price. You get 32 MBit in the download direction and 2 Mbit in the upload direction. Additionally to this you can order a FRITZ!Box 7270 which allows you to use VoIP for the phone part. As I always try to maximize the usage of new hardware I started to explore what is possible with this combination. In this post I will explain how you get access to your FRITZ!Box using ssh. Following this post, some articles about how you can turn the FRITZ!Box into a OpenVPN server and how you can use the VoIP access point remotely from any computer having a VoIP software installed, will be done. As I said the hardware used is a FRITZ!Box Fon WLAN 7270 with the firmware 54/74.04.80 from 2009/12/15 which is an official one from AVM. Other firmware versions may work also, but I haven’t tested that. The following topics are all for advanced user. So if you aren’t in touch with Linux or start asking what the hell is vi and how get I out of it, stop reading now. All the information in this and the following posts are based on several websites I found in the Internet. Mainly this are some forum entries at http://www.ip-phone-forum.de, the series about the FRITZ!Box at http://www.tecchannel.de, the posts on http://www.teamarbyte.de, the blog at http://www.realriot.de and this article at http://www.cswpro.de. So thanks to all the people for sharing this kind of information. Before we start some words of caution: It’s easily possible to render the FRITZ!Box unusable. So there is no warranty of any kind if you do some of the things mentioned in this blog. Also I’m not responsible for anything happen to your FRITZ!Box or the Internet connection. After all making a backup of your current configuration might be a good idea.

Preparing the FRITZ!Box

First of all you should register an account at http://www.dyndns.com or any other service for dynamic IP resolution. You can then add this information to the “DynamicDNS” tab of the Internet settings in the FRITZ!Box web frontend. This will allow you to connect to your FRITZ!Box without knowing the IP after a reconnect. Lets use us xtestx.dyndns.org in the following examples. Next you need telnet access to the FRITZ!Box to make the initial configuration for the ssh server. Enabling telnet is as simple as calling #96*7* with a local connected phone. To disable the telnet daemon later you call #96*8*. Now you need a usbstick where all the software will be installed on and which have to be connected to the FRITZ!Box all the time. In principle the size doesn’t matter, around 5 MBytes free space should be enough. Time to connect to the FRITZ!Box for the first time. A simple telnet fritz.box should do it.

Installation and configuration of the ssh server

For the ssh server software dropbear is used. You can get a prepared version for the FRITZ!Box from the spblinux server.

cd /var/tmp
wget http://www.spblinux.de/fbox.new/cfg_dropbear
chmod u+x cfg_dropbear

After downloading, the server has to be installed on the usbstick by executing

./cfg_dropbear usb_install

In my case the software is installed into /var/media/ftp/FLASH-DISK-01/addons. Now we will create a host key which will be reused even after a reboot of the FRITZ!Box.

cd /var/media/ftp/FLASH-DISK-01/addons
dropbear/bin/dropbearkey -t rsa -f dropbear/etc/sshd_rsa_host_key

The FRITZ!Box has initial no root password entry. We have to create one and save the password hash for later usage.

passwd
cat /etc/passwd

You have to note the part between root: and the next colon.

Putting all together

The initial starting point for all modifications on the FRITZ!Box is a file called /var/flash/debug.cfg. Its executed on every boot after all the other services are started. We will use it only to start a script which is located on the usbstick. This makes sure that even after a firmware upgrade our changes are not lost. The content looks like the following:

# execute the start script which is on the usb stick
/var/media/ftp/FLASH-DISK-01/addons/startup.sh

Please note that you have to use the nvi to edit files on the flash device from the FRITZ!Box, cause all files there are marked as non regular. The startup.sh will do all the work necessary for preparing and starting the ssh server. The content is:

#!/bin/sh
# whats the base usb directory
BASE=/var/media/ftp/FLASH-DISK-01/addons

# change to a temporary directory
cd /var/tmp

# install and start dropbear with our host key
${BASE}/cfg_dropbear usb_install
/bin/dropbear -E -r ${BASE}/dropbear/etc/sshd_rsa_host_key

# set passwords
echo 'root:XXXXXX:0:0:root:/var/tmp/:/bin/sh' > /var/tmp/passwd
echo 'ftpuser:any:1000:0:ftp user:/var/media/ftp:/bin/sh' >> /var/tmp/passwd

# add fritz box itself in resolv.conf to resolv dhcp attached machines in your network
echo "nameserver 192.168.220.1" >> /var/tmp/resolv.conf

You have to replace XXXXXX by the password hash you created above. In my case the network is in the 192.168.220.0/24 subnet and the FRITZ!Box has the IP 192.168.220.1. You have to adjust the name server entry to your environment. After a reboot which could be initiated with reboot you should be able to access your FRITZ!Box over ssh.

To allow connections from the outside of your home you need to change the forward rules of the internal FRITZ!Box firewall. Unfortunately you can’t add this rule using the web frontend cause it isn’t allowed to add rules which targeting the FRITZ!Box itself. Most of the settings for the FRITZ!Box configuration are located in a file called /var/flash/ar7.cfg. Use nvi to edit it and search for the string forwardrules. If this string is missing you could temporary create a rule in the web frontend, which will you later remove again. You have to change the line so that it looks like this:

forwardrules =
               "tcp 0.0.0.0:7777 0.0.0.0:22 0 # SSH-Server";

Here the connection port is 7777, but of course could you use any valid port number. You could also add more rules by separating them with a comma. To make the configuration change happen the execution of ar7cfgchanged is sufficient.

Conclusion

With this setup its possible to connect to the FRITZ!Box with the very secure ssh protocol from inside of your home environment and from the outside. This makes it easily possible to change parameters without manually starting the telnet daemon which is in addition very insecure. Don’t forget to remove any temporary rules from the ar7.cfg file and to disable the telnet daemon with the procedure explained above. Stay tuned for the next post about going one step further and making the FRITZ!Box an OpenVPN connection point for your internal network.

Update

There is a new article about installing ssh on the FRITZ!Box. If you are interested have a look at this post.

Integrating native Cocoa controls into Qt

Making applications looking and feeling as native as possible on every supported platform is one of my main responsibilities within the VirtualBox development. Most of the work therefor is done by the Qt framework which we are using for our GUI. Qt does a nice job for Windows and most of the currently popular X11 window toolkits used under Unix and Linux. They are behaving and looking similar in many ways which make it easy to develop for both architectures. Unfortunately this doesn’t count in any case for Mac OS X, which often uses very different approaches or uses very specialized controls to reach a specific aim. One of this controls is the Mac OS X help button who every Mac user is familiar with. If an Mac OS X application doesn’t use this help button, it breaks the design rules and the application, lets say, smells a little bit “under designed”. The following little example shows how to integrate a NSButton seamlessly into your Qt application.

Qt make it easy

Nokia added the QMacCocoaViewContainer class with Qt 4.5. This class make it easy to integrate any NSView or deviate of the NSView class into the QWidget hierarchy of an application. The best integration is archived if one deviate from QMacCocoaViewContainer. To use Cocoa code and C++ classes at once the Objective-C++ compiler is necessary. The gcc uses the Objective-C++ compiler automatically if the source file ends with mm. We start with the C++ interface which looks like the following:

ADD_COCOA_NATIVE_REF(NSButton);
class CocoaHelpButton: public QMacCocoaViewContainer
{
    Q_OBJECT
public:
    CocoaHelpButton(QWidget *pParent = 0);
    QSize sizeHint() const;
    void onClicked();
signals:
    void clicked();
private:
    NativeNSButtonRef m_pButton;
};

For any Qt programmer this class definition is easy to understand. The only unusual is the ADD_COCOA_NATIVE_REF macro call and the NativeNSButtonRef type itself. One could say NativeNSButtonRef should be NSButton* and you are done, but it’s not that easy. The reason for this is that the include file will be included first in the Objective-C++ source code file, where the NSButton* definition wouldn’t be a problem, but secondly in every C++ source file which will use the CocoaHelpButton, where on the other side any Cocoa code is forbidden. The ADD_COCOA_NATIVE_REF macro avoid this problem by expanding NativeNSButtonRef to NSButton* if Objective-C++ code is compiled and to void* if C++ code is compiled. The macro itself looks like this:

#ifdef __OBJC__
# define ADD_COCOA_NATIVE_REF(CocoaClass) 
    @class CocoaClass; 
    typedef CocoaClass *Native##CocoaClass##Ref
#else /* __OBJC__ */
# define ADD_COCOA_NATIVE_REF(CocoaClass) typedef void *Native##CocoaClass##Ref
#endif /* __OBJC__ */

The advantage of using such a macro is that one can use all methods of the NSButton in the Cocoa part of the source code without any casting.

A little bit of Cocoa

The initialization of the CocoaHelpButton class is straight forward as seen in the next code part:

CocoaHelpButton::CocoaHelpButton(QWidget *pParent /* = 0 */)
  :QMacCocoaViewContainer(0, pParent)
{
    m_pButton = [[NSButton alloc] init];
    [m_pButton setTitle: @""];
    [m_pButton setBezelStyle: NSHelpButtonBezelStyle];
    [m_pButton setBordered: YES];
    [m_pButton setAlignment: NSCenterTextAlignment];
    [m_pButton sizeToFit];
    NSRect frame = [m_pButton frame];
    frame.size.width += 12; /* Margin */
    [m_pButton setFrame:frame];
    /* We need a target for the click selector */
    NSButtonTarget *bt = [[NSButtonTarget alloc] initWithObject: this];
    [m_pButton setTarget: bt];
    [m_pButton setAction: @selector(clicked:)];
    /* Make sure all is properly resized */
    resize(frame.size.width, frame.size.height);
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}

QSize CocoaHelpButton::sizeHint() const
{
    NSRect frame = [m_pButton frame];
    return QSize(frame.size.width, frame.size.height);
}

void CocoaHelpButton::onClicked()
{
    emit clicked(false);
}

This set up the NSButton object and make sure that everything has the right size. As shown there, to make a standard button a help button the bezel style has been set to NSHelpButtonBezelStyle. To get the click notification the wrapper class NSButtonTarget is necessary.  As highlighted in the code above the target action is set to the selector “clicked”.  The NSButtonTarget class looks as follow:

@interface NSButtonTarget: NSObject
{
    CocoaHelpButton *m_pTarget;
}
-(id)initWithObject:(CocoaHelpButton*)object;
-(IBAction)clicked:(id)sender;
@end
@implementation NSButtonTarget
-(id)initWithObject:(CocoaHelpButton*)object
{
    self = [super init];
    m_pTarget = object;
    return self;
}
-(IBAction)clicked:(id)sender;
{
    m_pTarget->onClicked();
}
@end

If you put all this together and add the CocoaHelpButton class to your project you will get some output like this:

More integration could be reached by adding wrapper methods for e.g. setting the tooltip, but this is left out as an exercise for the reader.

Conclusion

For more complex controls like a NSSearchField more interaction with Cocoa will be necessary. On the other hand this little excursion to the Cocoa world should make it easy for everyone to add shiny new Mac OS X controls to the own Qt application.