Sunday, March 23, 2008

Adjusting wallpapers on dual monitor configuration easy


I have TFT monitor with 1280x1024 resolution and TV connected in nvidia twin view configuration with TV's resolution of 800x600. Whenever I want to set up a desktop wallpaper on Gnome, I must adjust it, because Gnome "sees" my desktop as one large 2080x1024 desktop. So, I must manually open wallpaper in Gimp and create another picture that contains two wallpaper next to each other, one with 1280x1024 dimension, and another one, with 800x600 dimensions right of the first one. So, I decided that that's enough. So I utilized imagemagick to accomplish this and put convinient function in my .bashrc file. Here it is:
make_wallpaper(){
    convert -background white "$1" -resize 1280x1024 \( "$1" -resize 800x600 \) +append "$2";
}

Of course, background color isn't neccesary since it is not visible, I just put it as a reminder. All I have to do now is to call:
make_wallpaper original.png my.png

Sweet, ain't it;)

Saturday, March 15, 2008

JspWiki export from OpenOffice 2.3

If you have Open Office 2.3, you probably noticed that you can export your document to Media Wiki format (with File->Export). I needed JspWiki format, and it turned out, they are fairly similar, so I changed corresponding XSLT file, and present you here way to add JspWiki export. It will work on both Linux and Windows, and it will only work on Open Office version >= 2.3.

First download this zip. This is zip file that should be extracted to your $INSTALL_DIR/share directory, so it should end up probably in:
C:\Program Files\Open Office\share\

if you are using Windows, or, if you are using Linux, it should be:
/usr/lib/openoffice/share


Of course, if this directory doesn't exist on your system, find out where Open Office 2.3 is installed. This will add XSLT files, so Open Office knows how to export to JspWiki, and it will overwrite two files, so this export can be registered in Open Office (so that you will be able to go to File->Export and select JspWiki export from drop down list).

Advanced


How this works? Media Wiki and JspWiki seems to be very different, but they are pretty much the same, except for different markup characters. If you diff against jspwiki/odt2jspwiki.xsl and wiki/odt2jspwiki.xsl, you will find that they differ by only few lines that needs to be modified in order to have JspWiki export that does as much as Media Wiki export. I started by basically copying Media Wiki .xslt and modifying it. This is also the way you should start if you want to add support to Open Office so it can export to wiki format you need. Have fun!

Saturday, March 08, 2008

Changing power button functionality

How often do you use power button to shut down your computer? I never use it, and, even if I would have need to shutdown or restart my computer, I would use GUI way to do it (simply because, it is something that is rarely used, I never remember I could use power button in that split second when I want to shut it down)

But, if you (like me) don't have keyboards with fancy shortcut buttons, why not use that same power button for some shortcut. Or, you can make fun of your Windows friends just by showing what power and mind-boggling functionality Linux have and just waits for yours ideas to unleash it. I think this is great example of that.

I will use Ubuntu to set it up, but, with minor (or even none) modification, this should work on any distro. First you will need, is to remove annoying gnome log-off screen that shows up when you press power button. For this, we will need to change two keys in gconf. Start gconf-editor and change those two keys:
  • /apps/gnome-power-manager/action_button_power
  • /apps/gnome-power-manager/buttons/power
to "nothing" (without quotes). This will disable log-off screen. Now, it's all about editing /etc/acpi/powerbtn.sh to suit your needs. I will give you two possible scenarios, and there are no limits what you can do.

Enable/disable internet (forwarding)

I already had two little script to enable or disable internet to some users I am routing internet to. These are some iptables stuff (something like `iptables -I FORWARD -p ALL -s 192.168.0.122 -j DROP`) and I had to open console, execute it and later enable it. This can be done with this in /etc/acpi/powerbtn.sh:
#! /bin/sh
if [ -f /var/tmp/internet_off ]; then
    /etc/rc.start_internet
    rm /var/tmp/internet_off
else
    /etc/rc.stop_internet
    touch /var/tmp/internet_off
fi
This is stupid script. It checks for existence of file /var/tmp/internet_off that signalizes if forwarding is on. It then executes appropriate scripts. If you have someone dumb enough, you can tell them that they have no internet because your computer is turned off, and what they see on monitor is just a picture, or drop them a story about virtual (wau!) machine that run even when computer is off (everyone heard of vmware) - something like that:) You can even confirm this by pressing button in front of them to enable or disable their internet access.

Starting firefox


I use firefox all day. If I ever want to dedicate any button to any program, that is certainly firefox. But to start GUI program in shell script that is run as root, we need some workarounds. For example, you need to set DISPLAY and XAUTHORITY environment variable.
#! /bin/sh
export DISPLAY=:0
export XAUTHORITY=/home/yourusername/.Xauthority
sudo -u yourusername firefox
But, this script have few defects. If firefox is running, it will launch another windows, and we see 'yourusername' is all around. This is improved version:
#! /bin/sh
USERNAME=yourusername
export DISPLAY=:0
export XAUTHORITY=/home/$USERNAME/.Xauthority

if ps -U $USERNAME -u $USERNAME|grep firefox; then
    sudo -u $USERNAME firefox -new-tab about:blank
else
    sudo -u $USERNAME firefox
fi
If firefox is running, it will just open new empty tab, otherwise it will launch it normally. Also, your username is pulled up as variable, so you just need to change second line to your username and this script will work. Have fun!

Further ideas

Only one function for button is nothing. Maybe we can split two different functionality by defining click and double-click on power button. Simple creating file on first click, and checking if file was created 2 seconds before current time (I will not go into details here). Also, you could use that button to open CD tray, why not:) Like anything in Linux, your creativity is your only limit. Do you have any ideas what to do else with this button? What would you put in /etc/acpi/powerbtn.sh?

Thursday, July 26, 2007

Disabling internet connection to NAT users with redirection and notification


First of all that I want to tell you - this is not for people unfamiliar with Linux, iptables and apache. You really should know exactly what are you doing and this text only needs to give you idea and push you in right direction, because if you're just copying commands, you will not get too far. I'm not trying to scare you, just to point out that I didn't go too far in details. Also, this is a text about Linux as router which utilize iptables and apache, so if you don't have that, you can just read, but not try out. I guess, if you are a guru, you could achieve similar result with other tools besides iptables and apache, but you're on your own then. Let's start.

USAGE


You have Linux router and, while you want to deny your users internet access, you also want to display them page about that. You want to deny your users access to certain sites and, instead of desired site, show them page with warning/notification that they've been naughty little users or that that site is forbidden. Other weird ideas...

BASIC STUFF

Ok, I have small server which (mainly) serves as a router for about 20 users/neighbours and we share internet. Problem is when someone don't want internet for upcoming month or is not there or simple when someone forgets to chip in for internet. Until now, we had simple iptables solution - REJECT all packets and allow only IP addresses (or MAC) that paid for internet with something like this:
iptables -I FORWARD -i ext0 -o ext1 -j DROP
iptables -I FORWARD -p ALL -s 192.168.0.XX -j ACCEPT
iptables -I FORWARD -p ALL -d 192.168.0.XX -j ACCEPT
Then we got the idea that, when someone who didn't pay for internet visit some site get simple page (from ours Apache) telling him that he didn't paid (until now, he only could see his browser stuck while resolving site's hostname). First idea was to hack our server's DNS service, but it would be hell to do, nonextensible and, well...shitty.

So, here is simple, yet effective solution. General idea is to redirect http request packets to our server and show them simple notification page. So, first we will need is iptables stuff. Simple line that redirect specific user would be:
iptables -t nat -I PREROUTING -s 192.168.0.XX -p tcp --dport 80 -j REDIRECT --to-ports 3001
Quick explanation is that all TCP packets from user with IP 192.168.0.XX destined to port 80 would get redirected to port 3001 of our server. This is where we will be putting our apache server to listen (later on). But, hey...wait...this isn't going to work. Why? Because, when user requests (for example) http://www.mozilla.com/en-US/firefox, hostname should first be resolved, e.g. before any packets on port 80 is sent, packets to DNS server is sent. And, if we have:
iptables -I FORWARD -i ext0 -o ext1 -j DROP
then there would be no resolving, no http packets. So, we must allow DNS packets with something like this:
iptables -I FORWARD -s 192.168.0.XX -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 192.168.0.XX -p udp --sport 53 -j ACCEPT
iptables -t nat -I PREROUTING -s 192.168.0.XX -p tcp --dport 80 -j REDIRECT --to-ports 3001
This, in some way is trade-off since our users are now not completely isolated from internet - they got access to DNS servers. OK, first part with redirecting is over - next to setting up apache.

All you need now is to create new virtual host on Apache. YMMV, but here's all I had to do in httpd.conf to make it work:
Listen 192.168.0.1:3001
Listen 127.0.0.1:3001
NameVirtualHost *:3001

<VirtualHost *:3001>
ServerName <ours_servers_LAN_name>
DocumentRoot /var/www/no_net/
RewriteEngine On
RewriteRule ^.* /index.html
<VirtualHost>
Append it to end of httpd.conf, and make new htdocs root folder (here is /var/www/no_net/) with index.html which will show notification that user didn't pay for internet. Port for listening must be same as in iptables redirect command (3001) on which this virtual host work. As you can see, listen directive is only for localhost and our LAN, so this virtual host is not visible from internet. If you look carefully in this VirtualHost directive, you could notice two strange lines:
RewriteEngine On
RewriteRule ^.* /index.html
These lines rewrite everything in URL and replaces it with "/index.html". Why? Because, let's suppose user goes to the site http://www.mozilla.com/en-US/firefox/.
Then it got redirected to 3001 port. From there, user's browser asks for /en-US/firefox/ page which, of course don't exist. Easiest way to gather all GET request is to rewrite them all with mod_rewrite module. Second line does exactly that - with help of regular expression, it replaces anything with "/index.html". All you have to do now is to create index.html page and that is it.
But, hey - this is too simple to be geeky. Let's spice it with some Bash magic.

ADVANCED STUFF

Since our local network is on 192.168.0.0/24 subnet, we have 253 available IPs and around 20 users only. So, basically you will have to repeat 253-20 times:
iptables -I FORWARD -s 192.168.0.XX -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 192.168.0.XX -p udp --sport 53 -j ACCEPT
iptables -t nat -I PREROUTING -s 192.168.0.XX -p tcp --dport 80 -j REDIRECT --to-ports 3001
and 20 times part:
iptables -I FORWARD -p ALL -s 192.168.0.XX -j ACCEPT
iptables -I FORWARD -p ALL -d 192.168.0.XX -j ACCEPT
Huh. Either to have a slave to do work for you, or to learn bash.
So, here's how I did it. This is no extravagant solution, but will give you idea. Create file /etc/allowed_ips and in it, you put last IP octet of IP's that will have internet - one octet per line. So, if 192.168.0.12 and 192.168.0.34 have internet, this file will look like:
1
12
34

Our subnet is static, and for the sake of simplicity, I ommited whole IP addresses. Also, notice that we need to enable server itself (which is 192.168.0.1). Now, create script ip_allowing (put it wherever you want) with content like this:
#!/bin/bash

FILE=/etc/allowed_ips
ip_listing=`cat $FILE`

function check_exist {
for i in $ip_listing; do
if [ ${i:0:1} != "#" ]; then
if [ "$i" = "$1" ]; then
return 1
fi
fi
done
return 0
}

for ip in `seq 1 254`; do
check_exist $ip
if [ $? -eq 1 ]; then
#ip exist
iptables -I FORWARD -p ALL -s 192.168.0.$ip -j ACCEPT
iptables -I FORWARD -p ALL -d 192.168.0.$ip -j ACCEPT
echo allowing 192.168.0.$ip
else
#ip doesn't exist
iptables -I FORWARD -s 192.168.0.$ip -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 192.168.0.$ip -p udp --sport 53 -j ACCEPT iptables -t nat -I PREROUTING -s 192.168.0.$ip -p tcp --dport 80 -j REDIRECT --to-ports 3001
fi
done
No voodoo magic here. Function check_exist takes number (last octet) as argument, and checks whatever that IP is allowed and returns 1 if it is, 0 if it isn't. Main part just goes in loop from 1 to 254, and either allow DNS and redirect or allows all packets. You might have noticed line:
if [ ${i:0:1} != "#" ]; then

This line allows us to add comments to /etc/allowed_ips file, and ignore them, so our file could be like this now:
#server
1
#neighbour 1
12
#neighbour 2
34
Pretty handy, isn't it. All what is left is to call our new script (and give it exec permission, but you all know that - otherwise you wouldn't go this far in reading) from wherever script you setup iptables. Example would be:
iptables -I FORWARD -i ext0 -o ext1 -j DROP
/etc/rc.d/ip_allowing

Where now?

Well, this is simple solution. There are a lot of things that can be changed. For example, you might want to allow and deny internet access by MAC, not by IP addresses. Or, if you have larger subnet, this could be slower, so you would want your iptables commands to work with IP ranges. Or, you could pull your allowed IP addresses not from file, but from LDAP or MySQL with a bit more of parsing. You could also redirect only certain sites by using both source and destination in iptables REDIRECT command. On the other hand, looking at apache part, you see that our virtual host is hungry - it eats all URLs, so you couldn't have two pages in it. If you want that (for example to have index.html and contact.html), you would have to play with regular expressions to replace everything except "/contact.html" to /index.html.

Possibilities are endless, as with everything with Linux, you just have to know what you want and how to do it - simple as that.

Tuesday, July 04, 2006

KDE and Cyrillic filenames


I just found out what I have been looking for a long time now - how to setup KDE to show Cyrillic filenames on ext2/ext3 partitions. As I later found out (in hard way) it has nothing to do with filesystem itself, e.g. ext2/ext3 partitions support UTF-8 - problem was in KDE (e.g. Linux) setup. One has to set locale, e.g. just put these few lines in your profile.d (at my slack it is in /etc/profile.d/), make new script in it and type this:

#!/bin/sh

LANG=en_US.UTF-8
LANGUAGE=$LANG
LC_ALL=$LANG

export LC_ALL LANGUAGE LANG

Although my KDE is in Cyrillic and my locale should be Serbian (sr_CS.UTF-8), I still used en_US (it doesn't matter for KDE, it uses its own locale setup, this is only for terminal locale), the thing that matter in this script is that you should tell every program that you use UTF-8. Just login again and try to rename any file - it should be working now.