The most active posts on spiration http://www.spiration.co.uk/rss/active The most active posts on spiration en-us Torkalot christo@uk.com christo@uk.com ubuntu: error: stdio.h: No such file or directory http://www.spiration.co.uk/post/1291/ubuntu: error: stdio.h: No such file or directory Somehow I assumed that I would be able to compile a basic C program on any linux box - I mean unices are useful like that, right? So I was a bit surprised when I decided to compile a bit of C just now (in fact Christian Wolff's neat little mp3cut tool) and was faced with the following errors: [code] chris@snackerjack-lx:/usr/src/mp3cut-0.8$ make gcc -o mp3cut mp3cut.c mp3cut.c:25:19: error: stdio.h: No such file or directory mp3cut.c:26:20: error: stdlib.h: No such file or directory mp3cut.c:27:20: error: string.h: No such file or directory mp3cut.c:28:20: error: unistd.h: No such file or directory ..etc .. etc [/code] So what kind of unix comes with make and a compiler, but none of the required dev libraries and headers required to make any normal C program work? Well a brief google yielded the following solution.. Yup, you guessed it.. you need to install a dev package: [code] sudo apt-get install build-essential [/code] Excuse my rant, but if it's so 'essential', then why isn't it installed as part of the core system? I find that kinda weird. Anyway, problem fixed and C-sources are now compiling. christo follow me on twitter: [url]http://twitter.com/planet_guru[/url] Submit is not a function http://www.spiration.co.uk/post/1232/Submit is not a function This means you have a function trying to call the form's submit() method, but you also have a button which is called submit(). This causes a conflict in javascript, because the submit method is already bound to that button. To solve the problem, simply change the name of the button so that name="moo" (or something). Your submit() call in your javascript function/method will now work. It took me a while of hacking javascript and html to work that one out - hopefully this post will mean it only takes you a minute.. christo follow me on twitter: [url]http://twitter.com/planet_guru[/url] Ubuntu Linux - Bluetooth and GPRS dialup connection http://www.spiration.co.uk/post/1307/Ubuntu Linux - Bluetooth and GPRS dialup connection This article explains how to set up a bluetooth connection between your ubuntu laptop and phone and get PPP working with BT's mobile service in the UK. It probably isn't so hard to repeat this for other network providers. I'm sure that if you do a Yahoo search for the GPRS settings of your mobile telco, you'll be up and runnin with little more than a few mintues of poking around. First you need to install the bluetooth packages on your linux machine: [code] $sudo apt-get install bluez-utils $sudo apt-get install blues-pin [/code] Now you need to make sure you have the ppp package installed $sudo apt-get install ppp At this point you already have enough software on your machine to do a scan of the local area and see what devices are available. this is done using hcitool. When I run this command, the output looks like this: [code] $chris@snackerjack-lx:~$ hcitool scan Scanning ... 00:07:3A:08:EE:74 n/a 00:18:13:50:0C:EB Christo Yahoo! chris@snackerjack-lx:~$ [/code] That means that my laptop can see my phone - it's reporting the MAC address and the device name. For more information on hcitool, you can run 'man hcitool'. Basically hcitool is a handy bluetooth utility which allows you to scan for and query local bluetooth devices. At this stage you can use hcitool to pair your bluetooth-enabled laptop with your phone. Use the following commands to achieve this: [code] $sudo hcitool cc 00:18:13:50:0C:EB [/code] Note, you should use the MAC address of your own phone in this command - as reported by the hcitool scan command earlier. This creates a baseband connection to your phone. The next step is: [code] $sudo hcitool auth 00:18:13:50:0C:EB [/code] This will request authentication with your phone - this is known as 'pairing' and will allow your computer to communicate with your bluetooth phone. Note again, you should replace the mac address with that of your phone. Don't use mine! The next stage is to use the Service Discovery Protocol to ask your device what bluetooth services it is offering. At this point, if you're feeling really curious, you could re-run your hcitool scan and then run an SDP discovery search on all the listed devices. You never know - it might be interesting. However, this article is about setting up a Dial-up connection through your phone, so let's keep focussed.. The command you need to issue looks like this: [code] $sdptool browse 00:18:13:50:0C:EB [/code] Again, use your own phone's MAC address - This will list all sorts of bluetooth services that your phone offers. This is what the output looks like when I run this command against my own phone.. I know it's a lot to paste, but it's worth seeing the kind of services which might be on offer: [code] chris@snackerjack-lx:~$ sdptool browse 00:18:13:50:0C:EB Browsing 00:18:13:50:0C:EB ... Service Description: Sony Ericsson K750 Service RecHandle: 0x10000 Service Class ID List: "PnP Information" (0x1200) Service Name: Dial-up Networking Service RecHandle: 0x10001 Service Class ID List: "Dialup Networking" (0x1103) "Generic Networking" (0x1201) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 1 Profile Descriptor List: "Dialup Networking" (0x1103) Version: 0x0100 Service Name: Serial Port Service RecHandle: 0x10002 Service Class ID List: "Serial Port" (0x1101) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 2 Service Name: HF Voice Gateway Service RecHandle: 0x10003 Service Class ID List: "Handfree Audio Gateway" (0x111f) "Generic Audio" (0x1203) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 3 Profile Descriptor List: "Handsfree" (0x111e) Version: 0x0101 Service Name: HS Voice Gateway Service RecHandle: 0x10004 Service Class ID List: "Headset Audio Gateway" (0x1112) "Generic Audio" (0x1203) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 4 Profile Descriptor List: "Headset" (0x1108) Version: 0x0100 Service Name: OBEX Object Push Service RecHandle: 0x10005 Service Class ID List: "OBEX Object Push" (0x1105) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 5 "OBEX" (0x0008) Profile Descriptor List: "OBEX Object Push" (0x1105) Version: 0x0100 Service Name: OBEX File Transfer Service RecHandle: 0x10006 Service Class ID List: "OBEX File Transfer" (0x1106) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 "OBEX" (0x0008) Profile Descriptor List: "OBEX File Transfer" (0x1106) Version: 0x0100 Service Name: OBEX SyncML Client Service RecHandle: 0x10007 Service Class ID List: "Error: This is UUID-128" (0x00000002-0000-1000-8000-0002ee000002) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 7 "OBEX" (0x0008) Service Name: OBEX IrMC Sync Server Service RecHandle: 0x10008 Service Class ID List: "IrMC Sync" (0x1104) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 8 "OBEX" (0x0008) Profile Descriptor List: "IrMC Sync" (0x1104) Version: 0x0100 Service Name: Mouse & Keyboard Service Description: Remote Control Service Provider: Sony Ericsson Service RecHandle: 0x10009 Service Class ID List: "Human Interface Device" (0x1124) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 17 "HIDP" (0x0011) Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Human Interface Device" (0x1124) Version: 0x0100 chris@snackerjack-lx:~$ [/code] That's pretty cool - First you can see that I'm using a Sony Ericsson K750 phone and then on every bluetooth 'Service Name:' line, you can see the name of a service on offer. The one we are most interested in is the 'Dial-up Networking' service, however, we can also use this device as a voice gateway, and it will support OBEX transfer requests (ie the exchange of binary objects from other bluetooth devices). I can also use this phone as an input device (service 'Mouse & Keyboard') - note that this last service describes itself as 'Remote Control' and yes, it can be used in precisely that way - so the phone will suddenly become a pointer/mouse within the PAN. I will explain this in another article. Okay, so where are we now? Well the next step is simply to tell your system which channel you want to talk RFCOMM. RFCOMM is a special bluetooth serial port emulation over radio frequency (hence the name rf communication). It is quite literally an implementation of the RS232 serial protocol over radio. Bluetooth can handle several rfcomm channels consecutively. We just have to decide which one we're going to use for this exercise.. This is dead easy. Just look at the output of the sdp search which you ran just now and look at the RFCOMM channel number in the 'Dial up Networking' service section. In the case above, it's channel 1. All you do now is specify that channel in your rfcomm.conf - so on my system that looks like this: [code] rfcomm0 { bind yes; device 00:18:13:50:0C:EB; channel 1; comment "PPP connect"; } [/code] At this point, you can set up /dev/rfcomm0 by running the following command: [code] $sudo /etc/init.d/bluez-utils restart [/code] We're nearly there. Now that you have your rfcomm node fully configured and your phone and computer are paired, all you need to do is set up the PPP and chat settings on your computer. Chat sets up a ppp connection between your modem and a remote ppp service based on rules which you define in a chatscript. First create the file /etc/ppp/peers/bluetoothconn and put the following into it: [code] debug noauth connect "/usr/sbin/chat -v -f /etc/chatscripts/bluetoothconn" usepeerdns /dev/rfcomm0 115200 defaultroute crtscts lcp-echo-failure 0 [/code] Now edit the file /etc/chatscripts/bluetoothconn and make sure it contains the following: [code] TIMEOUT 35 ECHO ON ABORT 'nBUSYr' ABORT 'nERRORr' ABORT 'nNO ANSWERr' ABORT 'nNO CARRIERr' ABORT 'nNO DIALTONEr' ABORT 'nRINGINGrnrnRINGINGr' '' rAT OK 'AT+CGDCONT=2,"IP","btmobile.bt.com"' OK ATD*99***2# CONNECT "" [/code] It took me a while to get this configuration to work. I tried several settings for the data profile number, without any real idea of what it should be - and found that ***2 worked. You might have to play around with this for your own telco - try swapping the '2' for any integer between '1' and '4', or even remove the whole lot and just terminate with a '#'. To bring the connection up, just run the command: [code] $pon bluetoothconn [/code] and to turn it off again: [code] $poff Bluetoothconn [/code] It's as simple as that. If you still have questions about your bluetooth and GPRS setup with linux on your laptop and trying to talk to BT, please reply to this and let me know. Hope that helps. christo [url]http://www.twitter.com/planet_guru[/url] Java md5 example with MessageDigest http://www.spiration.co.uk/post/1199/Java md5 example with MessageDigest This is a quick tip for implementing md5 encryption in java. We use the MessageDigest class in the java.security package and some string manipulation to turn the plain text into a byte array. The digest is then updated from the bytes from the byte array and a hash computation is conducted upon them. To quote from the Sun java api docs, The MessageDigest class provides applications the functionality of a message digest algorithm, such as MD5 or SHA. Message digests are secure one-way hash functions that take arbitrary-sized data and output a fixed-length hash value. Anyway the md5 example code below takes a session id (this is just a string which I wanted to encrypt - It could just as easily be a document, say a lump of xml or any old bit of text). This session id is pulled into the bytes array, defaultBytes and then the MessageDigest is instantiated as an instance of an md5 encryption. Java developers who have come over from PERL or PHP often get frustrated with such a longwinded means of running what could simply be a single line of code, however the snippet below could be wrapped into an md5sum class which conducts the encryption and simply returns a string of cipher text. [code] include java.security.*; ... etc sessionid="12345"; byte[] defaultBytes = sessionid.getBytes(); try{ MessageDigest algorithm = MessageDigest.getInstance("MD5"); algorithm.reset(); algorithm.update(defaultBytes); byte messageDigest[] = algorithm.digest(); StringBuffer hexString = new StringBuffer(); for (int i=0;i<messageDigest.length;i++) { hexString.append(Integer.toHexString(0xFF & messageDigest[i])); } String foo = messageDigest.toString(); System.out.println("sessionid "+sessionid+" md5 version is "+hexString.toString()); sessionid=hexString+""; }catch(NoSuchAlgorithmException nsae){ } [/code] Remember to import the java.security package. The original plain text and cipher text strings are echod to the java console just to demonstrate what has happened. Hope that's useful, christo follow me on twitter: [url]http://www.twitter.com/planet_guru[/url] ubuntu linux VPN connection without cisco vpn client http://www.spiration.co.uk/post/1293/ubuntu linux VPN connection without cisco vpn client Getting a reliably working VPN connection on your linux box isn't as easy as one might think. The Cisco VPN client for linux comes with a few major flaws - firstly it's a complete arse to install - particulary on heavily package-based distros such as Ubuntu - the program requires all the kernel headers to be present and it also insists that they exactly match the running kernel version. This may or may not be a total ballache to manage. In addition to that, I have run the Cisco VPN client for linux on at least two distros (including Slackware and Redhat) and it has been bad to say the least. Connections just die over SSH when any more than a few packets are sent and nothing less than a restart of the client will allow the system to reconnect - Such a program falls well beyond my 'suitable-for-use' radar. It was these issues which pushed me to find an alternative solution. The solution came in the form of Maurice Massar's vpnc - a relatively little-known and fairly unassuming application which does exactly as it says on the tin. Ubuntu users are one step ahead of the source-based distros just because a vpnc package does exist for dapper. First let's install that on the client system. Do this with the following command: [code] sudo apt-get install vpnc [/code] If you are not running ubuntu, you will probably have to compile the program yourself. I would image this to be quite simple. The sources are downloadable from this page: http://www.unix-ag.uni-kl.de/~massar/vpnc/ Now this is where things get a bit tricky - you have the application installed, but it won't work until you have a working config. This contains a bunch of IPSec settings required to talk to your VPN endpoint. When I first looked at these, I really didn't know where to start, but I pretty soon determined that the most important values would be these: [code] IPSec gateway IPSec ID IPSec secret Xauth username Xauth password [/code] So from whence should we collect this data? I knew that if I was to ask the IT department at work, they would probably tell me that the software isn't supported and to use the cisco client under windows. That doesn't suit my needs, but it does offer a clue. You see, for every connection profile, the Cisco VPN client keeps a profile description file called a .pcf. All I need to do is locate the .pcf file on my windows partition and copy it over. [code] mount /dev/hda1 /windows cp /windows/Program Files/Yahoo! Inc/VPN Client/profiles/London.pcf /home/chris/Desktop/. [/code] Now we can extract the vpn gateway hostname, the Group ID and the group 'secret' from the locally copied .pcf. The group secret is a very long string of characters - it's actually a hexadecimal representation of the key, (which itself is formed from a mixture of SHA-1 hashing and triple-DES in CBC mode - a web search will yield all the gory details if that interests you). This throws a slight hurdle in our path, because it is the original plain text version which we need to offer our vpnc config. Thankfully there are tools around to help us with this. First you will need to install the libgcrypt-dev package: [code] sudo apt-get install libgcrypt-dev [/code] You will then need to compile the cisco-decrypt.c utility which is downloadable from here: http://www.unix-ag.uni-kl.de/~massar/soft/cisco-decrypt.c . Note that when you come to compile the program you will need to use the following compile options: [code] gcc -Wall -o cisco-decrypt cisco-decrypt.c $(libgcrypt-config --libs --cflags) [/code] This will result in a working binary in ./cisco-decrypt. Okay, we're nearly there.. all we need to do now is decrypt that cipher string from the .pcf file and then we can paste that into our vpnc.conf. The first thing cisco-decrypt does is convert the string from hexadecimal to binary. Here's how I did that: [code] root@snackerjack-lx:~/Desktop# grep enc_GroupPwd London.pcf | awk -F= '{print $2 }' | xargs ./cisco-decrypt atat@atet8s8cu*7777uv8paiaiecrac$ root@snackerjack-lx:~/Desktop# [/code] Of course I have modified it for obvious reasons, but you get the idea. And now to the final stage - creating the config file: [code] vim /etc/vpnc/vpnc.conf [/code] Just enter the follwing lines (of course using your own settings), write out the file and exit: [code] IPSec gateway <your gateway address from the pcf> IPSec ID General IPSec secret atat@atet8s8cu*7777uv8paiaiecrac$ Xauth username clacy Xauth password nottellingyou [/code] It's worth mentioning here that if you omit the username and/or password, the vpnc program will prompt you for them at run time. I highly recommend you do this. It will save you from having to enter them in plain text into a config file. Additionally, if you use RSA-SecureID fobs for your passwords it will make using the application far easier. Nobody wants to hack a config every time they run a program! Now all you need to do is fire up the connection like this: [code] sudo vpnc /etc/vpnc/vpnc.conf [/code] If this is useful to you and you would like some of this packaged up in some way, please let me know. I think it's pretty simple as it is, but if there is any interest out there and I can make this simpler for the next person, then I will :) christo Using PHP to generate an Excel Spreadsheet http://www.spiration.co.uk/post/1198/Using PHP to generate an Excel Spreadsheet Use PHP to retrieve data from a database and present it instantly in an Excel Spreadsheet to your user. This tutorial shows how simple it is to provide information in a way which is useful to your customer - whether it's your boss, a colleague, or an end user of one of your web applications. One requirement of this method is that you install the PEAR::Spreadsheet_Excel_Writer module on your webserver. If you don't have permission to do that, contact your systems administrator and ask him to to it. It's a two-second job. All you need to do is connect as root and issue the following command: root@server: pear install Spreadsheet_Excel_Writer This module was intended as a clone of the Spreadsheet::WriteExcel Perl module (on CPAN). It allows you to create an Excel spreadsheet without the use of COM object. However, because the module uses the BIFF5 format, it currently only supports Excel version 5, so features in newer version of excel aren't available at this stage. Now you are ready to start coding. In this example I start off by pulling in some libraries which manage my database connection.. they just define the $db_name, $db_user, $db_password, $db_hostname and all that stuff, and then provide a call to mysql_select_db() ready for my connection. If you don't know how to do this stuff, then read up on that first - or if you don't want to that's fine. Afterall, this article is about generating spreadsheets, So the first and foremost thing that has to happen in your php is a call to require_once. This enables us to pull in the Writer.php class definition, which now resides somewhere in your php path. (probably under /usr/local/lib/php/Spreadsheet/Excel/). require_once 'Spreadsheet/Excel/Writer.php'; This makes all the classes and methods available to the rest of our script, so the next job is to call the constructor on this writer class and assign the newly created workbook object to a variable which we will call $workbook: $workbook = new Spreadsheet_Excel_Writer(); From here we can really do whatever we like with the workbook. We can add worksheets, define formatting directives, insert data and formulae.. really all of the things that you would want to do with a basic spreadsheet. In this example I'm going to use an addressbook table in my database, load all the information out of it and present it in a spreadsheet. First I want to define the column headers and I want these to be in bold. For this we use the addFormat() method to say that we want to create a new set of formatting rules. This (in true OOP style) creates a format object, w:-o hich we assign to $format_bold (that's what I'm going to call it), and then we call methods belonging to the format class to specify exactly what we want, for example setBold(), which says that the format being called will have bold text. $workbook = new Spreadsheet_Excel_Writer(); $format_bold =& $workbook->addFormat(); $format_bold->setBold(); You might also notice something else in here - and that's the use of the '&' character when creating the workbook. I have done this because an Excel Spreadsheet can be quite an unwieldly thing - I mean there's a lot of metadata in there even before you start inserting cell data. Using the '&' character tells the programme to pass me a reference to the object which has been created not the object itself. This is really just a pointer - it tells me the precise location in memory where the object is stored. The result of this is that I don't have duplicates of the spreadhseet object flying around the place and taking up valuable resources. Instead I'm just using a reference. So lets get on with creating a worksheet and actually writing the column title data into the top row: $worksheet =& $workbook->addWorksheet(); $worksheet->write(0, 0, "name", $format_bold); $worksheet->write(0, 1, "address", $format_bold); $worksheet->write(0, 2, "phone", $format_bold); $worksheet->write(0, 3, "email", $format_bold); $worksheet->write(0, 4, "comments", $format_bold); So once again I call a constructor method and pass back a reference to the newly created object. I can then manipulate the worksheed object with the methods on offer - well in this case I just use write(), specifying each time a row number, column number, some text and finally I pass in a format object (the one created earlier - this will make the top row bold). Well that was simple enough. All that's required now is some code to put the data in under the column headings and we're just about there: $query="select * from addresses"; $result=mysql_db_query($db_name,$query); First I run a query and grab the returned result object back into $result. Now I just iterate through the result, grabbing row contents one at a time and incrementing my way down through the spreadsheet rows with the captured data. $i=1; while($row=mysql_fetch_assoc($result)){ $worksheet->write($i, 0, "$row[name]"); $worksheet->write($i, 1, "$row[address]"); $worksheet->write($i, 2, "$row[phone]"); $worksheet->write($i, 3, "$row[email]"); $worksheet->write($i, 4, "$row[comments]"); $i++; } So this time I don't specify a format and the text just goes in as regular weighted text. The only thing that's left for me to do now is to send the freshly generated spreadsheet up to the user. The Workbook class does come with a send() method which send the object up to the client's browser, bundling in all the correct MIME headers and wot not. The result is that the user (who has presumably just clicked on a link to call this php page) will almost instantly get an Excel screen loading before their eyes with all the address book data contained within. You can then clean up with close() and end the script $workbook->close(); ?> Please reply if you have any further comments, or click on the 'subscribe' icon at the botton of the PHP/MySQL channel to receive an email notification next time an article is posted. All that's left for me to do now is to provide all the sources for this example and to wish you a good day. [code] <?php /* $Id: report_all.php,v 1.1 2004/08/30 16:03:40 chris Exp $ generate a spreadsheed from and addressbook in mysql database. */ include "dblib.php"; DBConnect(); require_once 'Spreadsheet/Excel/Writer.php'; $workbook = new Spreadsheet_Excel_Writer(); $format_bold =& $workbook->addFormat(); $format_bold->setBold(); $worksheet =& $workbook->addWorksheet(); $worksheet->write(0, 0, "name", $format_bold); $worksheet->write(0, 1, "address", $format_bold); $worksheet->write(0, 2, "phone", $format_bold); $worksheet->write(0, 3, "email", $format_bold); $worksheet->write(0, 4, "comments", $format_bold); # start by opening a query string $fullquery="select * from smslog"; $result=mysql_db_query($db_name,$fullquery); $i=1; while($row=mysql_fetch_assoc($result)){ $worksheet->write($i, 0, "$row[name]"); $worksheet->write($i, 1, "$row[address]"); $worksheet->write($i, 2, "$row[phone]"); $worksheet->write($i, 3, "$row[email]"); $worksheet->write($i, 4, "$row[comments]"); $i++; } $workbook->send('test.xls'); $workbook->close(); ?> [/code] follow me on twitter: [url]http://twitter.com/planet_guru[/url] vpnc: no response from target - ubuntu linux VPN http://www.spiration.co.uk/post/1335/vpnc: no response from target - ubuntu linux VPN As a follow up on the [URL=http://www.spiration.co.uk/post/1293]Ubuntu linux VPN tutorial[/URL] it is worth pointing out one more tip on getting this to work. With newer versions of vpnc, you might get this message when trying to initiate a vpn connection: vpnc: no response from target This is simple to fix simply by adding the following line to your vpnc.conf: NAT Traversal Mode cisco-udp So your /etc/vpnc/vpnc.conf file should look something like this: [code] IPSec gateway 217.32.131.20 IPSec ID General IPSec secret aa@thattosuri22pr*7uv8pespfosic$ Xauth username clacy NAT Traversal Mode cisco-udp [/code] christo follow me on twitter: [url]http://twitter.com/planet_guru[/url]