Identify www bots and mobile devices

Posted by Dan Sosedoff on March 12, 2009

Need to identify web crawlers and mobile devices with your web-app ? Here is the list of couple regular expressions you can use (most common values):

Mobile Devices:

/(blackberry|motorokr|motorola|sony|windows ce|240x320|176x220|palm|mobile|iphone|ipod|symbian|nokia|samsung|midp)/i

Web Spyders:

/(google|yahoo|baidu|bot|webalta|archiver|crawler|spyder)/i

Connecting to wifi with specified wep key index

Posted by Dan Sosedoff on March 09, 2009

Since i got trouble while connecting to wireless network with given parameters in linux, i tried a lot of ways to get my internet working.

So, the problem is: Windows Network manager have special option – Key index. The index is transmitted with the encrypted message. The receiver then looks-up the key corresponding to the transmitted index and uses it to decrypt the message. But linux (ubuntu) network managers i`ve tried have no key index field, so there is no way to set it up properly with gui. Connection won`t work if index value set to incorrect value.

After giving up to find any useful gui program i wrote small shell script only for one network (because i have no access to router and no chance to improve some security settings):

#!/bin/bash
 
# settings
interface="ath0" # wireless interface, default to wlan0
essid="NETWORK_NAME_HERE"
key="YOUR_KEY_HERE"
index="4" # can be [1..4]
 
# check permission
if [ "$(id -u)" != "0" ]; then
   echo "Run this script under root" 1>&2
   exit 1
fi
 
# show information
echo "Settings:"
echo "-> Interface: $interface"
echo "-> Wifi ESSID: $essid"
echo "-> Key: $key"
echo "-> Key Index: $index"
 
# perform association
ifconfig $interface down
iwconfig $interface essid $essid
iwconfig $interface key $key [$index]
iwconfig $interface key [$index]
ifconfig $interface up
dhclient $interface

Download shell script – http://files.sosedoff.com/9591756c/

Check root user permissions in bash scripts

Posted by Dan Sosedoff on March 09, 2009

For example, in your bash shell script you`re going to use some root-specific commands like network operations, mounting devices and so on. There are couple easy ways to check if your script is executing under root privileges.

#!/bin/bash
# ...
if [ "$(id -u)" != "0" ]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi
# ...

Another way: use EUID. When user account created a user ID is assigned to each user. Bash shell stores the user ID in $UID variable. Your effective user ID is stored in $EUID variable.

#!/bin/bash
# ...
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi
# ...

Fetching album covers from Last.Fm API 3

Posted by Dan Sosedoff on February 15, 2009

As previous post was about fetching covers media from Amazon Web Services, this post will be about fetching covers from popular music site – Last.fm. API documentation page

#!/usr/bin/ruby
 
require 'rubygems'
require 'net/http'
require 'cgi'
require 'xmlsimple'
 
# key from API documentation
$lastfm_key = "b25b959554ed76058ac220b7b2e0a026" 
$lastfm_host = "ws.audioscrobbler.com"
 
def fetch_cover(artist, album)
	artist = CGI.escape(artist)
	album = CGI.escape(album)
 
	path = "/2.0/?method=album.getinfo&api_key=#{$lastfm_key}&artist=#{artist}&album=#{album}"
	data = Net::HTTP.get($lastfm_host, path)
	xml = XmlSimple.xml_in(data)
	if xml['status'] == 'ok' then
		album = xml['album'][0]
 
		cover = {
			:small => album['image'][1]['content'],
			:medium => album['image'][2]['content'],
			:big => album['image'][3]['content']
		}
 
		return cover
	end
 
	return nil
end
 
puts fetch_cover('Nickelback', 'Dark Horse').inspect

Download ruby script

Fetching album covers from Amazon Web Service 1

Posted by Dan Sosedoff on February 15, 2009

On my small project i was looking for web service to get media covers from. I found that i can use Amazon Web Services API. The documentation for this ECommerce Service is pretty old, but it still works.
More detailed information about API you can find here

#!/usr/bin/ruby
 
require 'rubygems'
require 'net/http'
require 'cgi'
require 'xmlsimple'
 
$amazon_key = "12DR2PGAQT303YTEWP02" # NOT MY KEY (FOUND ON INTERNET)
$amazon_host = "webservices.amazon.com"
 
def fetch_cover(artist, album)
	artist = CGI.escape(artist)
	album = CGI.escape(album)
 
	path = "/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=#{$amazon_key}&Operation=ItemSearch&SearchIndex=Music&Artist=#{artist}&ResponseGroup=Images&Keywords=#{album}"
	data = Net::HTTP.get($amazon_host, path)
	xml = XmlSimple.xml_in(data)
	if xml['Items'][0]['TotalResults'].to_s.to_i then
		cover = {
			:small => xml['Items'][0]['Item'][0]['SmallImage'][0]['URL'],
			:medium => xml['Items'][0]['Item'][0]['MediumImage'][0]['URL'],
			:big => xml['Items'][0]['Item'][0]['LargeImage'][0]['URL']
		}
		return cover
	end
	return nil
end

So, after execution of this function you will get array with 3 different images (small, medium, big).
I use XML-Simple gem for ruby. Can be installed this way

sudo gem install xml-simple

That`s it. Download script

Writing simple daemons in C

Posted by Dan Sosedoff on February 13, 2009

Since i started writing simple manuals about how to make system daemons i found bunch of interesting documents. For today, i just want to publish one of them instead of writing source code. This is manual originally written by Devin Watson, can be very useful for those how have no idea how to develop such system daemons. It`s only a basic information.

http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

Clean project from .svn directories 3

Posted by Dan Sosedoff on February 06, 2009

Sometimes it`s necessary to delete all .svn directories that were created by subversion version control system. This shell command will work on all unix systems:

rm -rf `find . -name .svn`

That`s it!

Updating order fields in table with MySQL

Posted by Dan Sosedoff on February 05, 2009

This is a simple piece of code which describing how to update special order field in table. For example, you have table ‘photos’:

+ --------------------------------- +
| ID    | UserID | OrderID | ImgURL |
+ --------------------------------- +
| 1132  | 1      | 0       | ...    |
| 2124  | 1      | 0       | ...    |
| 3456  | 1      | 0       | ...    |
.....................................
| N     | 1      | 0       | ...    |
+ --------------------------------- +

OrderID field value by default is 0. If some images has been deleted order lose its consistency.
To repair order we can use single transaction:

BEGIN;
 
SET @ORDER := 0;
UPDATE photos
SET order_id = (SELECT @ORDER := @ORDER + 1)
WHERE user_id = 1;
 
COMMIT;

After executing this on table ‘images’ we`ll get such result:

+ --------------------------------- +
| ID    | UserID | OrderID | ImgURL |
+ --------------------------------- +
| 1132  | 1      | 1       | ...    |
| 2124  | 1      | 2       | ...    |
| 3456  | 1      | 3       | ...    |
.....................................
| N     | 1      | M       | ...    |
+ --------------------------------- +

Some developers instead of using resources of mysql script language trying to solve this problem by executing numerous call, such ‘UPDATE table SET order_id = [value] WHERE id = [id] LIMIT 1;’. It`s wrong. MySQL language have a lot of ways to make it easy. At least UDF`s.

HDD click problem in Ubuntu

Posted by Dan Sosedoff on January 30, 2009

Since i completely switched to ubuntu 8.04 on my laptop i got very weird “click” sounds from hard drive. I thought it was just a simple “sleep” mode, parking heads or something pretty simple. But that sound began to appear so often (sometimes 2 clicks in 1 secons)  that i cant even get sleep with that disturbing sound.. But that sound appeared only in ubuntu and never heard it in other os. Wtf  is going on? After googling for a short time i figured out what was the problem – Advanced Power Management in Ubuntu.

Solution was very simple. Just turn off this power management:

sudo hdparm -B255 /dev/sda

If you have more than one drive – the same operation but with different device. That`s it.

Writing very simple daemon in Ruby 1

Posted by Dan Sosedoff on January 24, 2009

Ruby is very powerful language, not only for web development as many can think for the first time. It is also providing all necessary resources to build system utilities and daemons. So, this post exactly about it.
Long time ago i was looking for some tool to write simple daemon in a short term. I didn`t choose C just because i was able to develop program only on special computer (i mean “production-like” environment) and the problem wasnt critical to resources. In other words – this daemon was working only few days to complete the task. Ok, lets see what we`ve got:

#!/usr/bin/ruby
# ---------------------------------------------------------------------
# MODULES
# ---------------------------------------------------------------------
require 'daemonize'
include Daemonize
include Process
# ---------------------------------------------------------------------
# CONFIGURATION
# ---------------------------------------------------------------------
$daemon = {
  :name => "Test Daemon",                  # daemon name
  :abbr => "testd",                        # daemon abbreviation
  :author => "(c) 2008 author",            # daemon author
  :version => "0.1",                       # actual version
  :file_log => "/var/log/testdaemon.log",  # log path
  :file_pid => "/var/run/testdaemon.pid",  # process id path
  :delay_sleep => 1,                       # seconds
  :user => 'tux',                          # working data user
  :grp => 'tux',                           # working data group
  :background => false,                    # background mode
  :work => true                            # daemon work flag
}
 
$daemon_log = nil
$daemon_pid = nil
 
# ---------------------------------------------------------------------
 
def daemon_log(str)
  puts "[#{Time.now.strftime("%m/%d/%Y-%H:%M:%S")}] #{str}"
end
 
def daemon_terminate
  $daemon[:work] = false
end
 
def daemon_stop
  daemon_log("Stopping working process...")
  $daemon_pid.close
  File.delete($daemon[:file_pid])
end
 
def daemon_start
  if File.exist?($daemon[:file_pid]) then
    daemon_log("Process already running. If it`s not - remove the pid file")
    exit
  end
 
  daemon_log("Starting process...")
  daemonize if $daemon[:background]
 
  begin
    $daemon_pid = File.new($daemon[:file_pid],"w")
  rescue Errno::EACCES
    daemon_log("Cannot create PID file. Check the permissions and try again!")
    $daemon_pid = nil
    exit
  end  
 
  daemon_work
end
 
def daemon_work
  if ($daemon_pid) then
    $daemon_pid.sync = true
    $daemon_pid.puts(Process.pid.to_s)
 
    begin
      while $daemon[:work] do
        daemon_log("Daemon working")
        daemon_handle_signals
        sleep($daemon[:delay_sleep])
      end
    rescue Exception => e
      daemon_log("Error: #{e.message}")
    end
 
    daemon_stop
  end
end
 
def daemon_handle_signals
  # termination signal
  Signal.trap("TERM") do
    daemon_log("TERM signal received.")
    daemon_terminate
  end  
 
  # kill signal
  Signal.trap("KILL") do
    daemon_log("KILL signal received.")
    daemon_terminate
  end
 
  # keyboard interruption
  Signal.trap("INT") do
    daemon_log("SIGINT signal received.")
    daemon_terminate
  end
 
  Signal.trap("TSTP") do
    daemon_log("SIGTSTP signal received.")
  end
end
 
def daemon_show_version
  puts "#{$daemon[:name]} v#{$daemon[:version]} #{$daemon[:author]}"
end
 
def daemon_show_usage
  daemon_show_version
  puts "Usage:"
  puts "    -b, --background        work in background mode"
  puts "    -v, --version           view version of daemon"
  puts "    -h, --help              view this help"
end
 
def daemon_parse_opts
  return true if ARGV.length == 0
 
  case ARGV[0]
    when '-b', '--background'
      $daemon[:background] = true;
      return true
 
    when '-v', '--version'
      daemon_show_version
 
    when '-h', '--help'
      daemon_show_usage
    else
      puts "Invalid argument: #{ARGV[0]}" if !ARGV[0].nil?
      daemon_show_usage
  end
 
  return false
end
 
def daemon_main
  daemon_start if daemon_parse_opts
end
 
daemon_main

This is just a basic structure of daemon, it supports background mode. I removed all unimportant information and left only main program cycles. As you can see, the entry point of whole program – daemon_main procedure. It parsing the command line parameters. In this example there is no required parameters, so daemon will run in basic mode (not background). To enable background you should specify the -d (or –background) option. Also, very important – this example needs to be executed under root or other user that have access to /var/run. Other way, PID file path can be changed to whatever you want (file_pid key). All daemon configuration variables stored in array $daemon. Also, it supports system signals handling, like SIGTERM or SIGKILL (all ruby signal constants u can explore here).

I think that`s it. Not a lot, but very simple. Download script: http://files.sosedoff.com/b57415aa/