Posted (Updated ) in Uncategorized

I’ve been frustrated for a while now at Chromes lack of a decent Amazon S3 extension. Firefox has S3Fox but the closest Chrome users come is S3 which only lets you browse and not modify the files in your buckets. Well that’s just changed!

Over the weekend I finally gathered up enough free time to add support for creation and deletion of files/buckets. While I was in there I made a few other modifications to improve performance and clean things up a bit.

Download the latest version (and the source: Github repo)

Adding a bucket
Adding a bucket
Deleting a bucket
Delete link when hovering over buckets
Adding files
Multi-select file browser for uploading files
Uploading Files
The uploading window
File delete
The confirmation you see when deleting files
Deleting a bucket with files in it
Error you see when attempting to delete a bucket with files in it

Read More »

Posted (Updated ) in Database

Earlier today I completed my first project in Django and it came time to do some database optimization. I wanted to get a list of SQL queries executed for each page and a bit of Googling let me to this script on DjangoSnippets. It did everything I needed it to do, however I noticed it interfered with dynamically generated binary file outputs (such as the images made with django-simple-captcha). For this I needed to check if the output was in binary, and if so just return it without attempting to print the SQL log. I found what I was looking for here and after combining the two had the perfect SQL logger! Below is my finished code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from django.db import connection
from django.template import Template, Context
import string 
#http://djangosnippets.org/snippets/161/class SQLLogMiddleware:
    def process_response ( self, request, response ):
        #Don't print SQL queries for binary outputs!        if istext(response.content) == 0:            return response 
        time = 0.0
        for q in connection.queries:
            time += float(q['time'])
 
        t = Template('''
            <p><em>Total query count:</em> {{ count }}<br/>
            <em>Total execution time:</em> {{ time }}</p>
            <ul class="sqllog">
                {% for sql in sqllog %}
                    <li>{{ sql.time }}: {{ sql.sql }}</li>
                {% endfor %}
            </ul>
        ''')
 
        response.content = "%s%s" % ( response.content, t.render(Context({'sqllog':connection.queries,'count':len(connection.queries),'time':time})))
        return response
 
#http://code.activestate.com/recipes/173220-test-if-a-file-or-string-is-text-or-binary/def istext(s):
    if "\0" in s:
        return 0
 
    if not s:  # Empty files are considered text
        return 1
 
    # Get the non-text characters (maps a character to itself then
    # use the 'remove' option to get rid of the text characters.)
    t = s.translate(string.maketrans("", ""), "".join(map(chr, range(32, 127)) + list("\n\r\t\b"))) 
    # If more than 30% non-text characters, then
    # this is considered a binary file
    if float(len(t))/len(s) >= 0.30:        return 0

To get this working on your site just add it to your MIDDLEWARE_CLASSES in settings.py and make DEBUG is set to True.

Read More »

Posted (Updated ) in PHP

While aimlessly browsing my Twitter feed last night, I came across this tutorial on using CodeIgniter‘s Zip class. Kohana 3.1 doesn’t seem to come with similar functionality out of the box (at least from the brief glance I took), so I figured I’d write up a quick patch to get CI’s class working with it.

Download the module with example controller and test files here.

You can read up on how to use the class in CodeIgniter’s documentation or the tutorial linked to above. I’ve included a controller and 2 test files in the download above as a kind of ‘quick start guide’. To access them simply go to /koziptest and /koziptest/invalid for a successful and unsuccessful download respectively.

There isn’t really any more to say about this one other than the fact that I made the methods in my module chainable for convenience and consistency with other Kohana classes. Note that this means the read_file, read_dir and archive methods will now throw exceptions if you use an invalid file/directory path or your input or output files aren’t readable/writable – so remember to use a try..catch block! I’ve also made the download method take a Request variable as its first argument – simply pass your controllers current request to it like so:

$Zip->download( $this->response )

Read More »

Posted (Updated ) in Uncategorized

If you’re paginating your data and have tens or hundreds of pages, chances are you’d prefer only a subset of these be displayed in your page number list (example – see page list at bottom). Django-paginator gets 90% of your work done for you however it doesn’t support this one very useful feature. To make a developers life easier, meet flynsarmy_paginator!

flynsarmy_pagination
flynsarmy_pagination in action

 

Download it here.

This app is a simple subclass of django’s built in Paginator and Page classes. The only changes I’ve made are to add an optional adjacent_pages parameter to FlynsarmyPaginator and a .page_range_data variable to the FlynsarmyPage object with the following contents:

  • page_range – same as Paginator.page_range – a list of page numbers but only showing a subset of pages if adjacent_pages was specified in the FlynsarmyPaginator constructor.
  • show_first – Boolean value set to True if ‘1’ isn’t present in the page_range list above.
  • show_last – Boolean vlaue set to True if the last page isn’t present in the page_range list above.

Read More »

Posted (Updated ) in Linux

Update 2011-11-20: Now working with Ubuntu 11.10+

I’ve always been pretty jealous of my Windows 7-using friends with their fancy rotating backgrounds so I thought I’d do a bit of research into adding similar functionality into Ubuntu. After a little investigation I found that sure enough, Ubuntu supported background lists through the use of XML files. The only problem now was: How do I automatically generate the XML file and set the active background to it?

Behold! My automatic rotating background generator! Below is the code, or you can download it here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/bin/bash
 
#
# Author: Flynsarmy
# Contributor: Ariel Barabas (ariel.baras atGmail)
#
 
#interval in seconds
INTERVAL=1800
OUTFILE=backgrounds.xml
DIR=$(pwd)
 
if [ $1 ]; then
	if [ $1 == "--help" ]; then
		echo "	Creates the background configuration xml file with 30min of delay between pictures with the images found in the same directory, you can modify that delay entering other number
Example:
	./createSlideShow.sh 15		makes the delay of 15 minutes"
		exit
	else
		INTERVAL=$(expr $1 \* 60)
	fi
fi
 
echo "<background>
  <starttime>
    <year>2009</year>
    <month>08</month>
    <day>04</day>
    <hour>00</hour>
    <minute>00</minute>
    <second>00</second>
  </starttime>
" > $OUTFILE
 
while read -r IMG;
do
	if [ "$FIRST_IMG" ]; then
		echo "<transition>
	<duration>5.0</duration>
	<from>$DIR/$LAST_IMG</from>
	<to>$DIR/$IMG</to>
</transition>" >> $OUTFILE
	else
		FIRST_IMG="$IMG"
	fi
 
	echo "<static>
	<duration>$INTERVAL</duration>
	<file>$DIR/$IMG</file>
</static>
 
" >> $OUTFILE
done < <(find -name "*.jpg" -o -name "*.png" -o -name "*.gif" | shuf)
 
echo "<transition>
	<duration>5.0</duration>
	<from>$DIR/$LAST_IMG</from>
	<to>$DIR/$FIRST_IMG</to>
</transition>
 
</background>" >> $OUTFILE
 
if hash gsettings &>/dev/null; then
	gsettings set org.gnome.desktop.background picture-uri "file://$DIR/$OUTFILE"
else
	gconftool-2 -t string --set /desktop/gnome/background/picture_filename "$DIR/$OUTFILE"
fi

Remember to chmod +x ./createSlideshow.sh to add execute permissions then ./createSlideshow.sh to run it.

Unlike the original script (written by Ariel Barabas), this version will search recursively from its location for jpg, png and gif files and will work with files/folders containing spaces in their names. It also shuffles the files in the slideshow so if you need to regenerate the background list you won’t get the same list every time.

It defaults to rotating every 3 minutes but you can change this by using ./createSlideshow.sh <minutes>.

Have fun with it!

Read More »

Posted (Updated ) in PHP

Update 06 June 2011: I’ve contacted the current developer and he’s accepted the patch. It should be appearing in a WP-Syntax near you shortly!
Update 16 July 2011: I’ve merged Chimo’s excellent patch which adds page range support. See the updated tutorial below for usage instructions. Thanks Chimo!
Update 27 July 2011: We have liftoff! This patch is finally part of the official plugin!

I’ve used a few different WordPress syntax highlighters in my day but WP-Syntax is easily the best of them. One issue that’s bothered me with WP-Syntax for a while now, however, is lack of line highlighting support so I decided to look into adding it myself. At the time of writing I’m using WP-Syntax 0.9.9.

To add highlighting support, open up /wp-content/plugins/wp-syntax/wp-syntax.php. You’ll need to modify two functions – wp_syntax_highlight and wp_syntax_before_filter. Here’s wp_syntax_highlight:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function wp_syntax_highlight($match)
{
    global $wp_syntax_matches;
 
    $i = intval($match[1]);
    $match = $wp_syntax_matches[$i];
 
    $language = strtolower(trim($match[1]));
    $line = trim($match[2]);
    $escaped = trim($match[3]);
 
    $code = wp_syntax_code_trim($match[5]);    if ($escaped == "true") $code = htmlspecialchars_decode($code);
 
    $geshi = new GeSHi($code, $language);
    $geshi->enable_keyword_links(false);
    do_action_ref_array('wp_syntax_init_geshi', array(&$geshi));
 
    //START LINE HIGHLIGHT SUPPORT    $highlight = array();    if ( !empty($match[4]) )    {        $highlight = strpos($match[4],',') == false ? array($match[4]) : explode(',', $match[4]); 	$h_lines = array();	for( $i=0; $i<sizeof($highlight); $i++ )	{		$h_range = explode('-', $highlight[$i]); 		if( sizeof($h_range) == 2 )			$h_lines = array_merge( $h_lines, range($h_range[0], $h_range[1]) );		else			array_push($h_lines, $highlight[$i]);	}         $geshi->highlight_lines_extra( $h_lines );    }    //END LINE HIGHLIGHT SUPPORT 
    $output = "\n<div class=\"wp_syntax\">";
 
    if ($line)
    {
        $output .= "<table><tr><td class=\"line_numbers\">";
        $output .= wp_syntax_line_numbers($code, $line);
        $output .= "</td><td class=\"code\">";
        $output .= $geshi->parse_code();
        $output .= "</td></tr></table>";
    }
    else
    {
        $output .= "<div class=\"code\">";
        $output .= $geshi->parse_code();
        $output .= "</div>";
    }
    return
 
    $output .= "</div>\n";
 
    return $output;
}

and here’s wp_syntax_before_filter:

1
2
3
4
5
6
7
8
function wp_syntax_before_filter($content)
{
    return preg_replace_callback(
        "/\s*<pre(?:lang=[\"']([\w-]+)[\"']|line=[\"'](\d*)[\"']|escaped=[\"'](true|false)?[\"']|highlight=[\"']((?:\d+[,-])*\d+)[\"']|\s)+>(.*)<\/pre>\s*/siU",        "wp_syntax_substitute",
        $content
    );
}

Updated/added lines are, of course, highlighted 🙂

Below is an example of the new functionality:

<pre lang=”php” highlight=”2″>
$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;
</pre>

$foo = 'foo';
    $bar = 'bar';    $foobar = 'foobar';

<pre lang=”php” highlight=”1,2,5-7″>
$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;

$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;

$foo = ‘foo’;
$bar = ‘bar’;
$foobar = ‘foobar’;
</pre>

$foo = 'foo';    $bar = 'bar';    $foobar = 'foobar';
 
    $foo = 'foo';    $bar = 'bar';    $foobar = 'foobar'; 
    $foo = 'foo';
    $bar = 'bar';
    $foobar = 'foobar';

Remember to add highlight to the list of allowed <PRE> tag arguments in your themes functions.php file. Details on doing so can be found here.

Read More »

Posted (Updated ) in Javascript

I discovered recently a little quirk with accessing a JQuery UI Dialog‘s options and methods from within the dialog itself. I was AJAXing the dialog’s contents and was having difficulty figuring out how to access the dialog’s methods. As it turns out, from the contents of the dialog you don’t use

$(this).closest('.ui-dialog').option()

which returns a javascript object, but instead use

$(this).closest('.ui-dialog-content').option()

Seeing as this post would otherwise be pretty short, let’s do a little more than simply retrieving options. Below I’ll explain not only to open a AJAX dialog from a HTML link, but also tell the dialog what element opened it. This could be useful in such instances as when you need to click a link which opens a dialog allowing you to upload a user avatar, and upon uploading, replaces the link with the avatar image.

For the lazy, you can download the complete tutorial files here.

Read More »

Posted (Updated ) in Linux

Upon downgrading back to Ubuntu 10.10 after my horrendously bad experience with 11.04, I’ve been reunited with a bug I’d previously put up with for 6 months: The trackpad on my laptop often ‘mouseups’ when dragging, resulting in windows not being dragged correctly. In addition, web browser and pidgin tabs will occasionally close on click instead of giving focus to that tab. Well here’s the fix!

Make sure the following 2 lines are In the InputClass section of /etc/X11/xorg.conf.d/50-synaptics.conf:

Option "ClickFinger3" "1"
        Option "EmulateTwoFingerMinZ" "280"

Here’s what mine looks like:

Section "InputClass"
        Identifier "touchpad catchall"
        Driver "synaptics"
        MatchIsTouchpad "on"
        MatchDevicePath "/dev/input/event*"
        Option "ClickFinger3" "1"
        Option "EmulateTwoFingerMinZ" "280"
EndSection

You’ll probably need to do a reboot for the changes to take effect.

Thanks to users egermani and ejmarkow for their respective fixes here and here.

Read More »

Posted (Updated ) in Database, Linux

Update 2011-10-12: More storage options! Google Storage, Local HDD, FTP, experimental unlimited Google Docs conversion

Have you ever wanted to ensure that even if your server dies in the most spectacular of ways, your DB is safe? Meet Cloud Database Backup. Cloud Database Backup is a little script I’ve written that allows you to quickly and easily back up your MySQL DBs to the cloud.

Currently you can back your database up to:

  • Amazon S3
  • FTP
  • Google Docs
  • Google Storage
  • Local HDD

Download the script here.

Requirements:

  • MySQL with access to INFORMATION_SCHEMA database
  • php, php5-cli (for S3 backups)
  • python2, python-gdata (for Google Docs backups)

This is an updated version of my old Automatic MySQL Database Backup script that adds support for Google Docs (which now allows uploads of any file type for non-enterprise users), the recently opened Google Storage, as well as local HDD and FTP servers. It does a MySQL dump of each DB separately, zips them all and uploads the zip to your cloud service of choice.

I’ve also added in an experimental ‘db chunker’ which uses this script to split SQL dumps into convertible sizes for Google Docs, allowing you to upload unlimited backups for free; owever due to a reproducible bug in Google Docs, I wouldn’t recommend its use (and it’s disabled by default).

To get started simply update your details in the appropriate places at the top of backup.sh and type ./backup.sh. Presto!

I’ve also included a crontab example to allow automation of backups.

Read More »

Posted (Updated ) in Uncategorized

A while back Samsung released a line of relatively cheap “EcoGreen” 2TB hard drives. Being the storage hungry IT nerd that I am, I picked up 2 of the things before finding out their firmware contains a known data write bug requiring a firmware patch best summed up with the following:

“It [the drive] will “forget” to write out its buffer if certan SMART commands are sent to the drive. This is the very definition of silent data corruption.”
source

Samsung has released a patch but it requires booting into DOS which is incredibly difficult to do on todays floppyless PCs. After a bit of googling I came across the following two solutions to get the job done:

Bootable ISO image

This is the easier solution of the two but it is also the one that didn’t work for me. Michael has created a FreeDOS image with the patch merged in. For the download and installation details, see this post.

Bootable USB image

After trying and failing the above, I settled for a bootable USB image instead. User ZDOS has written up a handy tutorial here which I’ve detailed a bit more in depth below:

  • Download the Windows 98 system files (at the top) and HP USB Disk Storage Format Tool from here and F4EG.exe from here.
  • Install the HP Format Tool and run it with administrator privileges (right click – Run as Administrator).
  • Extract the Windows 98 system files.
  • With the HP Format Tool, format your USB drive (quick format should be enough) as Fat32 making sure you use the Windows 98 system files where it offers.
  • Once done, copy F4EG.exe to your USB drive.
  • Shutdown and unplug all HDDs besides your unpatched Samsung drive
  • Boot your PC and enter the BIOS by pressing Delete during startup. Ensure that your HDDs are set to run in AHCI mode.
  • Reboot either ensuring USB-HDD is selected as your top boot device or press F12 during startup to visit the One Time Boot Device page (results may vary – check your motherboard documentation).
  • You should see a Windows 98 logo flash on the screen for a split second and then a command prompt. In the prompt type F4EG and press enter. Your drive should flash itself.

For plenty more useful information on this issue, I found this forum thread very helpful.

Read More »

Page 10 of 16« First...89101112...Last »