Thursday, 22 November 2012

Facebook Developer: Debugger


Not sure how many of you know about this, but check out the Facebook Debugger!

You can enter an Input URL, Access Token, or Open Graph Action ID!

View Here: http://developers.facebook.com/tools/debug

Error when saving a table in SQL Server: "Saving changes is not permitted"


Error Message
Saving changes is not permitted. The changes that you have made require the following tables to be dropped and re-created. You have either made changes to a table that can't be re-created or enabled the option Prevent saving changes that require the table to be re-created.

Why?
This problem occurs when the Prevent saving changes that require the table re-creation option is enabled, and you make one or more of the following changes to the table:
  • You change the Allow Nulls setting for a column.
  • You reorder columns in the table.
  • You change the column data type.
  • You add a new column.
When you change a table so that you alter the metadata structure of the table, and then you save the table, the table must be re-created based on these changes. This may result in the loss of metadata and in a direct loss of data during the re-creation of the table.

Fixing the Problem

OPTION 1 - Using the ALTER SQL keyword to change the table definition.

Code Snippet
  1. ALTER TABLE NameOfTable ALTER COLUMN ColumnToAlter INT NOT NULL
End of Code Snippet

Option 2 - Turning off the "Prevent saving changes that require table re-creation" option. NOT RECOMMENDED!. This may cause data loss due to changes with the meta structure of the table. A good example of potential data loss is if you enable Change Tracking.

If you only have the table structure set up and/or data loss isn't an issue (Test Data for example), then here are the following steps to turn off this data protection feature.

1. Open SQL Server Management Studio (SSMS).
2. On the Tools menu, click Options.
3. In the navigation pane of the Options window, click Designers.
4. Select or clear the Prevent saving changes that require the table re-creation check box, and then click OK.




Joining MP4 Files together without Re-Encoding (Windows and MAC)


OPTION 1 - MP4Join (Cross Platform) [RECOMMENDED!]

VERY simple cross platform solution to join MP4 files. Just add them to the lit, re-order them, and it will simply copy the next video on to the previous at the end of the last frame. It will output the final MP4 without loss of quality or re-encoding.

Download Here: http://www.mp4joiner.org/en


OPTION 2 - Quicktime (7 or X at time of writing). Windows users must use Quicktime PRO ONLY.

1. Open the two H264 videos in Quicktime 7. Let's suppose they are named video1.mp4 and video2.mp4.

2. Working on video1.mp4, Select All, then Copy.

3. Switch to video2.mp4, make sure the "cursor" is at the beginning of the video, then Paste. This inserts the content of video1.mp4 at the front of video2.mp4.

4. This step is probably optional. "Save As" the modified video2.mp4. You will be able to save in .mov format only. I saved as a self-contained movie, but I suppose a reference movie would work too. I used the filename "video.mov".

5. Select "Export" in the file menu to export video.mov to the joined H264 file. The "Export" to select is "Movie to MPEG-4". The preset is not important, I chose "LAN/Intranet". The preset is not important because we override it in the next step.

6. Click on "Options" to reach the settings dialog. In the Video pane, "Video Format" is selected to be "H.264". Click on the menu, select "Pass Through". As expected, all the other options will get disabled.

7. Click OK, then Save, and watch your joined file be saved at the speed of your hard disk.


OPTION 3 - MAC Users Only!

SimpleMovieX, a shareware video editor which exactly advertises this as a feature. Requires OS X 10.6 or later.

Download Here: http://simplemoviex.com/SimpleMovieX/download.html

Thursday, 26 July 2012

iPhone - Free 3G tethering


Applications like MyWi and PDANet are not allowed on the Apple App Store due to getting around user's data network data usage plans (Which networks charge a lot for!)

Check out this app, very simple, lightweight and free!

http://www.junefabrics.com/desktop/

Tuesday, 17 July 2012

JDBC - Calling an Oracle Stored Procedure with CURSOR output


This article explains how to call an Oracle Stored Procedure that returns a Cursor as an output parameter with Java using JDBC.


Things to note:
- JDBC begins it's index's at 1, not 0. I.e. The CallableStatement object's methods such as: getObject must have a parameter with a value of at least 1.
- Once the Connection or CallableStatement objects are closed, the ResultSet will be empty. This is because it only exists as long as the database connection is open. Ensure you take your results before these objects are destroyed.
- oracle.jdbc.OracleCallableStatement and java.sql.CallableStatement offer the same outcome in this example. Therefore, I have opted to use the java.sql library.
- The '?' within the prepareCall parameter is a place holder for a parameter. This is populated (in this example) using the registerOutParameter method, declaring it's expected type.


Oracle Stored Procedure
Code Snippet
  1. CREATE OR REPLACE PROCEDURE PACKAGENAME.GET_ACCOUNTS
  2. (
  3.     l_cursor OUT sys_refcursor
  4. )
  5.     OPEN l_cursor FOR SELECT ACCOUNT_NAME FROM Accounts ORDER BY ACCOUNT_NAME;
  6. END GET_ACCOUNTS;
End of Code Snippet


Java Code
Code Snippet
  1. // Establishes and returns a new connection to the database
  2. private Connection GetConnection() throws SQLException
  3. {
  4.     // Load and register Oracle driver
  5.     DriverManager.registerDriver(new OracleDriver());
  6.    
  7.     // Establish a connection
  8.     return DriverManager.getConnection("jdbc:oracle:thin:@SERVER:PORT:SID", "USERNAME", "PASSWORD");
  9. }
  10.  
  11.  
  12. // Gets a collection of all accounts within the database
  13. public Collection<Account> GetAccounts() throws SQLException
  14. {  
  15.     Connection conn = null;
  16.     CallableStatement cstmt   = null;
  17.     Collection<Account> accounts = new ArrayList<Account>();
  18.  
  19.     try
  20.     {
  21.         // Connect
  22.         conn = this.GetConnection();
  23.  
  24.         // Get ResultSet
  25.         cstmt = conn.prepareCall("{call PACKAGENAME.GET_ACCOUNTS(?)}");   // '?' is a template for our Cursor OUT parameter
  26.         cstmt.registerOutParameter(1, OracleTypes.CURSOR);
  27.         cstmt.execute();
  28.  
  29.         // Index starts at 1, so we want our first result, which is the Cursor
  30.         ResultSet rs = (ResultSet) cstmt.getObject(1);
  31.  
  32.         // process results one row at a time
  33.         while(rs.next())
  34.         {
  35.             Account acc = new Account(rs.getString(1)); // Account name is the first (and only) result in our Cursor.
  36.             accounts.add(acc); // Add account to our collection of accounts to return
  37.         }
  38.     }
  39.     catch (SQLException e)
  40.     {
  41.         System.err.println(e.getErrorCode() + e.getMessage());
  42.     }
  43.         catch(Exception e)
  44.         {
  45.             e.printStackTrace();
  46.         }
  47.     finally
  48.     {
  49.         conn.close();
  50.         cstmt.close();
  51.     }
  52.    
  53.     return accounts; // Return collection of accounts to caller
  54. }
  55.  
  56.  
  57.  
  58. // Account POJO
  59. public class Account
  60. {
  61.     private String accountName;
  62.  
  63.     public Account(String accName)
  64.     {
  65.         this.accountName = accName;
  66.     }
  67.    
  68.     public String getAccountName() {
  69.         return this.accountName;
  70.     }
  71.  
  72.     public void setAccountName(String accountName) {
  73.         this.accountName = accountName;
  74.     }
  75. }
End of Code Snippet

java.lang.IllegalAccessError: oracle/jdbc/driver/OracleCallableStatement


I received this error when attempting to cast the result of a Connection object's prepareCall method.

Solution
Try altering the application to not refer to oracle.jdbc.driver.OracleCallableStatement. It should be oracle.jdbc.OracleCallableStatement.

Reason
For Oracle 9i onwards you should use oracle.jdbc.OracleDriver rather than oracle.jdbc.driver.OracleDriver as Oracle have stated that oracle.jdbc.driver.OracleDriver is deprecated and support for this driver class will be discontinued in the next major release.

Tuesday, 29 May 2012

iPhone - iOS 5.1.1 untethered jailbreak with Absinthe 2.0.2



Summary
After copious amounts of work and many sleepless nights Absinthe 2.0 is finally here to jailbreak your device. This release has been a large collaborative effort between Chronic-Dev Team and iPhone Dev Teams (Jailbreak Dream Team)

This jailbreak supports firmware 5.1.1 ONLY and is again one of the most easiest jailbreaks to use (so easy your grandma could do it ;D)


Press Release
http://conference.hitb.org/hitbsecconf2012ams/ios-jailbreak-dream-team-releases-absinthe-2-0-ios-5-1-1-jailbreak/


Absinthe 2.0 supports the following devices
iPad1,1 – 2,1 – 2,2 – 2,3 – 3,1 – 3,2 – 3,3

iPhone2,1 – 3,1 – 3,3 – 4,1

iPod3,1 – 4,1

(Support for iPad2,4 will be added at a later date)



How To Use Absinthe 2.0 (if you're unjailbroken)
1. Make a backup of your device in iTunes by right clicking on your device name under the ‘Devices’ menu and click ‘Back Up’.

2. Once your backup is complete return to your device and go to Settings – General – Reset – Erase all Content and Settings. This will make the jailbreak process much faster.

3. Open Absinthe and be sure you are still connected via USB cable to your computer.

4. Click ‘Jailbreak’ and wait…. just be patient and do not disconnect your device.

5. Once jailbroken return to iTunes and restore your backup from earlier. Right click on your device name under the ‘Devices’ menu in the left panel of iTunes and click ‘Restore from Back Up…’ then select the latest backup you created before. (restoring this backup will return all the content previously on your device ie, apps, photos, etc.)

6. Thanks for using Absinthe, enjoy your jailbroken iDevice!


How To Untether 5.1.1 (if you're already jailbroken)
Just search for and install "Rocky Racoon 5.1.1 Untether" from Cydia.


Download Links
Absinthe v2.0.2 MacOSX (10.5, 10.6, 10.7)
Absinthe v2.0.2 Windows (XP/Vista/Win7)
Absinthe v2.0.2 Linux (x86/x86_64)


Source: http://greenpois0n.com

iPhone - What are SHSH Blobs and how to downgrade your iOS firmware



Summary
An SHSH Blob is a signature file which is verified against Apple Server to verify the the iPhone is running the latest version of iOS. If for some reason, when you are try to restore to a previous version, Apple will not allow you to restore it becuase, you are trying load a older version of iOS. To make this possible, we need to send a request to a different server (Local or designated) which sends a SHSH blob (which was saved by you) back to iTunes faking that its the current version.


This applies to all apple based devices
iPhone, iPad, iPod Touch etc...


An SHSH Blob CANNOT be shared across multiple devices
I.e. you can't use a friends! This is because the ECID (Exclusive Chip ID - Unique ID for the device) is saved alongside it and must match.


Why and when to save these SHSH Blobs?
You should save these SHSH Blobs everytime your device is updated to a new firmware version. This will allow you to downgrade the firmware for the device regardless of Apple unsigning the firmware or not. So keep a collection, and you can downgrade to whichever you wish.


Why should I downgrade?
- Your generally unhappy with the new firmware
- The new jailbreak has problems, and you would like to revert to a previous firmware where your previous jailbreak was running smoothly.
- The new firmware only has a Tethered jailbreak available.

Teathered vs. Unteathered?
This simply means, weather you need a computer to start your phone. If a release of redsn0w offers a Teathered solution, then !everytime! your phone turns off (out of battery, new app install etc.) you will need to plug it into your computer and use redsn0w to boot the phone! The batteries are pretty decent, so you probably don't even care or it's no big deal.


I don't have my SHSH Blobs for a previous firmware version, but I still want to downgrade...
A utility called "An SHSH Blobs Extractor" is being worked on by iH8sn0w... This allows you to extract blobs for a previous firmware version from the device. Stay tuned though, it's not out yet!


How do I save an SHSH Blob for my device
NOTE: Do you not need a jail broken device to save your SHSH Blob.

You have a number of options here, but the way that works for jailbroken and non-jailbroken devices is by using TinyUmbrella (For Windows and MAC).

TinyUmbrella Download
TinyUmbrella-5.11.01.pkg (MAC)
TinyUmbrella-5.11.01.exe (Win)
View the TinyUmbrella blog to get the latest version here

1. Open TinyUmbrella
2. Click "Start TSS Server"
3. Save SHSH
4. The SHSH files for your device will now be stored on your local system.

NOTE:
If your device is jailbroken, you can store these on the Cydia server. This will allow you to revert back to a previous firmware without worrying about keeping them safe. Also, if you buy an Apple device from ebay, the seller may have already done this, so its good to check Cydia if this is the case!


Downgrading your device with SHSH Blobs
Once you have the SHSH Blobs for the firmware you would like to downgrade to, then you can use iFaith to achieve this! More information here

Monday, 28 May 2012

Shell Script: NSLookup DNS entry to see which server is LIVE


Here is a simple script which allows you to perform an NSLookup on a DNS entry to find out if the current host is Live or not.

This is useful if you have a mirrored backup server that shouldnt process any data unless its currently live. If a failover occurs, the backup server will then realise it's live and process the information which the other server was currently processing.


Code Snippet
  1. #!/bin/sh
  2. ################################################################################
  3. # Does an NSLookup on a server DNS entry to determine which server is currently LIVE.
  4. ################################################################################
  5. #
  6. # Get LIVE server and query current server
  7. liveServer=`eval nslookup mgs | grep "Name:"`
  8. currentServer=`eval hostname`
  9.  
  10.  
  11. # Nslookup to see if this server is LIVE
  12. echo "$liveServer" | grep $currentServer >/dev/null 2>&1
  13.  
  14. if [ "$?" -eq "0" ]; then
  15.     echo "This IS the Live server"
  16. else
  17.     echo "This IS NOT the Live server"
  18. fi
  19.  
  20.  
  21.  
  22. exit 0
End of Code Snippet

Thursday, 3 May 2012

iTunes - Play .ogg vorbis files in iTunes



By default, you cannot play .ogg files in iTunes, as they currently are not supported. iTunes uses Quicktime libraries in the backend to handle playback of audio and video content. We can, however, use a utility to allow Quicktime to handle files of different types.

Xiph
Xiph QuickTime Components (XiphQT) is, in short, the solution for Mac and Windows users who want to use Xiph formats in any QuickTime-based application, e.g. playing Ogg Vorbis in iTunes or producing Ogg Theora with iMovie.

Download
http://www.xiph.org/quicktime/download.html

Bonus
Also: How to add FLAC files into iTunes

Wednesday, 2 May 2012

Linux/Mac - Find files by filetype and move them into a target directory


Find (find) all text files ('*.txt') in the current directory (.) by case-insensitive filename (-iname) and display the output in the console (-print).
Code Snippet
  1. find . -iname '*.txt' -print
End of Code Snippet


Find (find) all text files ('*.txt') in the current directory (.) by case-insensitive filename (-iname) and (-exec) move each one of them (mv {}) to the temp directory (/tmp).
Code Snippet
  1. find . -iname '*.txt' -exec mv {} /tmp \;
End of Code Snippet

daemonize - Running commands as a Unix daemon



Daemonize
daemonize runs a command as a Unix daemon. As defined in W. Richard Stevens’ 1990 book, UNIX Network Programming (Addison-Wesley, 1990), a daemon is “a process that executes ‘in the background’ (i.e., without an associated terminal or login shell) either waiting for some event to occur, or waiting to perform some specified task on a periodic basis.” Upon startup, a typical daemon program will:

  • Close all open file descriptors (especially standard input, standard output and standard error)
    Change its working directory to the root filesystem, to ensure that it doesn’t tie up another filesystem and prevent it from being unmounted
  • Reset its umask value
  • Run in the background (i.e., fork)
  • Disassociate from its process group (usually a shell), to insulate itself from signals (such as HUP) sent to the process group
  • Ignore all terminal I/O signals
  • Disassociate from the control terminal (and take steps not to reacquire one)
  • Handle any SIGCLD signals

Download: daemonize

Example Usage
Code Snippet
  1. daemonize ./samplescript.sh
End of Code Snippet

By checking running processes on our system, we can see our script running as a daemon...
Code Snippet
  1. ps -ef | grep samplescript
End of Code Snippet

root 898 1 0 10:51 ? 00:00:00 /bin/sh /usr/local/bin/samplescript.sh

Tuesday, 1 May 2012

Solaris/SunOS - xymond_client: fatal: libpcre.so.0: open failed: No such file or directory Killed


libpcre.so.0: open failed: No such file or directory Killed
This is an error which appeared in the logs during runtime of a client installation of some system monitoring software called Xymon.
The problem is that during runtime, the pcre shared object files cannot be located. This can be because we haven't installed the libraries, or we didn't link them properly when building from source.
The same solution may apply to any other software that relies on the pcre libraries.


Here are the steps to resolve the problem...

1. Ensure you have CSWpcre installed... You can do this using pkgutil
Code Snippet
  1. pkgutil -i pcre
End of Code Snippet

Check that the pcre shared objects and includes can be found in the csw directory..

/opt/csw/lib
/opt/csw/include


2. Navigate to the Xymon build directory and open the Solaris/SunOS Makefile...
Code Snippet
  1. vi Makefile.SunOS
End of Code Snippet


3. Add a reference to pcre to the linker..

REPLACE
NETLIBS = -lresolv -lsocket -lnsl
WITH
NETLIBS = -lresolv -lsocket -lnsl -lpcre


4. Use GNU make to make a new Xymon binary...

Code Snippet
  1. make -s
End of Code Snippet


Troubleshooting Xymon Client Connectivity
Logs are your friend! These are located in the Xymon log's directory.. (/xymon/client/logs)


Sending a test query to the Xymon server
Code Snippet
  1. /xymon/client/bin/xymon --debug XYMONSERVERIPADDRESS "query XYMONSERVERIPADDRESS conn"
End of Code Snippet

Troubleshooting client connection using the web server interface
You can view all client machine activity with Xymon server (even if the machine is not configured in hosts.cfg) by viewing Ghost Clients (http://XYMONSERVER/xymon-cgi/ghostlist.sh)... This may help you identify why some servers aren't showing up.

Monday, 30 April 2012

SunOS/Solaris - Xymon make error (locator symbol referencing errors in xymond_worker.o)


Xymon
Xymon is a piece of software for multiple platforms which allows system administrators to monitor resources and usage. Computer monitoring systems are used to repeatedly gather data from various monitored systems for the purpose of real-time incident notification, system health verification, performance analysis, and longitudinal capacity planning.


Problem
gcc -o ../client/xymond_client -Wl,-R/opt/csw/lib xymond_client.o xymond_worker.o xymond_buffer.o client_config.o ../lib/xymonclient.a -L/opt/csw/lib -lpcre -lresolv -lsocket -lnsl
Undefined first referenced
symbol in file
locator_serverdown xymond_worker.o
locator_serverup xymond_worker.o
locator_init xymond_worker.o
locator_register_server xymond_worker.o
ld: fatal: Symbol referencing errors. No output written to ../client/xymond_client
collect2: ld returned 1 exit status
gmake[1]: *** [../client/xymond_client] Error 1
gmake[1]: Leaving directory `/tmp/xymon/xymond'
gmake: *** [xymond-client] Error 2


I was receiving this error for Xymon versions: 4.2.3 to 4.3.7 when trying to make a client version of Xymon.


To repeat the process, this is exactly what I did...
1. SSH onto a Solaris box (SunOS servername 5.9 Generic_112233-05 sun4u sparc SUNW,Sun-Fire-V210) as root.

2. Unzip Xymon source and run configure for a client install "./configure --client"

3. 'gmake' to make the libraries.


Solution
The error relates to a missing symbol that requires referencing in the Makefile so gcc knows where to find the locator symbols.

Add "locator.o" to CLIENTLIBOBJS in lib/Makefile

Now you should be able to do a make.

Thursday, 26 April 2012

Managing Swapfiles in Linux


Swapfiles
If you run anything close to a modern operating system, you almost certainly interact with a swap file. You might be familiar with the basics of how these work: they allow your OS to prioritize more frequently-used pages in main memory and move the less frequently-used ones to disk. But there's a lot going on underneath the covers. Here's a simple guide to swap files in Linux.


Making a new swap file is a simple process. In this example, we'll make a 2 GiB swap file and make it available to the system as additional swap space. We'll use swapfile as the name of the example swap file, but there is nothing special about the name of the file or its extension. You may use anything you wish.

First, we need to create the swap file itself. We'll use a stream of zeroes as the input source (if=/dev/zero), and write it out to a file named swapfile in the root directory. We will write 2048 (count=2048) blocks each 1 MiB in size (bs=1M). Depending on the speed of your hard disks, this may take a little while.


Code Snippet
  1. dd if=/dev/zero of=/swapfile bs=1M count=2048
  2. chmod 600 /swapfile
  3. mkswap /swapfile
  4. swapon -v /swapfile
End of Code Snippet

mkswap - Formats this file and prepares it for use as a swapping space. The mkswap utility sets up a swap area on a device or file.

swapon - After formatting it, the swap can now be added to our system. The swapon utility activates the swap region.



Reboot Persistence
To activate /swapfile after Linux system reboot, add entry to /etc/fstab file. Open this file using a text editor such as vi...
Code Snippet
  1. vi /etc/fstab
End of Code Snippet


Append the following line:
Code Snippet
  1. /swapfile swap swap defaults 0 0
End of Code Snippet

Creating a Live USB with MAC and Windows



Live USB
A live USB is a USB flash drive or a USB external hard disk drive containing a full operating system that can be booted. Live USBs are closely related to live CDs, but sometimes have the ability to persistently save settings and permanently install software packages back onto the USB device.


Example
Here's an example, we would like to take a distribution of ubuntu linux, and install it on to a USB Flash Drive. We can then insert it into a machine, change the BIOS order, and boot directly from the USB and use the OS directly on the flash drive.


MAC OS X

1. [Optional] If your OS image (I.e. ubuntu-11.10-desktop-i386.iso) is an ISO file, we need to convert this into .img format. We can do this by using the hdiutil utility.

Code Snippet
  1. hdiutil convert -format UDRW -o ubuntu-11.10-desktop-i386.img ubuntu-11.10-desktop-i386.iso
End of Code Snippet


2. Enter this command into a Terminal window...
Code Snippet
  1. diskutil list
End of Code Snippet

We need to identify which drive is our USB Flash Drive. If you cannot tell, then run the command before inserting drive, and again, afterwards. You will notice which entry belongs to the newly inserted drive. I.e. /dev/disk3


3. Mac OS X will automatically mount the memory stick into Finder, so we must unmount the drive (This is not the same as ejecting it) and it will prevent us from seeing "Resource Busy" errors.
Code Snippet
  1. sudo diskutil umountDisk /dev/diskX
End of Code Snippet

(Where diskX is the disk corresponding to your USB Flash Drive).


4. We can now use dd to extract the image on to the disk.
Code Snippet
  1. sudo dd if=ubuntu-11.10-desktop-i386.img of=/dev/diskX bs=1m
End of Code Snippet

(Where diskX is the disk corresponding to your USB Flash Drive). This step may take a while depending on the size of the image.


5. Eject the flash disk using diskutil.
Code Snippet
  1. diskutil eject /dev/diskX
End of Code Snippet


(Where diskX is the disk corresponding to your USB Flash Drive).


You can now boot directly from the USB into your loaded operating system. Remember to go into the BIOS on the host system and change the Boot Priority, making the USB Flash Drive higher than the host HDD itself.



Windows

Windows users have a few options, you can repeat the above steps with a verison of dd for windows, however I have found that the following method is by far easiest!

1. Download your required operation system (.iso, .img etc)

2. Download Linux Live USB Creator

3. Launch Linux Live USB Creator, specify the OS image, the target Flash Drive (make sure its plugged in) and simply click the Lightning logo. All done!


You can now boot directly from the USB into your loaded operating system. Remember to go into the BIOS on the host system and change the Boot Priority, making the USB Flash Drive higher than the host HDD itself.

Manually remove Oracle installation from Linux


Stop all the databases and listener on the box either manually or using your startup script
Code Snippet
  1. /etc/init.d/oracle stop
End of Code Snippet


You can view all oracle processes using the command, this will search all running processes that begin with 'ora'.
Code Snippet
  1. ps -ef | grep ora
End of Code Snippet


Kill the relevent processes using the process' PID and the kill command
Code Snippet
  1. kill <PID>
End of Code Snippet


Remove all files within your $ORACLE_BASE directory (Don't forget to re-create this directory structure on a new install)
Code Snippet
  1. rm -rf $ORACLE_BASE
End of Code Snippet


Remove all Oracle references in etc
Code Snippet
  1. rm -rf /etc/ora*
End of Code Snippet


Remove any temporary files
Code Snippet
  1. rm -rf /tmp/.oracle
  2. rm -rf /var/tmp/.oracle
End of Code Snippet


This should be enough to remove Oracle from the machine...

Tuesday, 24 April 2012

cron/crontab Task Scheduler - HOW TO


cron
cron is a time-based job scheduler in Unix-like computer operating systems. cron enables users to schedule jobs (commands or shell scripts) to run periodically at certain times or dates. It is commonly used to automate system maintenance or administration, though its general-purpose nature means that it can be used for other purposes, such as connecting to the Internet and downloading email.


To view the cron list on your current OS, execute the following command...
Code Snippet
  1. crontab -l
End of Code Snippet


The cron list above shows you which jobs are currently runing on your system. It may be totally empty, or it may have some jobs in there. Lets take a look at adding jobs to the cron list.


Adding jobs to the cron list
The cron list is like a plain text file... the location of this depends of what OS you are running. However, we can simply edit the cron list by executing the following command...
Code Snippet
  1. crontab -e
End of Code Snippet

If you cannot view the cron list, then you may need to set the EDITOR environment variable to your default editor (nano, vi etc...)


Now we have the cron list in view, lets look at adding a job...

All jobs in the cron list take the following format (We can also forward the output to another process, we'll look at this later).



 *   *    *   *   *    Command to be executed
┬   ┬  ┬  ┬  ┬
│ │ │ │ │
│ │ │ │ │
│ │ │ │ └───── day of week (0 - 6) (0 is Sunday, or use names)
│ │ │ └────────── month (1 - 12)
│ │ └─────────────── day of month (1 - 31)
│ └──────────────────── hour (0 - 23)
└───────────────────────── min (0 - 59)


Lets take a look at this example...
30 22 * * * /usr/local/bin/TenThirtyScript.sh >>/usr/local/CronLog.log 2>&1

This cron entry will execute the "TenThirtyScript.sh" script every day at 22:30... It will also store all of the scripts output in the "CronLog.log" file (useful for debugging cron entries!)

Extra Info (What does 2>&1 mean?)
2 is the default file descriptor for stderr.
1 is the default file descriptor for stdout.
>& is shell syntax for "fold a file descriptor into another"


Special Characters
We can also schedule more complex cron jobs using some special characters.

Asterisk ( * )
The asterisk indicates that the cron expression will match for all values of the field; e.g., using an asterisk in the 4th field (month) would indicate every month.

Slash ( / )
Slashes are used to describe increments of ranges. For example 3-59/15 in the 1st field (minutes) would indicate the 3rd minute of the hour and every 15 minutes thereafter. The form "*/..." is equivalent to the form "first-last/...", that is, an increment over the largest possible range of the field.

Percent ( % )
Percent-signs (%) in the command, unless escaped with backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.

Comma ( , )
Commas are used to separate items of a list. For example, using "MON,WED,FRI" in the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.

Hyphen ( - )
Hyphens are used to define ranges. For example, 2000-2010 would indicate every year between 2000 and 2010 CE inclusive.

L
'L' stands for "last". When used in the day-of-week field, it allows you to specify constructs such as "the last Friday" ("5L") of a given month. In the day-of-month field, it specifies the last day of the month.

W
The 'W' character is allowed for the day-of-month field. This character is used to specify the weekday (Monday-Friday) nearest the given day. As an example, if you were to specify "15W" as the value for the day-of-month field, the meaning is: "the nearest weekday to the 15th of the month". So if the 15th is a Saturday, the trigger will fire on Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you specify "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary of a month's days. The 'W' character can be specified only when the day-of-month is a single day, not a range or list of days.

Hash ( # )
'#' is allowed for the day-of-week field, and must be followed by a number between one and five. It allows you to specify constructs such as "the second Friday" of a given month.[citation needed]

Question mark ( ? )
Note: Question mark is a non-standard character and exists only in some cron implementations. It is used instead of '*' for leaving either day-of-month or day-of-week blank.


Here are some more examples...

23:00:00 every weekday night
0 23 * * MON-FRI /usr/local/bin/TestScript.sh >/dev/null 2>&1

In 2003 on the 11th to 26th of each month from January to June every third minute starting from 2 past 1am, 9am and 10pm
2-59/3 1,9,22 11-26 1-6 * 2003 /usr/local/bin/TestScript.sh >/dev/null 2>&1


Note: ">/dev/null" forwards the output to a bottomless pit! Useful if you want to remove trace of the output completely.



cron Permissions
The following two files play an important role:

/etc/cron.allow - If this file exists, then you must be listed therein (your username must be listed) in order to be allowed to use cron jobs.

/etc/cron.deny - If the cron.allow file does not exist but the /etc/cron.deny file does exist, then you must not be listed in the /etc/cron.deny file in order to use cron jobs.

Please note that if neither of these files exists, then depending on site-dependent configuration parameters, only the super user will be allowed to use cron jobs, or all users will be able to use cron jobs.....



Saving Changes
Once you have made all the changes to the cron list file, save the file (I.e. !wq in vi)

You will now need to restart the cron service to pick up your changes.
Code Snippet
  1. /etc/init.d/cron stop
  2. /etc/init.d/cron start
End of Code Snippet


This command depends on which OS you are running.... See this link for restarting services on various distros of Linux: http://theos.in/desktop-linux/tip-that-matters/how-do-i-restart-linux-network-service/

Wednesday, 18 April 2012

Apple/iTunes - Create an App Store account for another country (US/UK etc...)


This is useful if you would like to use an app on your iPhone or iPad only available in a certain country.

1. Change your country setting in the app store
http://downloadsquad.switched.com/2010/03/05/how-to-create-a-us-itunes-app-store-account-when-youre-not-in-t/

2. Create a new app store account without credit card
http://support.apple.com/kb/HT2534

3. Search for the application you would like and add it to your downloaded apps.

4. Sync your apps with your iPhone... All done!

Monday, 2 April 2012

The folder "iTunes" is on a locked disk or you do not have write permissions for this folder.


Problem: iTunes requires write access to the iTunes directory located in your local user's music directory.

MAC OS X
1. Navigate to /Users/home/Music
2. Command+i on the iTunes directory (Opens the directory info)
3. Click the padlock in the bottom right and enter administrator credentials for the local machine...
4. Add your current user to the list of users with access (If it's not currently there)
5. Open the 'Privilege' dropdown for the current user, and select 'Read & Write'.
6. Click the padlock to lock the permissions.
7. Restart iTunes.


Windows
I don't have a Windows machine handy at the moment, but the process will be similar...

1. Navigate to 'My Documents' for the current user.
2. Right click and Properties for the iTunes directory (Either in here, or in the 'My Music' directory.
3. Set write permissions for the logged in user.
4. Restart iTunes.

Mac OS X - Package Management with MacPorts


MacPorts
The MacPorts Project is an open-source community initiative to design an easy-to-use system for compiling, installing, and upgrading either command-line, X11 or Aqua based open-source software on the Mac OS X operating system.

You can obtain MacPorts from the download page as a package (For Lion, Snow Leopard and Leopard - At time of writing) or you can build from source.
This will typically be installed into /opt/local/bin, so make sure this sits in your PATH.

Update MacPorts
Code Snippet
  1. port selfupdate
End of Code Snippet

View installed ports
Code Snippet
  1. port installed
End of Code Snippet

Search for ports
Code Snippet
  1. port search apache2
End of Code Snippet

Get information about a port
Code Snippet
  1. port info apache2
End of Code Snippet

Find out dependencies for a port
Code Snippet
  1. port deps apache2
End of Code Snippet

See what variations for a port are available (I.e. with/without SSL)
Code Snippet
  1. port variants apache2
End of Code Snippet

Install a port (-f = Force activation)
Code Snippet
  1. sudo port install -f apache2
End of Code Snippet

Clean an installed port
Code Snippet
  1. sudo port clean --all apache2
End of Code Snippet

Uninstall a port
Code Snippet
  1. sudo port uninstall apache2
End of Code Snippet

Display files belonging to an installed port
Code Snippet
  1. port contents apache2
End of Code Snippet

Upgrade a port
Code Snippet
  1. sudo port upgrade apache2
End of Code Snippet


More information can be found on the official MacPorts Guide.

Friday, 30 March 2012

HTTP POST Test site


Use this website if you would like to test your HTTP POST scripts/programs without having to write a server-side test solution.

http://www.posttestserver.com/

Using curl to download files


Example
Code Snippet
  1. curl -C - -O http://www.mirror.com/path/to/NeoOffice-Patch.dmg
End of Code Snippet

Parameters Used
-o/--output Write output to instead of stdout (Outputs the file to the window by default)
-C/--continue-at Resumed transfer offset

Unix - I don't know what kind of terminal you are on - all I have is 'xterm-color'.


If you receive the following error, typically when using text editors like vi, then you need to change your Terminal (Environment variable: TERM)

xterm-color: Unknown terminal type
I don't know what kind of terminal you are on - all I have is 'xterm-color'.


Depending on which shell your using, set the following...

csh shell
Code Snippet
  1. setenv TERM xterm
End of Code Snippet

bash
Code Snippet
  1. export TERM='xterm'
End of Code Snippet

xterm is an example of a terminal emulator. You can use whichever you would like, it's simply a program that emulates a video terminal within some display architecture. Programs gather information from the terminal your currently using (Set in TERM) to aide the display of the content/program.

Here is a good list of various terminals you can try: List of Terminals

Unix Shells


csh (C-Shell)
The C shell is a command processor that's typically run in a text window, allowing the user to type commands which cause actions. The C shell can also read commands from a file, called a script. Like all Unix shells, it supports filename wildcarding, piping, here documents, command substitution, variables and control structures for condition-testing and iteration. What differentiated the C shell, especially in the 1980s, were its interactive features and overall style. Its new features made it easier and faster to use. The overall style of the language looked more like C and was seen as more readable.

tcsh (TENEX C-Shell)
On many systems such as Mac OS X and Red Hat Linux csh is actually tcsh, an improved version of csh. One file containing the tcsh executable has links to it as both "csh" and "tcsh" so that either name refers to the same improved version of the C shell.

On Ubuntu and Solaris machines, there are two different packages: csh and tcsh. The former is a based on the original BSD version of csh and the later is the improved tcsh. To enable the improved version of csh (tcsh), just type 'tcsh'... You will now notice you have access to command history, working arrows etc...

Other shells exist, such as: bash, sh, ksh, zsh, rc etc... Each having their own unique advantages, however, the common shell principles still apply.



Shell startup Scripts (.files)
When you enter a shell (by logging in for example) or switch to another shell (su or executing a different shell), certain shell startup scripts will be executed. It can become confusing as to which shells use which files (I.e. .cshrc, .profile etc etc).

The following as a list of which shells use which files...

csh
Some versions have system-wide .cshrc and .login files. Every
version puts them in different places.

Start-up (in this order):
.cshrc - always; unless the -f option is used.
.login - login shells.

Upon termination:
.logout - login shells.

Others:
.history - saves the history (based on $savehist).

tcsh
Start-up (in this order):
/etc/csh.cshrc - always.
/etc/csh.login - login shells.
.tcshrc - always.
.cshrc - if no .tcshrc was present.
.login - login shells

Upon termination:
.logout - login shells.

Others:
.history - saves the history (based on $savehist).
.cshdirs - saves the directory stack.

sh
Start-up (in this order):
/etc/profile - login shells.
.profile - login shells.

Upon termination:
any command (or script) specified using the command:
trap "command" 0

ksh
Start-up (in this order):
/etc/profile - login shells.
.profile - login shells; unless the -p option is used.
$ENV - always, if it is set; unless the -p option is used.
/etc/suid_profile - when the -p option is used.

Upon termination:
any command (or script) specified using the command:
trap "command" 0

bash
Start-up (in this order):
/etc/profile - login shells.
.bash_profile - login shells.
.profile - login if no .bash_profile is present.
.bashrc - interactive non-login shells.
$ENV - always, if it is set.

Upon termination:
.bash_logout - login shells.

Others:
.inputrc - Readline initialization.

zsh
Start-up (in this order):
.zshenv - always, unless -f is specified.
.zprofile - login shells.
.zshrc - interactive shells, unless -f is specified.
.zlogin - login shells.

Upon termination:
.zlogout - login shells.

rc
Start-up:
.rcrc - login shells

pkg-get and pkgutil package management for Solaris/SunOS


pkg-get
Pkg-get is an open-source, Sun-approved software installation and management tool for Sun Solaris. You can use pkg-get to install a variety of pre-compiled software without having to worry about version compatibility, patch requirements, libraries, or any other prerequisites.

pkgutil
Pkgutil, written in Perl and licensed under GPL, is a tool to make installation of packages in Solaris easier. It handles package dependencies so all required packages are installed before the desired package automatically. This is based on functionality present in apt-get (Debian Linux).

Which tool?
Both tools offer a similar deal... They aide package management on SunOS, they work out dependencies for packages and versioning is controlled by the package manager. I personally use pkgutil, simply because The Open Community Software Project (OpenCSW) has now deprecated support for pkg-get users (This is a large database of free Solaris packages - Note: There are many others you can use with pkg-get)

OpenCSW/Blastwave
The Open Community Software Project (OpenCSW) is an open-source project providing Solaris binary packages of freely available or open-source software. This was previously hosted at Blastwave. The project was originally Blastwave, but this was forked to created The OpenCSW.
OpenCSW provides packages for Solaris 9 and 10, for 32 and 64-bit, x86 and SPARC architectures. Solaris 8 is no longer a 1st-class supported OS[2]: however, there still exists a legacy Solaris 8 archive, which occasionally gets updates.

This isn't the only place to retrieve Solaris packages, but with a nice large database (3500+ packages at time of writing), its quite beneficial to consume.

Getting Started with pkgutil
http://www.blastwave.org/jir/blastwave.fam


Mirrors
OpenCSW/Blastwave do not directly host packages... A number of mirror sites are available to get these, but you must set this in your pkgutil config file. This is typically located here: /etc/opt/csw/pkgutil.conf

To view a list of mirrors, visit The OpenCSW Mirror Page

When selecting a mirror, you must add '/stable' or '/unstable' to the end of the URL. Unstable packages will be more up to date, but may have bugs present. Stable, on the other hand, will have older packages but more robust.

Open your configuration file for editing and alter the "mirror" section. The below example is a stable UK mirror site.
Code Snippet
  1. mirror=http://www.grangefields.co.uk/mirrors/csw/stable/
End of Code Snippet

Save the file and attempt to update the pkgutil catelog (Basically an index of all availalbe packages for a mirror).

Update the pkgutil catelog
Code Snippet
  1. pkgutil -U
End of Code Snippet

Now the catelog is up to date, we can begin to use pkgutil to download and install packages.


Things to note
Ensure wget is in your system PATH (which wget)... pkgutil ships with it's own version, but most distributions of Solaris have a version located here: /usr/sfw/bin

Update pkgutil using the following command
Code Snippet
  1. pkgutil -u pkgutil
End of Code Snippet

Install packages using the following (I.e. bash)
Code Snippet
  1. pkgutil -i bash
End of Code Snippet

Thursday, 22 March 2012

Download older versions of Oracle products


Welcome to the Oracle Software Delivery Cloud

Wednesday, 21 March 2012

Rar Command Line Usage Examples


Rar a single file/directory
Code Snippet
  1. rar a NameOfYourArchive.rar /path/to/file
End of Code Snippet

Rar multiple files
Code Snippet
  1. rar a NameOfYourArchive.rar /path/to/files/*
End of Code Snippet

Unrar a *.rar compressed file
Code Snippet
  1. unrar x NameOfYourArchive.rar
End of Code Snippet

List the contents of a rar file without uncompressing it
Code Snippet
  1. unrar l NameOfYourArchive.rar
End of Code Snippet

Restarting and managing services on Mac OS X


Method 1

Searching running processes to get he PID, then killing it (The service will automatically restart).

Example
Code Snippet
  1. sudo ps -A | grep -i ssh
End of Code Snippet

23450 ?? S 0:00.12 /usr/sbin/sshd -i
23455 ?? S 0:00.03 /usr/sbin/sshd -i
23649 p8 S+ 0:00.00 grep -i ssh


Now use 'kill' on the PID...
Code Snippet
  1. sudo kill 23450
End of Code Snippet



Method 2

launchd is a unified, open-source service management framework for starting, stopping and managing daemons, applications, processes, and scripts. Written and designed by Dave Zarzycki at Apple, it was introduced with Mac OS X Tiger and is licensed under the Apache License.

We will be using launchctl, a subset of this framework to manage services...

List all services
Code Snippet
  1. launchctl list
End of Code Snippet

We can then use this list to identify the names of our services.

Here's an example with SSH...

Stopping a service
Code Snippet
  1. launchctl stop com.openssh.sshd
End of Code Snippet

Starting a service
Code Snippet
  1. launchctl start com.openssh.sshd
End of Code Snippet

How to enable X11 Forwarding with SSH on Mac OS X


The aim of this blog post is to discuss how to display an X window from a target machine on our local system.

A good example here would be the Oracle installer for linux... when the installer is executed, it utilises the windowing system configured to display the installer via. SSH. Lets see how we can set this up...


What is the X windowing system (or X11)
The X window system (commonly X Window System or X11, based on its current major version being 11) is a computer software system and network protocol that provides a basis for graphical user interfaces (GUIs) and rich input device capability for networked computers.

Advantages of using SSH for X11 Traffic
- No problems with firewalls, as long as they let SSH pass through (No need to allow access to tcp-port 6000+)
- Communication is encrypted


Note to other OS users [Windows etc]
As long as your software/OS implements the X windowing system, you will be able to display X windows. For windows users, I recommend PuTTY


Mac OS X Configuration

Enable X11 Forwarding in sshd_config
In order to allow X11 forwarding to pass through SSH, we need to enable X11 Forwarding in our config for SSH. This is located in a file called sshd_config and found typically here: /etc/sshd_config or /etc/ssh/sshd_config

Uncomment out the line "# X11Forwarding no" and set it to "yes" (If this hasn't been done already. You will be left with this configuration...

Code Snippet
  1. X11Forwarding yes
End of Code Snippet

Save the file, and restart the sshd service...


Add your target system to the access control list
So our windowing system on our local machine has an access control list (We cant let anybody in as and when we please!)... So we need to allow our target system access to our windowing system.

Code Snippet
  1. xhost fullyqualified.server.name
End of Code Snippet

You will then see this message to confirm...
fullyqualified.server.name being added to access control list


SSH onto our target machine (with the apps using the windowing system. I.e. Oracle Installer)
We can now SSH onto our target machine...

Code Snippet
  1. ssh -X user@fullyqualified.server.name
End of Code Snippet


Ensure the DISPLAY environment variable is configured correctly
On the machine we just SSH'd onto, we need to make sure the DISPLAY environment variable is configured correctly. Our apps will use this to find out where our target machine that supports the X windowing system is located.

Code Snippet
  1. DISPLAY=fullyqualifiedaddressforourhostmachine:0.0
End of Code Snippet

Ensure this has been set correctly...
Code Snippet
  1. echo $DISPLAY
End of Code Snippet

Now lets test to see if our X apps can use our host windowing system via. SSH...
Code Snippet
  1. xclock &
End of Code Snippet

If you do not have xclock, or maybe your trying to execute an installer for Oracle or something, then try and execute the installer.


Gotchas
- Do not set the DISPLAY variable in any login scripts (I.e. bashrc, bash_profile etc...)

Friday, 9 March 2012

Python - POST HTTP multipart form (Using standard urllib libraries)


The Python script in this example utilises standard Python libraries to POST a form with content type multipart/form-data over HTTP (or quite simply, a multipart form).

The content type "multipart/form-data" should be used for submitting forms that contain files, non-ASCII data, and binary data.

I won't delve deep into the details on multipart forms, but if you would like a good explanation, read the official W3C document. One thing if doesn't mention on there, is that the boundary can be between 1 and 70 characters long, consisting of alphanumeric, and the punctuation you see in the list. Spaces are allowed except at the end.

Code Snippet
  1.     import itertools
  2.     import mimetools
  3.     import mimetypes
  4.     from cStringIO import StringIO
  5.     import urllib
  6.     import urllib2
  7.      
  8.     class MultiPartForm(object):
  9.         """Accumulate the data to be used when posting a form."""
  10.      
  11.         def __init__(self):
  12.             self.form_fields = []
  13.             self.files = []
  14.            
  15.             # Generate unique boundary string with the format: hostipaddr.uid.pid.timestamp.random
  16.             self.boundary = mimetools.choose_boundary()
  17.             return
  18.        
  19.         def get_content_type(self):
  20.             return 'multipart/form-data; boundary=%s' % self.boundary
  21.      
  22.         def add_field(self, name, value):
  23.             """Add a simple field to the form data."""
  24.             self.form_fields.append((name, value))
  25.             return
  26.      
  27.         def add_file(self, fieldname, filename, fileHandle, mimetype=None):
  28.             """Add a file to be uploaded."""
  29.             body = fileHandle.read()
  30.             if mimetype is None:
  31.                 mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
  32.             self.files.append((fieldname, filename, mimetype, body))
  33.             return
  34.        
  35.         def __str__(self):
  36.             """Return a string representing the form data, including attached files."""
  37.             # Build a list of lists, each containing "lines" of the
  38.             # request.  Each part is separated by a boundary string.
  39.             # Once the list is built, return a string where each
  40.             # line is separated by '\r\n'.  
  41.             parts = []
  42.             part_boundary = '--' + self.boundary
  43.            
  44.             # Add the form fields
  45.             parts.extend(
  46.                 [ part_boundary,
  47.                   'Content-Disposition: form-data; name="%s"' % name,
  48.                   '',
  49.                   value,
  50.                 ]
  51.                 for name, value in self.form_fields
  52.                 )
  53.            
  54.             # Add the files to upload
  55.             parts.extend(
  56.                 [ part_boundary,
  57.                   'Content-Disposition: file; name="%s"; filename="%s"' % \
  58.                      (field_name, filename),
  59.                   'Content-Type: %s' % content_type,
  60.                   '',
  61.                   body,
  62.                 ]
  63.                 for field_name, filename, content_type, body in self.files
  64.                 )
  65.            
  66.             # Flatten the list and add closing boundary marker,
  67.             # then return CR+LF separated data
  68.             flattened = list(itertools.chain(*parts))
  69.             flattened.append('--' + self.boundary + '--')
  70.             flattened.append('')
  71.             return '\r\n'.join(flattened)
  72.      
  73.      
  74.      
  75.      
  76.      
  77.     if __name__ == '__main__':
  78.      
  79.         # Create the form with simple fields
  80.         form = MultiPartForm()
  81.        
  82.        
  83.         """
  84.            Either specify a source, file or a url...
  85.            The system will take the first one respectively if all three have content.
  86.            This example uses a dummy file called test.sql, with a string of content.
  87.       """
  88.        
  89.         # No source specified
  90.         form.add_field('source', '')
  91.        
  92.         # REAL FILE EXAMPLE
  93.         # fileHandle = open ('test.sql', 'r')
  94.         # form.add_file('file', 'test.sql', fileHandle)
  95.         # fileHandle.close()
  96.        
  97.         # Use dummy file
  98.         form.add_file('file', 'test.sql', fileHandle=StringIO('FILE CONTENTS'))
  99.        
  100.         # No URL specified
  101.         form.add_field('url', '')
  102.        
  103.        
  104.        
  105.         # Add remaining required parameters
  106.         form.add_field('language', 'php')
  107.         form.add_field('line_numbers', '2')
  108.         form.add_field('word_wrap', 'on')
  109.         form.add_field('tab_width', '8')
  110.         form.add_field('highlight_keywords', 'on')
  111.         form.add_field('default_color', '0000bb')
  112.         form.add_field('keyword_colors[1]', 'DEFAULT')
  113.         form.add_field('keyword_colors[2]', 'DEFAULT')
  114.         form.add_field('keyword_colors[3]', 'DEFAULT')
  115.         form.add_field('keyword_colors[4]', 'DEFAULT')
  116.         form.add_field('comments_color', 'DEFAULT')
  117.         form.add_field('escaped_chars_color', 'DEFAULT')
  118.         form.add_field('brackets_color', 'DEFAULT')
  119.         form.add_field('strings_color', 'DEFAULT')
  120.         form.add_field('numbers_color', 'DEFAULT')
  121.         form.add_field('methods_color', 'DEFAULT')
  122.      
  123.         # Build the request
  124.         request = urllib2.Request('http://qbnz.com/highlighter/php_highlighter.php')
  125.        
  126.         # Hi i'm FireFox 5
  127.         request.add_header('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11')
  128.        
  129.         # We are required to specify the content type and length...
  130.         body = str(form)
  131.         request.add_header('Content-type', form.get_content_type())
  132.         request.add_header('Content-length', len(body))
  133.         request.add_data(body)
  134.      
  135.             # Take a look at what we are sending... useful to match up against the required request
  136.         print
  137.         print 'OUTGOING DATA:'
  138.         print request.get_data()
  139.      
  140.             # View servers response
  141.         print
  142.         print 'SERVER RESPONSE:'
  143.         print urllib2.urlopen(request).read()
End of Code Snippet