Linux: Shell command to save webpage to file

This only saves the webpage to a file, but not linked images or stylesheets.

wget -O - > homepage.html > output.html

Be sure to remember to escape special characters such as ";" with "\".

Thunderbird: Security Error: Domain Name Mismatch

While setting up an email address for myself on my domain, I stumbled upon some certification error messages in Thunderbird when using an authenticated SMTP server.

You have attempted to establish a connection with "". However, the security certificate presented belongs to "". It is possible, though unlikely, that someone may be trying to intercept your communication with this web site.

If you suspect the certificate shown does not belong to "", please cancel the connection and notify the site administrator.

The annoying little confirmation box that appears every time
you try to send an email.

This is due because my domain is running off a shared server "" which points to the server which is running the SMTP server "".

The easiest way to solve this is to change your SMTP server address from "" to the one that matches the certificate. If the login details are correct, it shouldn't matter.

Another way is to install the Remember Mismatched Domains extension into Thunderbird.

The slightly altered confirmation box when using the extension.

Port Forwarding with NetGear DGN2000

I recently replaced my NetComm NB5Plus4W recently and had a bit of trouble getting my NetGear DGN2000 modem router to forward the ports properly.

Unfortunately, it was hidden under an unexpected link. Luckily, it was quite easy to configure.

Log in to your DGN2000 router configuration page at and click on "Firewall Rules" on the left side column.

Under "Inbound Services", click "Add".

Select the port range you want (or to forward everything, select "Any(ALL)") from the service list and "ALLOW always" for action.

Enter in the IP address of the machine you want the information to be relayed to under "Send to LAN server" and select "Any" for "WAN Users".

Disable logging in case you don't want the log to be filled up.

Apply and finish up to add the new rule.

The configuration should look something like this.

Now click apply to save the new settings for the firewall.

To test if the port forwarding has worked, use this page from uTorrent and it should give you a big green tick if port 58139 is forwarded correctly.

*edit 30/11/2009* - If you find your router is freezing up often, see Netgear DGN2000 overheating issues.

Thunderbird: Disable Return Receipts

Sometimes its annoying when a person has return receipts enabled whenever they send out an email.

Thunderbird users will see a message box confirming "The sender of this message has asked to be notified when you read this message. Do you wish to notify the sender?" every time you read a new email from them.

notify senderRather annoying... Kill it!

  • Go to the "Tools" menu and select "Options".
  • Select the "Advanced" tab and then "General"
  • image
  • Click on the "Return Receipts" button.
  • Select "Never send a return receipt".
  • image
  • Crack open some celebration drinks!

Easyway, the perfect celebration drink.

Django: Starting your first project

Assuming that Django has been installed and configured correctly, its quick and simple for you to start new projects.

Firstly, go to the folder you'd like to place the project and type:

django-admin startproject yourproject

Change the directory into "yourproject" and create a new app for a new component in your project:

django-admin startapp yourname

Now you have a project called "yourproject" and application called "yourapp".

Modify the "" file to configure your project. Take this opportunity to set up your database information while the file is open.

To include your application into the project, add the line "yourapp" to the list of installed applications in "INSTALLED_APPS".

Run the server and test if it works properly.

./ runserver


python runserver


Now you can start setting up pages and serve CSS and JS files. For more guides, see the django tag.

PHP: Get contents from a page protected by password

Retrieving the contents of a webpage in PHP5 is really easy these days. You simply make a call to file_get_contents() and it automatically handles the request and parsing for you. It even works for local files!

Now, what if the page you're trying to access requires authentication? Luckily, its not difficult to do this either.

// Set up the authentication information
$url = "";
$username = "administrator";
$password = "p455word";

// Set up the context stream
$context_info = array(
  'http' => array(
    'header' => "Authorization: Basic " . base64_encode("$username:$password")
$context = stream_context_create($context_info);

// Retrieve the page
$data = file_get_contents($url, false, $context);

The data scraped from the page should now be contained within the $data variable.

[ Source ]

Django: How to set up a page

Edit your "project/" to include your app "".

urlpatterns = patterns('',
    # Some default url patterns here...
    (r'^example/', include('yourapp.urls')),

Now thats done, you can safely customise any urls in your app without affecting anything else in the project.

Edit "project/yourapp/" and put in the following.

from django.conf.urls.defaults import patterns, url

urlpatterns = patterns('',
    url(r'^$', 'yourapp.views.home'),

The first case is simple, you simply point your browser to and it'll show you the output of 'yourapp.views.home'.

Now, what is that supposed to be? "" maps the URL request to a view and a view is implemented in your app "" file. This view handles the URL requests with the behaviour and logic you provide it.

Edit "project/yourapp/" and put in the following text.

from django.shortcuts import render_to_response

def home(request):
    return render_to_response("yourapp/home.html")

See the tutorial on how to create Django templates in order to understand what "home.html" contain, but for now just create "youapp/templates/yourapp/home.html" and throw in some random text in there.

Open up in the browser and your random text should appear. Horray! You have just successfully mapped the first url to a view.

The next crumb

The second url handler will resolve the http://yourdomain/example/test request by mapping "test" to test_view().

And add a new url mapping "url(r'^test$', 'yourapp.views.test_view)" to the "urlpatterns" in your app "" file.

Create a method called test_view() in your "" file.

def test_view(request):
    return render_to_response("yourapp/home.html")

At this point you can reuse your "home.html" or create a new template file. Try it, it might make you happy =)

Input arguments from URL

The last url "url(r'^number/(?P<input_integer>\d+)/$', 'yourapp.views.example_with_input')" is a bit trickier. It maps http://yourdomain/example/number/345 (or any number in place of 345) to example_with_input().

def example_with_input(request, input_integer):
    print input_integer
    return render_to_response("yourapp/input_test.html", { 'number': input_integer })

Make sure that the named callback "input_integer" in the regular expression is the same as the argument in example_with_input() function.

The "print" line however isnt necessary, but it'll show the input number into the console where Django is running.

Now in the same folder as your "home.html" template, add "input_test.html". Edit it and fill in the following.

{{ number }}

That should now spit out whatever number you put into the url.

Django: How to create a template

In your app folder, create a new directory called "templates\appname" where appname is the name of the app you're creating the template for.

Now, create a new file which has a relevant name. For this example, I'll just use "app_template_example.html".

Fill it up with any sort of output you want such as HTML, Javascript or CSS.

{% if user.is_authenticated %}
<a href="#" onclick="login(); return false;">Login</a>
{% else %}
<a href="#" onclick="user_panel(); return false;">{{ user.username }}</a>
<a href="#" onclick="logout(); return false;">Logout</a>
{% endif %}

Now, this will print out one of either cases. If you're logged in, it'll display a login link. Otherwise, it'll display a link to your user panel with the title of your account name and a logout link.

A simple view handler can provide you with information such as "user" and anything else you'd like. It also tells your app which template to use.

from django.shortcuts import render_to_response

def example_view(request):
    return render_to_response('appname/app_template_example.html', { 'user' : request.user, 'custom_field': 'blah blah blah...' })

Now open the view in the browser and it should display the template. To do that, see the tutorial on how to create Django views.

Lastly, just edit the template and include "{{ custom_field }}" anywhere you like. Refresh the page and you'll be able to see how easy it is to feed more information into the template.

Python: Equivelant of PHP functions print_r() or var_dump()

When migrating from PHP/Drupal to Python/Django, the lack of variable debugging can really impede your ability to get a feel for whats going on.

In PHP, I use print_r() and var_dump() type functions almost out of habit, just to see what information is being passed through to learn how things are working, or for debugging.

I havn't actually managed to find something that does the same in Python thing yet, but this comes pretty close so far. I'm sure someone can use this to work out what they need to do with it.

print dir(obj)

The output of the function varies, depending on the type of object being parsed.

a = [ 1, 2, 3, 4, 5 ]

print a
# Outputs [ 1, 2, 3, 4, 5 ]

print dir(a)
# Outputs all methods
# ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Now the best part about this function is that it also prints out the attributes of a the class instance.

class ExampleClass():
    title = "Title"
    description = "Description of something"

    def my_class_function(self):
        return [ 1, 2, 3 ]

Using dir() on an instance of that class would give:

c = ExampleClass()
print dir(c)
# Outputs
# ['__doc__', '__module__', 'description', 'my_class_function', 'title']

If anyone knows how to make it work better, feel free to let me know!

Firefox: Disable extension install delay

When starting fresh from a new Firefox profile, you tend to reinstall all your extensions in 1 hit. Eventually the stupid 3 second countdown will get on your nerves.

Good news, its easy to remove.

  • Open a new tab and type in "about:config" into the address bar.
  • Filter "security.dialog_enable_delay".
  • Set the value to 0.
  • It should apply immediately.

PHP: Easy way to parse XML and RSS feeds

With PHP 5, you can use either simplexml_load_file() or simplexml_load_string() to get an instance of the SimpleXMLElement class.

This is a massively simplified feed from Digg. (Shame the example didn't include anything about Kanye West being a big jackass to Taylor Swift)

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <title> Stories / Popular</title>
  <description> Stories / Popular</description>
   <title>6 Russian Volcanoes Erupt Simultaneously</title>
   <pubDate>Wed, 16 Sep 2009 22:30:01 +0000</pubDate>
   <guid isPermaLink="false"></guid>
   <title>Happiness: The New Currency in France</title>
   <description>Gross domestic product, inflation, unemployment- these are old-fashioned, Anglo-Saxon indicators of national wellbeing, says the president of France. From now on, the country's economic progress will be measured in terms of happiness.</description>
   <pubDate>Wed, 16 Sep 2009 22:10:02 +0000</pubDate>
   <guid isPermaLink="false"></guid>
   <title>The 15 Weirdest Music Videos Of All Time</title>
   <description>Music videos changed the music industry completely. Artists were finally given a "visual voice" and fans were able to put faces with names. Musicians are often a little quirky however, resulting in many truly bizarre videos.</description>
   <pubDate>Wed, 16 Sep 2009 22:00:01 +0000</pubDate>
   <guid isPermaLink="false"></guid>

To parse the items in this list, simply use the following.

$rss = simplexml_load_file("");

echo "Parsing feed with title: " . $rss->channel->title;

foreach ($rss->channel->item as $item) {
  echo $item->title;
  echo $item->link;
  echo $item->description;
  echo $item->guid;

And there you have it, very simple.

Django: How to perform an Ajax post request

Setting up a simple Ajax on Django 1.1 with jQuery can be done fairly quickly if you follow some basic tips.

  • Reference the correct IDs.
  • Know the correct path base that you're working from.
  • Ensure the data is what you expect and return sufficient error information when something isn't right.


Firstly, set up your Ajax post handler URL. This will be your entry point to the request.

This part sets up the path to your app from your project. For example, we'll make example app. In your "" file, add the following URL pattern.

urlpatterns = patterns('',
url(r'^example/', include('example_app.urls')),

Now, within your example app "" file, add the pattern for your post handler.

urlpatterns = patterns('',
url(r'^post$', 'example_app.views.ajax_post', name="example_ajax_post"),

And there you have it, now you've got a URL for

The handler

Now we actually need that url to handle the request. Create a new function called "ajax_post", or something that matches "example_app.views.ajax_post".

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404
from django.utils import simplejson

def example_ajax_post(request):
Just an example handler for the Ajax request.
# Check if the information was posted.
if not request.method == 'POST':
raise Http404

data = { 'error': True, 'message': '' };

int_a = int(request.POST.get("field_a"))
int_b = int(request.POST.get("field_b"))
string_c = request.POST.get("field_c")

## Just some dummy code
# object = get_object_or_404(YourObjectClass, id = int_a)

if int_a < 0 or int_b < 0:
data['message'] = 'No negative numbers allowed.'
data['answer'] = 0
data['error'] = False
data['message'] = 'Request OK!'
data['answer'] = int_a + int_b

data = simplejson.dumps(data)
return HttpResponse(data, mimetype="application/javascript")

Now you have a working handler that spits out JSON output. Example below.

{ 'error': 0, 'answer': 3, 'message': 'Request OK!' }

Also, if you wish to ensure that only logged in users can access this handler, it is easier to add in the following decorator than implement a check.

def flag_inappropriate_ajax(request):

The Request

The last step is to make the request using JQuery.

<script type="text/javascript" charset="utf-8">
function example_post(field_a_value, field_b_value, field_c_value) {
callback = function(data, status) {
// If there were no errors, fill the field with the answer.
if (!data.error) {
$('#example_item_message').replaceWith("The answer is: " + data.answer);


// Note: the post url is relative to the URL of the current page
$.post('/example/post', { 'field_a': field_a_value, 'field_b': field_b_value, 'field_c': field_c_value }, callback, 'json');

This script will send a post request to "/example/post" with the given values.

The callback handles the response from JSON output from the post page. Data contains the JSON information already converted into a Javascript object.

[ Source ]

The file 'Asms' on Windows XP Professional CD-ROM is needed.

While repairing a Windows XP installation on my friend's computer, it ran into a strange problem.

"Files Needed"
The file 'Asms' on Windows XP Professional CD-ROM is needed. Type the path where the file is located, and then click OK.


Solution A:

The tricks from Microsoft's KB didn't work for me, but it may for you. The instructions are fairly straight forward, but heres a translation to make things a bit simpler.

Note: Only use this if you're using NTFS for your partition. Otherwise, see the linked KB above.

  • When the dialog appears, press "Shift + F10".
  • Type in "regedit" and press enter.
  • Click "File"
  • "Load Hive"
  • Type in "%Windir%\System32\Config\System.sav"
  • Enter "Test"
  • Go to "HKEY_LOCAL_MACHINE\Test\ControlSet1\Control\Class\{4D36E965-E325-11CE-BFC1-08002BE10318}"
  • Delete any items in the right panel called "UPPERFILTERS" or "LOWERFILTERS"
  • Now go back to "HKEY_LOCAL_MACHINE\Test" and see if there are any other "ControlSet####" keys.
  • Drill into "Control\Class\{4D36E965-E325-11CE-BFC1-08002BE10318}" for that keys and delete any "UPPERFILTERS" or "LOWERFILTERS" items. Repeat for all "ControlSet####" keys.
  • Close the Registry Editor.
  • Try clicking OK on the setup error to continue.
  • If it doesn't work, cancel and try restarting to resume the setup.

That seems to be the solution that works for most people. For me, I used Solution B.

Solution B:

This is the one that worked for me. The majority of user advice seemed to stem from the fact that the DVD/CD drive not being loaded properly. I kinda winged it using an educated guess.

  • Press "Shift + F10"
  • Type in "sysdm.cpl" and press enter
  • Go to "Hardware" tab
  • Click "Device Manager"
  • If the items under "DVD/CD-ROM drives" have a little yellow exclamation mark on them, right-click on it and select "Update driver"
  • Select "No, not this time"
  • Select "Install from a list or specific location (Advanced)"
  • Select "Don't search, I will choose the driver to install"
  • Select the first generic "CD Rom Drive" driver.
  • Finish the setup and it should load up your DVD drives.
  • Now, continue with the Windows XP repair by replacing "GLOBALROOT\DEVICE\CDROM0\I386" with "X:\I386"
  • Copy this into clipboard, you'll need it. (Yes, clipboard works even during setup! How awesome! Eat that crApple iPhone!)
  • Whenever the next popup appears, paste and press enter. You'll need to do this alot of times throughout the setup.

Solution C:

Try some of the solutions suggested here.

Some people claim that ejecting the CD and then putting it back in works. Others claim a full power cycle of your computer (turning it off for a while and unplugging the power) will work.

To be honest, I found that a clean install proved to be much better than a repair. It seemed to cause more trouble in the long run.


Arrow keys in Excel scrolls instead of moving cursor

Every once in a while, my work computer goes crazy and decides to do things I don't want it to. Perhaps the most annoying thing is when it decides to scroll in Excel and Lotus Notes rather than moving the current highlighted item cursor.

Its really frustrating and time consuming trying to work with something that doesn't behave the way you want it to, or at least the way you're used to.

Luckily, the solution was incredibly simple. The "Scroll Lock" feature on the keyboard was on. Guess the cleaners accidently trigger the button while the computer is locked.

Kinda embarrassing, its sorta like complaining that everything I type is in caps without checking if the caps lock is on.

Setting aliases using Linux bash shell script with arguments

Its useful to use shortcut commands for common tasks, especially when it comes to repository management.

I like to pipe diff output into vim and logs into less, but at times I have to switch between multiple repositories such as git, svn and bzr.

To use the same alias between the repositories, set up a script and give it an argument.

Create a script file to manage your aliases.

chmod +x

Create an alias to make it easier to access. You may want to put this into your ".bashrc" profile.

alias workwith="source ~/bin/"

Modify your "" file and paste

#! /bin/bash

if [ "$1" = "git" ]; then
        alias d="git diff | vim -"
        alias commit='git commit -m'
elif [ "$1" = "svn" ]; then 
        alias d="svn diff | vim -"
        alias commit='svn commit -m'
elif [ "$1" = "bzr" ]; then
        alias d="bzr diff --diff-options='-U 5 -p' | vim -"
        alias commit='bzr commit -m'
        echo "Unknown command"

Now, whenever you want to switch between the commands, type

workwith svn

workwith git

workwith bzr

Windows 7: Cannot view/access/list any other computers on network

On one strange occasion, with proper permissions and firewall settings set, my notebook running Windows 7 (Computer A) cannot display ANY computers on the network except for itself.

The Windows XP machine (Computer B) was correctly displaying the other computers in the network correctly. The other Windows XP machine (Computer C) was also listing everything correctly.

All the computers could ping each other correctly, except Windows Explorer got confused when trying to find them. Typing in the path manually didn't work either.

When trying to access Computer A from Computer B, I was prompted with a password dialog. Strangely enough, even though I typed the correct information it wouldn't let me connect.


So what was wrong with Computer A running Windows 7? For some reason, it was connected to both my wireless network and VMWare virtual network.

After doing a little snooping, I discovered that it was the "VMWare DHCP Service" and "VMWare NAT Service" services which were messing with my wireless network settings.

Go into the "Services Manager" (by running "services.msc") and stop the services mentioned above. Don't disable them, only stop.

Refresh the network browser and the other computers should display properly.

Windows 7: Change location of "My Documents" folder

Some people (ie. MedinaSoft) likes to have personal folders, such as "My Documents", on different drives instead of the default "C:\Users\Username\Documents".

  • Open up your current "My Documents" folder in Windows Explorer
  • Right click the folder
  • Properties
  • Select the "Locations" tab
  • Click "Move"
  • (Create) and select the folder you want as the new location for "My Documents"
  • Click "Apply"
  • Click "Yes"
  • Pop bottles and models.

Also, remember to update your "Documents" library once you've relocated the folder.

14/09/2009 - You can also do this for a bunch of other folders in your "Users" profile, like "My Music" and even "Desktop". It all works in the same way.

Windows 7: Disable pinning of items or programs on taskbar

Good on Microsoft for making a fancy new taskbar for the masses which resembles the Mac OSX dock thingy (that I dislike so much).

But props to the Big M for making it so damn configurable, compared to the dicktatorship of Apple which decides for people what is best for them or gtfo.

Steve Jobs: "Mmm bitches...
you will learn to love the taste of my cock in your mouth."

However, not everything new is something I find helpful. I don't really need the option to pin things to the taskbar, especially when I use the classic taskbar mode that doesn't even support pinning.

The options to configure this is in the same location:

  • Open "gpedit.msc"
  • Navigate through to "Local Computer Policy"
  • User Configuration
  • Administrative Templates
  • Start Menu and Taskbar

To disable pinning of applications:

Enable "Do not allow pinning of items to jumps".

image image
Before. After, without pinnable applications.


To disable pinning of items onto taskbar:

Enable "Do not allow pinning of programs to taskbar".

image image
Before. After, without pinnable items.

Windows: Disable "Windows can't open this file" and "Use the Web service to find the correct program" dialog

A crucial part of being an overpowering process overlord is learning every process that runs on your computer. Sometimes you will find a new file type, but will know exactly what to use to open it.

image That means I don't want no silly dialogs like this.

You can do this via the Command Prompt console (big bad black screen)

  • Run a command prompt with administrator access.
  • Paste in the following

reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer /v NoInternetOpenWith /t REG_DWORD /d 1 /f

  • Profit!

Or through Notepad (big white textbox)

  • You can open Notepad
  • Paste in the following
  • Windows Registry Editor Version 5.00


  • Change type to "All files" and save it as "NoInternetOpenWith.reg"
  • Run the file.

So now, after attempting to open an unknown file type, it'll automatically skip that dialog and go straight to the "Open with" box.


[ Source ]

Windows 7: Disable search indexing

The "Windows Search Indexing" service once in XP was renamed to "Windows Search". Disabling this via "services.msc" (the Services Manager) will not break your search functionality, only the indexing.

You can also disable it via the options in:

  • Windows Explorer
  • "Tools" menu
  • "Folder Options"
  • "Search" tab
  • Select "Don't use the index when searching the file system"
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog