Linux homedir dotfiles
Most first-time Linux users come from a world where every program has a settings dialog in which to configure the program; indeed some have never opened those dialogs at all. In Linux, however, many applications still use configuration files located in your home directory. These are often prefixed with a period (.bashrc, .xinit, etc), and referred to as dotfiles for this reason. The reason behind the dot-prefix is that in Linux, files with filenames starting with a period are hidden in most listings by default. Since you don’t want to see all your config files every time you try to find something in your home directory, it makes sense to make them hidden. (If you don’t believe me, open a command prompt and run “ls -la” to see all the dotfiles as well)
So, let’s have a the dotfiles you will most likely want to change. Note that these are primarily for command-line applications, but since you’re using Linux, you will more than likely come in contact with the command line sooner or later.
.bashrc
This file contains all the configuration options for your shell (the application that handles everything that happens in your terminal window).
Below is my current .bashrc file:
# Check for an interactive session [ -z "$PS1" ] && return # Color aliases alias ls='ls --color=auto' alias grep='grep --color=auto' # Common aliases alias more='less' # Convenience aliases alias svim='sudo vim' alias srm='sudo rm' # Prompt PS1='[\u@\h \W]\$ ' # Tab completion for sudo # Disabled because it also autocompletes filenames... #complete -cf sudo # Sets the editor to use export EDITOR='vim' # Add local bins to path export PATH="$PATH:/usr/local/bin" # Other aliases # make alias ,='make' # git alias .='git pull' alias ..='git push' # file handlers alias o='xdg-open' # update commands alias yu='yaourt -Syu --aur' alias pu='sudo powerpill -Syu' alias yi='yaourt -S' # online tools alias t='tweet'
Note that you should change this to suit your preferences. If you don’t use git, then remove the git aliases or change them to something else you find useful!
.xinitrc
The .xinitrc file is a small, but important, file which controls what happens when you log in and start your X session (The “startx” command). If you’re running a graphical login manager such as GDM, KDM or SLiM, then these will execute startx for you, thus still invoking .xinitrc.
Since I’m running XFCE, my .xinitrc contains “exec startxfce4″.
The “ssh-agent” part runs the entire window manager under a single SSH agent daemon, allowing me to only enter the password for my private keys once in a single session.
exec ssh-agent startxfce4
.Xresources
The .Xresources file configures the visual aspects of all X applications (most notably xterm and xscreensaver).
Note that a lot of these settings will not change anything if you are using another terminal editor such as gnome-terminal or Konsole.
In my .Xresources file below (which is heavily inspired by the Arch Linux Wiki page on the subject), I define a “better” color theme, terminal settings such as font and how my xscreensaver should look. Feel free to experiment these and come up with the perfect settings for your tastes!
One important thing to note is that I am setting xterm to use the Inconsolata font – a very good monospaced terminal font. It is probably available for your Linux distro through the packaging system (Look for ttf-inconsolata)
! terminal colors ------------------------------------------------------------ ! tangoesque scheme *background: #111111 *foreground: #babdb6 ! Black (not tango) + DarkGrey *color0: #000000 *color8: #555753 ! DarkRed + Red *color1: #ff6565 *color9: #ff8d8d ! DarkGreen + Green *color2: #93d44f *color10: #c8e7a8 ! DarkYellow + Yellow *color3: #eab93d *color11: #ffc123 ! DarkBlue + Blue *color4: #204a87 *color12: #3465a4 ! DarkMangenta + Mangenta *color5: #ce5c00 *color13: #f57900 !DarkCyan + Cyan (both not tango) *color6: #89b6e2 *color14: #46a4ff ! LightGrey + White *color7: #cccccc *color15: #ffffff ! xterm ---------------------------------------------------------------------- xterm*geometry: 100x25 xterm*faceName: inconsolata:pixelsize=15 !xterm*font: -*-dina-medium-r-*-*-16-*-*-*-*-*-*-* xterm*dynamicColors: true xterm*utf8: 1 xterm*eightBitInput: true xterm*saveLines: 512 xterm*scrollTtyKeypress: true xterm*scrollTtyOutput: false xterm*jumpScroll: true xterm*multiScroll: true xterm*toolBar: false ! xscreensaver --------------------------------------------------------------- !font settings xscreensaver.Dialog.headingFont: -*-dina-bold-r-*-*-12-*-*-*-*-*-*-* xscreensaver.Dialog.bodyFont: -*-dina-medium-r-*-*-12-*-*-*-*-*-*-* xscreensaver.Dialog.labelFont: -*-dina-medium-r-*-*-12-*-*-*-*-*-*-* xscreensaver.Dialog.unameFont: -*-dina-medium-r-*-*-12-*-*-*-*-*-*-* xscreensaver.Dialog.buttonFont: -*-dina-bold-r-*-*-12-*-*-*-*-*-*-* xscreensaver.Dialog.dateFont: -*-dina-medium-r-*-*-12-*-*-*-*-*-*-* xscreensaver.passwd.passwdFont: -*-dina-bold-r-*-*-12-*-*-*-*-*-*-* !general dialog box (affects main hostname, username, password text) xscreensaver.Dialog.foreground: #ffffff xscreensaver.Dialog.background: #111111 xscreensaver.Dialog.topShadowColor: #111111 xscreensaver.Dialog.bottomShadowColor: #111111 xscreensaver.Dialog.Button.foreground: #666666 xscreensaver.Dialog.Button.background: #ffffff !username/password input box and date text colour xscreensaver.Dialog.text.foreground: #666666 xscreensaver.Dialog.text.background: #ffffff xscreensaver.Dialog.internalBorderWidth:24 xscreensaver.Dialog.borderWidth: 20 xscreensaver.Dialog.shadowThickness: 2 !timeout bar (background is actually determined by Dialog.text.background) xscreensaver.passwd.thermometer.foreground: #ff0000 xscreensaver.passwd.thermometer.background: #000000 xscreensaver.passwd.thermometer.width: 8 !datestamp format--see the strftime(3) manual page for details xscreensaver.dateFormat: %I:%M%P %a %b %d, %Y
.vimrc
If you want to do any kind of advanced text editing (programming, etc), you’ll want a proper editor. And vim is definitely a suitable option when configured properly.
My .vimrc below is largely inspired by Steve Losh’s “Coming Home to Vim“, though it does contain some of my own preferences as well.
With regards to Vim, there are a couple of plugins I recommend you download. The script below only contains a couple of them: ZenCoding and CloseTag, but have a read of the above article and find your own combination.
" Get indentation
set autoindent
set guioptions-=T " Remove toolbar
set vb t_vb= " No more beeps
set backspace=2 " Backspace over newlines
" GUI fixes
set ruler " Where am I?
set ttyfast
set laststatus=2
" Relative line numbers
set relativenumber
" Permanent undo
set undofile
" Autocomplete
set wildmenu
set wildmode=list:longest
" Fix tabs
set shiftwidth=4
set softtabstop=4
set tabstop=4
set expandtab
" Get syntax
syntax on
" Style vim
colors clouds
" Keymaps
let mapleader = ","
nnoremap <tab> %
vnoremap <tab> %
inoremap <F1> <ESC>
vnoremap <F1> <ESC>
vnoremap <F1> <ESC>
inoremap jj <ESC>
" Good-bye arrow keys... =(
nnoremap <up> <nop>
nnoremap <down> <nop>
nnoremap <left> <nop>
nnoremap <right> <nop>
inoremap <up> <nop>
inoremap <down> <nop>
inoremap <left> <nop>
inoremap <right> <nop>
nnoremap j gj
nnoremap k gk
" Proper search
nnoremap / /\v
vnoremap / /\v
set ignorecase
set smartcase
set gdefault
" Script plugins
au Filetype html,xml,xsl,php source ~/.vim/scripts/closetag.vim
au Filetype html,xml,css,php source ~/.vim/scripts/zencoding.vim
" Filetype indenting
filetype indent on
" Load indentation rules and plugins
" according to the detected filetype.
if has("autocmd")
filetype plugin indent on
endif
" Settings
set nocompatible
set modelines=0
set encoding=utf-8
set scrolloff=3
set showmode
set showcmd
set hidden
set showcmd " Show (partial) command in status line.
set mouse=a " Enable mouse usage (all modes) in terminals
Developing applications for Android – gotchas and quirks
Over the past couple of days, I have developed my first two applications for the Android Market; Tuples and PencilWise. The first is a simple tool for storing key-value pairs, or tuples, of information you need to remember such as your bank account numbers, your PGP fingerprints, etc.. The second is a mobile version of the puzzle page by the same name.
As this was my first attempt at an Android application, I encountered quite a lot of first-time gotchas and quirks with the Android development platform, and I figured I’d share them here so others can resolve them quicker than I did. I’ll also give some hints for how to accomplish common task,s such as strike-through text, that might not be as obvious as they should be.
All of this is based on Android 2.1, but I assume most of them apply to any 2.0+ API.
Quirks and Gotchas
View reuse
Since Android mostly runs on devices that lack in the area of processing power, several optimizations have been implemented in the core of the OS. Unfortunately, these can have some strange side-effects.
One of these optimizations is that Android reuses views (the common base class for all elements drawn on screen) once the given element is no longer in view on the screen. This means that any pointers you might have to a view, will actually point to whatever Android has reused the view as, not the element you originally thought it was.
An example of this annoyance can be observed in the following code:
public class PencilWise extends ListActivity {
View activeElement;
// ...
@Override
public void onCreate ( Bundle savedInstanceState ) {
// ...
this.getListView( ).setOnItemClickListener ( new OnItemClickListener ( ) {
public void onItemClick ( AdapterView<?> parent, View view, int position, long id ) {
MyActivity.this.activeElement = view;
MyActivity.this.showDialog ( DIALOG_ANSWER );
}
} );
}
}
The showDialog method will display the answer dialog, which needs to know what question the user has opened. The problem is that by the time the dialog opens, the view passed to onItemClick might have been reused, and so activeElement would no longer point to the element the user clicked to open the dialog in the first place!
To achieve the desired effect, you need to store the position or the ID instead, and use something like: “this.getListAdapter ( ).getItem ( this.activeElement )”, which will return the cursor used to fetch the element behind the selected item.
View reuse and formatting
A bi-product of the view reuse of Android is that formatting options on the view are actually kept when a View is reused. So, if you for instance set that a TextView should be painted with a strike-through (see further down), ever time Android reuses that view, the new view will also be striked even though you never explicitly made it so..
For instance, say you used a ListAdapter for a ListView as such:
the getView method here is used to dynamically manipulate elements drawn in the List whenever they are accessed from the adapter. This can be used to, as shown in the example below, only strike through elements that hold true for a given condition
this.setListAdapter ( new ArrayAdapter<String> ( this, android.R.layout.simple_list_item_1, new String[] { "Hello", "World" } ) {
@Override
public View getView ( int position, View convertView, ViewGroup parent ) {
TextView v = (TextView) super.getView ( position, convertView, parent );
if ( MyActivity.this.answered.getBoolean ( v.getText ( ).toString ( ), false ) )
v.setPaintFlags ( v.getPaintFlags ( ) | Paint.STRIKE_THRU_TEXT_FLAG );
return v;
}
} );
This code would seemingly be working, but once you start getting lots of elements, and the user starts to scroll, you will see that apparently random elements get striked. This is because of view reuse.
The solution is to undo the paint flag if the condition is not true, like this:
this.setListAdapter ( new ArrayAdapter<String> ( this, android.R.layout.simple_list_item_1, new String[] { "Hello", "World" } ) {
@Override
public View getView ( int position, View convertView, ViewGroup parent ) {
TextView v = (TextView) super.getView ( position, convertView, parent );
if ( MyActivity.this.answered.getBoolean ( v.getText ( ).toString ( ), false ) )
v.setPaintFlags ( v.getPaintFlags ( ) | Paint.STRIKE_THRU_TEXT_FLAG );
else
v.setPaintFlags ( v.getPaintFlags ( ) & ~Paint.STRIKE_THRU_TEXT_FLAG );
return v;
}
} );
Now, each view will be drawn correctly.
Dialog reuse
Android also reuses dialog boxes, which means that if you, for instance, have an input field in the dialog that the user types something in, closes the dialog, and opens another dialog with the same ID, the text will remain in the field. This can be very annoying if the value in the input field should depend on another action the user has performed (such as what element was clicked to open the dialog).
The obvious fix would be to reset the content of the text area whenever a dialog is created, which you would think would be done in the method “onCreateDialog” using something like this:
@Override
protected Dialog onCreateDialog ( int id ) {
// ...
( (EditText) dialog.findViewById ( R.id.text1 ) ).setText ( "" );
// ...
}
Turns out, however, that this won’t work, since onCreateDialog is only run once per dialog ID. The proper way is to also override “onPrepareDialog”, and do any dynamic changes to the dialog there. So, onCreateDialog is for setup/format, and onPrepareDialog is for manipulating content.
Dynamic dialog titles/messages
After reading the above gotcha, you might also be tempted to put the setTitle and setMessage calls on the AlertDialog in onPrepareDialog since they might change between invocations of the dialog. The problem is that Android will not display the title or the message if they have not been set in the dialog returned from onCreateDialog. So, to use setTitle in onPrepareDialog, you have to make sure that you run setTitle in onCreateDialog with some placeholder text as well, otherwise your title/message calls in onPrepareDialog will not have any effect!
Dealing with SQLite
SQLite is not as easy as it could be in Android, but the SQLiteOpenHelper class does help quite a bit.
In order to utilize SQLite in your application, you need a class representing each database you want to use that extends the class SQLiteOpenHelper. Each such class needs to define three methods:
- The constructor
- onUpgrade
- onCreate
The constructor will theoretically only contain line:
super ( context, DATABASE_NAME, null, DATABASE_VERSION );
where DATABASE_NAME and DATABASE_VERSION are values defined by you to represent the current database. DATABASE_NAME can be any string, and DATABASE_VERSION should be an int that you will increment if you do any structural changes to your database.
This brings us to onUpgrade. This method is called if the database version number is different between the last time the app was run and this time (i.e. the user has updated your app in the market and the new version has a different DB schema). Here, you should provide update paths from every version of your database schema to the next such as adding/dropping tables and columns.
Finally, we have onCreate, which is called the first time the database is accessed. Here, you also usually only need a single statement per table you are creating: “db.execSQL ( TABLE_CREATE );” where db is the SQLiteDatabase object the method is passed and TABLE_CREATE is the SQL statement used to create the given table.
When accessing your database later, you need to call the method getReadableDatabase() or getWritableDatabase() on your helper class instance object to actually execute query(), delete(), insert() and update() statements.
SQLite and CursorAdapters – Where the fun starts
There is one little quirk that is not very well advertised in the SDK documentation for Android, and that is the fact that all Cursor objects used as source for list adapters MUST have an ID column. And not just any ID column, but one with the name set in BaseColumns._ID and a type of “INTEGER PRIMARY KEY AUTOINCREMENT”. So, if you intend to use any table in SimpleCursorAdapter or CursorAdapter, make sure your CREATE_TABLE statement includes the column
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT"
Handling screen orientation changes
Android has another quirk that caused me quite a bit of headache when a bug was reported a couple of days ago:
If a dialog box was open, and the user changed the orientation of the screen, the dialog box would no longer contain the data from before the screen flip.
Turns out, whenever the screen orientation is changed, Android actually relaunches the current activity, thereby resetting all instance variables of that class! Thus, if I render the contents of the dialog based on what element in a list a user clicked (which is quite common), and the id of the element the user clicked is stored in this.activeElement; when the user changes orientation, that variable is reset to 0, and the code in onPrepareDialog does not know what element was originally pressed any more. This leads to it not changing the content, and only the structure from onCreateDialog is actually used (i.e. the title is only set to ‘__’).
After digging a bit around, I came upon this blog post dealing with the problem.
The solution is to use what Android refers to as an Application. This is kind of like a global registry for all of your application that will remain unchanged as long as your program runs. Thus, we can store any instance variables there, and access instance variables like this:
First, we create a new file holding the application class:
public class MyApplication extends Application {
public int activeElement = -1;
}
Next, we define in our application manifest (AndroidManifest.xml) what our application class is
<application [...] android:name="MyApplication">
And now, we can access variables from our activities using:
( (MyApplication) this.getApplication ( ) ).activeElement;
It might be good to define a getter and setter in your activity for ease of use:
private int getActiveElement ( ) {
return ( (MyApplication) this.getApplication ( ) ).activeElement;
}
private void setActiveElement ( int element ) {
( (MyApplication) this.getApplication ( ) ).activeElement = element;
}
How-tos
Strike-through text
Given a TextView view v, use:
v.setPaintFlags ( v.getPaintFlags ( ) | Paint.STRIKE_THRU_TEXT_FLAG );
To undo the strike-through, we use some bitwise magic:
v.setPaintFlags ( v.getPaintFlags ( ) & ~Paint.STRIKE_THRU_TEXT_FLAG );
Redraw all elements in a ListView
If you use an ArrayAdapter a, you can call
a.notifyDataSetChanged();
If you use an ArrayAdapter in a ListActivity:
( (ArrayAdapter) this.getListAdapter ( ) ).notifyDataSetChanged ( );
If you have a ListView ‘lv’ that uses an adapter that implements CursorAdapter, use:
((CursorAdapter) lv.getListAdapter()).getCursor().requery();
More flexible string handling through resources
Say you want to output the string “Hint: ” followed by some dynamically fetched hint. Your first thought might be to hard code ‘”Hint: ” + this.getHint()’, but it should be apparent that this is not the right way to do it. Android provides the strings.xml file for exactly this purpose. So, we define a string by the name of “hint_text” in strings.xml with the content “Hint: “. How do we access this string from our code?
Well, from any activity you can do this by simply calling “this.getString” which takes the ID of the string resource. In our case this would be
this.getString ( R.string.hint_text )
With our code looking like this (to put this in a toast):
Toast.makeText ( this, this.getString ( R.string.hint ) + this.getHint ( ), Toast.LENGTH_SHORT ).show ( );
You then happily compile and run the code, just to see that your text gets printed out as “Hint:Some hint” without the space you put in. The reason for this is that XML trims spaces inside elements, and as such, your space is lost. There are two wrong ways of fixing this, and one right one. The wrong ones are:
- Use the XML entity for a space:
- Hard code the space in your string concatenation in Java
If you want to do it properly, you define your string like this: ‘<string name=”hint_text”>Hint: %s</string>’. For those of you familiar with the printf family of functions, this should look familiar. What we are doing here is to tell Android that our string will contain dynamic content (here a string, represented by %s). We can then give the data that should be inserted into the text as additional parameters to the getString method like this:
Toast.makeText ( this, this.getString ( R.string.hint, this.getHint ( ) ), Toast.LENGTH_SHORT ).show ( );
Windows 7 login screen only showing last logged-on user and “Other user”
Ever since my initial install of Windows 7, there has been one thing nagging me. The Windows welcome screen only ever displayed the avatar for the last logged on user and a blank image with the label “Other users”. When the latter was clicked, two text fields would appear prompting for username and password.
I have tried numerous solutions, but none have worked until very recently when a user with the nickname “SaySay” came up with the following solution:
Legal disclaimer: Modifying REGISTRY settings incorrectly can cause serious problems that may prevent your computer from booting properly. Neither I nor Microsoft can guarantee that any problems resulting from the configuring of REGISTRY settings can be solved. Modifications of these settings are at your own risk
- Open regedit
- Press Windows+R
- Type regedit + enter
- Navigate to [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList]
- You will probably want to right-click on “ProfileList” and click export to save the entire subtree in case something goes wrong.
- You will find several subfolders or “keys” named something like “S-1-x-xx…”, open them one at the time
- Each should contain at least the three value-sets, “Flags”, “ProfileImagePath” and “State”, some will contain more
- Look at the end of ProfileImagePath for the name of the user represented by the key
- You will usually have one for each user on the system, and one for each of the three system entries ‘systemprofile’, ‘LocalService’ and ’NetworkService’
- Delete any key (i.e. the whole “S-1-x-xx” folder) that does not contain at least those three values
- The welcome screen should now work as expected, showing the avatar for all registered users; enjoy!
RSS feed for AlertBox
For those of you concerned with web usability, there are few better sources than Jakob Nielsen’s AlertBox.
Although his site is quite infrequently updated, it contains very informative posts. Unfortunately and ironically, the site does not have a RSS feed.
After an especially boring afternoon, I decided to see if I couldn’t do something about that, so with the use of this PHP Feed Generator class and some HTML parsing, I came up with the following script to generate an RSS feed from the AlertBox website:
Just download the FeedGenerator FeedWriter class from the given link, put the following code and FeedWriter.php in the same directory, upload it to a webserver with PHP support, and voilla, you have an AlertBox RSS feed.
Enjoy!
<?php
date_default_timezone_set("UTC");
class FetchAlertbox {
private $contents = array();
private function fetch() {
$page = file_get_contents("http://www.useit.com/alertbox/index.html");
$startList = stripos ( $page, '<ul>' );
$page = substr ( $page, $startList, stripos ( $page, '</ul>', $startList ) - $startList + strlen ( '</ul>' ) );
$page = str_ireplace ( '<p>', '', $page );
$page = preg_replace ( "/<li>(.*)/i", '<li>$1</li>', $page );
$page = preg_replace ( "@</?strong>@i", "", $page );
$p = @DOMDocument::loadHTML($page);
foreach ( $p->getElementsByTagName("li") as $article ) {
$url = '';
foreach ( $article->getElementsByTagName("a") as $link ) {
if ( preg_match ( "@\w+.html@i", $link->getAttribute('href') ) ) {
$url = 'http://www.useit.com/alertbox/' . $link->getAttribute('href');
break;
}
}
if ( $url === '' ) {
continue;
}
$contents = str_replace ( "\n", " ", $article->textContent );
$contents = preg_replace ( "/\s{2,}/", " ", $contents );
$date = 0;
$possibleStartDate = strrpos ( $contents, '(' );
if ( $possibleStartDate !== false ) {
$timestring = substr ( $contents, $possibleStartDate + 1, strpos ( $contents, ')', $possibleStartDate ) - $possibleStartDate - 1 );
$parsedDate = strtotime ( $timestring );
if ( $parsedDate !== false ) {
$date = $parsedDate;
$contents = str_replace ( "($timestring)", "", $contents );
}
}
$this->contents[] = array ( 'url' => $url, 'title' => trim ( $contents ), 'date' => $date );
}
return $this->contents;
}
public function fetchWithSummaries($type = "RSS2", $limit = 10, $start = 0) {
if ( empty ( $this->contents ) ) { $this->fetch(); }
include ( "FeedWriter.php" );
$feedType = RSS2;
$feedDate = DATE_RSS;
switch ( $type ) {
case 'RSS1':
$feedType = RSS1;
break;
case 'ATOM':
$feedType = ATOM;
$feedDate = DATE_ATOM;
break;
}
$feed = new FeedWriter($feedType);
$feed->setTitle("Alertbox");
$feed->setLink("http://www.useit.com/alertbox/");
$feed->setDescription("Current Issues in Web Usability - Bi-weekly column by Dr. Jakob Nielsen, principal, Nielsen Norman Group");
if ( $type === 'ATOM' ) {
$feed->setChannelElement('updated', date($feedDate, $this->contents[0]["date"]));
} else {
$feed->setChannelElement('pubDate', date($feedDate, $this->contents[0]["date"]));
}
$feed->setChannelElement('language', 'en-us');
$feed->setChannelElement('author', array('name' => 'Dr. Jakob Nielsen'));
if ( $type === "RSS1" ) {
$feed->setChannelAboute("http://www.useit.com/alertbox/");
}
for ( $i = $start; $i < $start + $limit && $i < count ( $this->contents ); $i++ ) {
$p = @DOMDocument::loadHTML ( file_get_contents ( $this->contents[$i]["url"] ) );
$blockquotes = $p->getElementsByTagName("blockquote");
if ( $blockquotes->length > 0 ) {
$this->contents[$i]["summary"] = trim ( str_replace ( "Summary:", "", $blockquotes->item(0)->textContent ) );
} else {
$contents = $p->saveHTML();
$endHeadline = stripos ( $contents, "</h1>" );
$this->contents[$i]["summary"] = trim ( strip_tags ( substr ( $contents, $endHeadline + strlen ( "</h1>" ), stripos ( $contents, "<p>" ) - ( $endHeadline + strlen ( "</h1>" ) ) ) ) );
}
$item = $feed->createNewItem();
$item->setTitle($this->contents[$i]["title"]);
$item->setLink($this->contents[$i]["url"]);
$item->setDate($this->contents[$i]["date"]);
$item->setDescription($this->contents[$i]["summary"]);
$feed->addItem($item);
// echo date ( "F jS, Y", $this->contents[$i]["date"] ) . ": " . $this->contents[$i]["title"] . " -> " . $this->contents[$i]["url"] . "\n";
// echo "\t" . $this->contents[$i]["summary"] . "\n\n";
}
$feed->genarateFeed();
}
}
$s = new FetchAlertbox();
$s->fetchWithSummaries(isset($_GET['type']) ? strtoupper ( $_GET['type'] ) : 'RSS2', isset($_GET['limit']) && ctype_digit($_GET['limit']) ? $_GET['limit'] : 10);
WPA2-Enterprise wireless with netcfg
At Bond University the IT department has now finally taken the step from an open wireless network with a login proxy to a proper WPA2 Enterprise setup.
Apart from giving much higher security since data is not transmitted unencrypted through the air, this also makes it a lot easier to automatically connect to the internet. With the previous setup, a post_up netcfg hook was needed that used some specially crafted cURL code to post the login form on the proxy. Ugly as hell, and not very reliable or secure either.
The only issue is that WPA2-Enterprise has a lot of different configuration options, so it took a while to figure out the exact setup to use.
First of all I had a look at the configuration options for Windows XP here: http://www.bond.edu.au/student-resources/student-support/computing-support/for-students/wireless-access/index.htm. The advantage of looking at the XP setup guide is that it doesn’t have as much fancy auto-detection as 7 or Mac OSX, so they give some more low-level details that we can base our setup on.
In this setup I decided to use netcfg simply because it provides a flexible utility for managing multiple wireless configurations and switching between them in a simple fashion. Furthermore, it abstracts away some of the uglier command line options of wpa_supplicant into configuration options.
All netcfg configuration files live in /etc/network.d. Each file represents one network, and contains at the very least for a wireless connection an interface specification, the SSID of the network and an IP configuration line. Have a look in the /etc/network.d/examples directory for, well, examples..
For WPA2-Enterprise however, we need quite a few more parameters:
CONNECTION='wireless' INTERFACE=wlan0 SECURITY='wpa-configsection' ESSID='BondStudents' IP='dhcp' CONFIGSECTION=' ssid="BondStudents" key_mgmt=WPA-EAP eap=PEAP group=CCMP pairwise=CCMP identity="<student ID goes here>" password="<password goes here>" priority=1 ca_path="/etc/ssl/certs" phase2="auth=MSCHAPV2" '
Quite a mouthful.. In essence, this means we are using WPA enterprise with CCMP (an AES-based encryption algorithm) and MSCHAPV2 authentication with PEAP (TLS) encapsulation. As if that helped..
The most interesting line here is: ca_path=”/etc/ssl/certs”.. Why would we need to import certfiicates? Well, turns out Bond uses a SSL certificate that is not exactly mainstream called “UTN-USERFirst-Hardware”. This certificate is usually included in the certificate directory of most distros, but is not very secure as it is not a trusted signing authority. If you want to know more about this, then Google it.
Well, that should be it. You should be able to run “sudo netcfg BondStudents” if you’ve called the configuration file “BondStudents” and you’ll be online!
Random lag spikes in Windows 7
Update: It turns out the issue is even more general than I thought at first. It is in fact not just the HTC mobile sync program that causes these freezes; it is in fact any mobile syncing application. After launching the Sony Ericsson PC Suite today, I noticed that the issue returned immediately. I killed the process, and it ended again. Seems as though Windows 7 has issues dealing with mobile syncing software if the device is not connected..?
For the past couple of weeks, my graphics card had been acting up. Or so it seemed. Every 5-6 seconds, the screen would freeze for a brief moment – just long enough to notice. It was only the screen though, because music playing in the background would keep going, and any other application would proceed as though nothing had happened. This lead me to believe that my nVidia 8600 GT was to blame.
After looking around the web, I found that several people were complaining about random lag spikes with the newest nVidia drivers, and thus my suspicion was reinforced. I tried uninstalling the drivers, and installing 6 different, previous versions of the driver pack, but to no avail.
A couple of days ago I’d had enough – it is really annoying when the mouse stops moving every five seconds – and so I decided to order a brand new graphics card. After all, if the graphics card is acting up, what is more likely to fix the issue than a new graphics card?
Well, it arrived in the mail yesterday, and to my great surprise, the issue persisted. And this was an ATI card – no nVidia drivers were even installed on the system. The mystery remained.
In order to find the cause of these lags, I fired up the Task Manager and kept an eye on the CPU usage graph. It turned out that one of my CPU cores spiked at about 10% every time the screen froze. I switched to the process view, but there were no processes suddenly jumping to the top on every freeze… Odd.. There was a process called fsynsrvstarter – with the suspicious description “TODO: <description>” quite close to the top. It didn’t use any CPU, it just sat there.. And so I figured I’d Google it just in case.
At this point, I came across this forum post explaining that this process was spawned every 4 seconds by HTC Sync. This seemed as though it aligned too perfectly with my spikes, so I decided to uninstall HTC Sync and see what happened. And what do you know? The spikes were gone..
So, I now own two graphics cards (albeit one somewhat outdated) which both work well, but are brought to their knees by such a complex piece of software as a mobile phone syncing program (an inactive one at that).
I hope this post will solve your problem before you decide to buy a new card like I did.
Inline website administration
Almost all modern websites require some sort of administration, and this usually involves creating a separate administration page where articles can be added and users managed. Lately, I’ve been making quite a few new websites that will be released in the upcoming year, and all of these have been quite simple sites with a single user and where the administration consists mainly of adding simple news updates and updating page text. For these sites, a full blown administration panel is not necessary, and is also quite inconvenient as the user will have to go back and forth to see the results. So, what are the alternatives?
(Live examples are not available at the moment, but might come later)
AJAX driven, on-page administration
Here, the user (the person administering the website) is allowed to edit content on the same page as the content through a rich text area in a popup, and the text is then changed afterwards to reflect the users edits.
The simplest, and in my experience most flexible way of doing this is through named fields. Each block of text on the site gets its own unique name, and is linked to a plain text file on the server. In my small site setups, I usually use a structure like this:
/ pages/ about.inc.php projects.inc.php bio.inc.php api.php page.php index.php
The .inc.php files can either be plain text or contain PHP code. The most important thing is that they have a unique name. The files the usually look something like this (simplified for clarity – remember security and error checking!)
<?php
// page.php
function printBlock($name) {
if ( !file_exists ( 'pages/' . $name . '.inc.php' ) ) return;
echo '<div id="' . $name . '" class="editable">';
require 'pages/' . $name . '.inc.php';
echo '</div>';
}
}
// api.php
require 'page.php';
$action = $_GET['a'];
$block = $_GET['e'];
switch ( $action ) {
case 'get':
printBlock ( $block );
break;
case 'post':
file_put_contents ( 'pages/' . $name . '.inc.php', $_POST['content'] );
break;
}
// index.php
require 'page.php';
?>
<!-- HTML structure -->
<!-- Then, whenever you're printing a block or page that should be editable, call printBlock -->
<?php printBlock ( 'about' ); ?>
Next, you will have to make some sort of JavaScript hook to make all editable areas editable. I like to use a combination of CKEditor, a simplified version of lightbox and jQuery so the end result looks something like this when a user double clicks on a box with the editable class:
Upon saving, jQuery sends a AJAX request to the api.php file with the updated contents, and also changes the contents of the block on the page using the .html() method on the element with the same ID as the block name.
In-line administration
On some sites, popup boxes simply won’t cut it. In fact, they might even become a bit cumbersome when working with news articles and such where you might want a live preview of the article as you’re typing it. Earlier, one had to have a rich text editor with a “Preview” button, but now we have a much better tool available: contentEditable. This awesome attribute allows you to tell the browser to allow the user to change the contents of an element on your page at will. Consider these screenshots that illustrate adding a new news post on a page utilizing this attribute for administration:
As you can see, this is a very simple way of creating and editing posts – and immediately seeing how it would look on the page. The major drawback is that you cannot easily accept rich inline content such as images and video, or even simple text formatting. On the other hand, such features often clutter the articles anyway. On this site, I have overcome this by allowing file attachments that are placed beneath the article based on their type (images are shown in a gallery strip, videos are embedded, etc.) Text formatting is achieved through a markdown-like syntax handled by JavaScript. There is no rich text logic in the backend.
Using contentEditable is quite simple. All you have to do is use JavaScript’s setAttribute/removeAttribute functions on any element you want to be editable. Set the attribute to true when you want it turned on, and remove it when you want it off. Apart from this, everything is quite straight-forward and very similar to the previous method of popup administration. JavaScript sends the new content to the backend, which saves it and returns the HTML rendering of the content as it would be displayed when loading the front page regularly. JavaScript then swaps the editable post area with the HTML from the server and disables editing on it.
Rounding up
Both these techniques provide quite intuitive and easy-to-access administration equivalents to classical admin-panel interfaces. They are not especially complex to build either, though they provide the user with a more comfortable and usable way to manage their sites. If you have any questions regarding these techniques, don’t hesitate to use the comment field below or e-mail me at jon <you know what goes here> thesquareplanet <and you know this one as well> com.
Developing for the modern web
Web development today is a constantly struggle between three major stakeholders: the customer, the designer and the developer. The customer tries to push through his or her (often distorted and silly) mental image of the website, the designer wants to be original, creative and fancy creating lots of intricate designs with fancy visual effects, and the developer who attempts desperately to explain to both the customer and the designer why what they’re doing is a bad idea (heavy background images, crammed pages, no whitespace, confusing visual effects…). The developers aren’t all good either though – They tend to put in as many fancy tricks and solutions in the final product as they can, often resulting in exotic bugs in various browsers and usually ungraceful downgrading™. In all of this, one stakeholder is often wholly forgotten, even though it is probably the most important one; the users.
Users often don’t know the first thing about how the web works. They don’t care whether the site is optimized for Firefox, Internet Explorer, Chrome or Safari (in fact, they probably don’t even know what a browser is…) The users want a site that is visually appealing, but not distracting – informative, but not cluttered – clear, but not over-simplified – and most importantly, one that is responsive. When a user does something, they should begin to see something happening within .1 seconds (http://www.useit.com/alertbox/timeframes.html) to feel as though they aren’t being slowed down by the site itself. Furthermore, the total loading time for whatever action the user initiates should be less than a second for the user not to fall out of his or her “flow”. Way to many websites violate these simple rules, causing the site to feel unresponsive to the user, and the users are likely to jump to the next site on their list.
In this post, I hope to show you how to make your website faster – mainly through optimizing the initial page load. In order to do this, there are three steps that need to be taken: Combine, Compress and Communicate. Repeat after me: Combine, Compress and Communicate.
Combine
Many developers seem to think (albeit erroneously) that many small files are better than few large ones. This might seem intuitive since a smaller file downloads faster than a large one, and you would think they could all be gotten out of the way quicker. The truth is quite different. Due to limitations of the HTTP protocol, the browser has to initiate a new request to the server for every single file, causing quite a bit of overhead when having to download several files. Also, modern browsers limit the amount of simultaneous downloads to 6, meaning downloading all of your small files will go even slower. Add to this the sequential nature of JavaScript, and the fact that the browser stops loading the page once it hits a JavaScript piece (external or not), and doesn’t continue loading until the JavaScript file is finished downloading and has been interpreted.
Therefore, you should work to combine as many of your files as possible. Don’t jump to put all your scripts and styles inline, however (you will understand why in Communicate). Instead, you should attempt to combine all your CSS files into one, all your JavaScript into another, and all your images into a third. Ideally, you should need no more than three external files on your site. So, how do you go about doing this?
CSS and JavaScript
Combining CSS and JS files shouldn’t itself be a problem.. Open up a text editor, copy-paste all of your CSS or JS into that file, save it and upload. You should probably still keep the separated files for readability though. Of course, modern web applications are usually a bit more complicated. For instance, you might have a stylesheet that is only included on sites with ads on them or a JavaScript file that is only needed on your frontpage. In these cases, your should look into using a combinator. One of the best sites describing the techniques of combining is this one. The mod_concat plugin for Apache2 provides several advantages over traditional scripting approaches especially with regards to communication (as will be discussed later)
Images
All your images should be done as sprites. Ideally, you should even be able to put every single image on your site into a single png image. Do this, and you will substantially reduce the loading time of your site. For an introduction to CSS sprites, have a look here.
Compress
All your CSS and JS files should be compressed to reduced overall download size. Again, it is usually a good idea to keep the original, uncompressed versions of the files, and re-compress the files whenever you change them. For CSS, I recommend the YUI compiler (http://www.refresh-sf.com/yui/). It does JavaScript as well, but Google’s recently released Closure Compiler seems to be even more effective at compressing it. You can find it at http://closure-compiler.appspot.com/home. With the Closure Compiler, you can also select the advanced compiler which will decrease the total file size even more, but will mess up your files’ external API. This means that any functions you define inside your files won’t be available from the outside by the same name. The internal workings of the file will be preserved though.
Apart from minimizing the files, you should also compress them using something like GZip which is natively supported by several browsers. To see how to do this automatically with Apache2, have a look at http://www.cyberciti.biz/tips/speed-up-apache-20-web-access-or-downloads-with-mod_deflate.html.
Communicate
OK, so all of your files are combined and compressed, and you’ve never seen the CSS and JavaScript download so quickly. How can it possibly go any faster? Quite simple – by preventing the browser from having to download the files at all. Modern browsers include a lot of caching technology to prevent them from downloading unnecessary data from the server. The problem is that many web servers do not communicate properly the states of the files, and the browsers can thus not determine if a file has changed or not; and therefore they download the file just to make sure. So, what should you do?
First of all, you need to tell your web server to send out as much data as possible about your file. This especially applies to dynamic files such as those created by PHP. Have a look here for a more thorough discussion of this topic.
Second, files that are GZipped by Apache don’t always get an expiration date, causing the browser to re-download the file on every page load. To overcome this problem, have a look at the first answer on this page
Final thoughts
In the course of this post, I hope I have given you an overview of what can be done to speed up the loading time of web pages, and enough pointers to keep you going in your quest for the best speed your website can achieve. This is an ever-expanding topic, and new techniques are always appearing, so you should attempt as best you can to keep up to speed (pun intended) on the newest advances in the field.
Happy speeding!
Browse the web with PHP
Ever so often, you come across a website that you would like to check regularly. Usually, this website is placed behind some sort of login, and therefore, you think, you might just as well forget it. A while ago, I found myself in the same situation. My university in Oslo published grades online, but gave you no warning when the exam results where published, so you had to check every now and then to see if you had any new ones. I figured that this was a bit bothersome, and wanted to find a way around it.
There are several scripts and browser plugins out there that can check a page for updates on a regular basis, and notify you when something changes. The problem is that this site required you to log in first by submitting a form, and then navigate to the relevant page. I therefore decided to write a PHP class (or actually two) that would allow me to browse the web as through a browser; submitting forms and clicking links.
The result was the two classes Browser (http://www.phpclasses.org/browse/package/5450.html) and RemoteForm (http://www.phpclasses.org/browse/package/5449.html). The latter is a class that takes a form and parses out any input fields, selects and textareas and their respective default values. It then allows you to set values for these fields and submit the form – returning the resulting URL. The Browser class is one layer above, and depends on the RemoteForm class for handling form submission. It allows you to start a browser session and then navigate by simulating clicks on links through XPath selection.
See how simple it is to submit a search form on Wikipedia:
<?php require 'browser.class.php'; /** * The long way to the PHP Reference Manual... */ /** * New browser object */ $b = new Browser ( ); /** * Navigate to the first url */ $b -> navigate ( 'http://en.wikipedia.org/wiki/Main_Page' ); /** * Search for php */ $b -> submitForm ( $b -> getForm ( "//form[@id='searchform']" ) -> setAttributeByName ( 'search', 'php' ), 'fulltext' ) -> click ( "//a[@title='PHP']" ) // Click the PHP search result -> click ( "PHP Reference Manual" ); // Click the link to the ref echo $b -> getSource(); // Output the source




