<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;A0YEQ305eip7ImA9WhRWFU4.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578</id><updated>2012-01-03T10:18:22.322+13:00</updated><category term="logging" /><category term="Windows XP" /><category term="Fedora 14" /><category term="Fedora" /><category term="customer satisfaction" /><category term="active directory" /><category term="gpg" /><category term="dd" /><category term="isoinfo" /><category term="isql" /><category term="webbrowser" /><category term="sha1sum" /><category term="Windows Server 2008" /><category term="unix philosophy" /><category term="linux odbc" /><category term="Kernel" /><category term="Pod Cast" /><category term="canon" /><category term="odbc" /><category term="Customers" /><category term="ghostscript" /><category term="Scite" /><category term="sed" /><category term="python web-service" /><category term="Document Editing" /><category term="dvbt" /><category term="Charity" /><category term="css" /><category term="gs" /><category term="md5sum" /><category term="rdp" /><category term="iPod" /><category term="printer" /><category term="F2280" /><category term="Apache" /><category term="TCP Printing Services" /><category term="xrdp" /><category term="scheduled tasks" /><category term="register globals" /><category term="work" /><category term="wget" /><category term="Support Group" /><category term="terms of service agreements" /><category term="lame" /><category term="facebook" /><category term="Payment Gateways" /><category term="VMWare" /><category term="MySQL" /><category term="authentication" /><category term="chomp" /><category term="freeview" /><category term="python inotify linux filesystem" /><category term="design principals" /><category term="iSCSI" /><category term="bash" /><category term="Latex" /><category term="networking" /><category term="F2200" /><category term="USB" /><category term="InnoDB" /><category term="Virtualisation" /><category term="Structured Documents" /><category term="bash progress bar" /><category term="iTunes" /><category term="fedora 12" /><category term="gtk-pod" /><category term="html" /><category term="xbox gamepad" /><category term="osCommerce" /><category term="ssl" /><category term="mod_python" /><category term="Network Storage" /><category term="remote desktop" /><category term="verify" /><category term="paymex" /><category term="new zealand" /><category term="old computers" /><category term=".NET" /><category term="Social networking" /><category term="xbox to usb" /><category term="python isoinfo dd bash verify md5sum sha1sum" /><category term="Vista" /><category term="Music Player" /><category term="real lve people" /><category term="windows to linux rdp" /><category term="VirtualBox" /><category term="floating box model" /><category term="perl" /><category term="christmas" /><category term="Linux Security" /><category term="flock" /><category term="youtube" /><category term="curl" /><category term="mplayer" /><category term="MYISAM" /><category term="pgp" /><category term="Active State" /><category term="gpodder" /><category term="ldap" /><category term="Windows Comand Line" /><category term="python" /><category term="heartbeat" /><category term="Clusters" /><category term="python 3 tier architecture." /><category term="layout" /><category term="podcasts" /><category term="mobile phone" /><category term="mame" /><category term="kvm" /><category term="Cluster" /><category term="rip wav2mp3" /><category term="driver" /><category term="gnupg" /><category term="Redhat" /><category term="Reverse Proxy" /><category term="id3v2" /><category term="Internet" /><category term="SQL Server 2008" /><category term="Jargon" /><category term="php" /><category term="process" /><category term="MediaWiki" /><category term="Images in wxPython" /><category term="sessman" /><category term="time calculations" /><category term="high availability" /><category term="software design" /><category term="music" /><category term="yami" /><category term="amarok 1.4" /><category term="virtual ip address" /><category term="wxPython" /><category term="nokia 3120" /><category term="Multiple Volumes" /><category term="print" /><category term="Redhat Kickstart" /><category term="blogger" /><category term="paypal" /><category term="eCommerce" /><category term="Linux" /><category term="twitter" /><category term="Audio Books" /><category term="accidental photo" /><category term="Pana" /><category term="mono" /><category term="gmail" /><category term="mod_perl" /><category term="single line" /><title>David Latham</title><subtitle type="html">Adventures in Linux, Web Applications, Shell Scripts and everything else related.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>83</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/david-latham" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="david-latham" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUAHRHg6eip7ImA9WhdXF0U.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-2035395986736988125</id><published>2011-08-31T22:12:00.006+12:00</published><updated>2011-08-31T22:48:55.612+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-31T22:48:55.612+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MySQL" /><category scheme="http://www.blogger.com/atom/ns#" term="MYISAM" /><category scheme="http://www.blogger.com/atom/ns#" term="iSCSI" /><category scheme="http://www.blogger.com/atom/ns#" term="Network Storage" /><category scheme="http://www.blogger.com/atom/ns#" term="Redhat" /><category scheme="http://www.blogger.com/atom/ns#" term="Multiple Volumes" /><category scheme="http://www.blogger.com/atom/ns#" term="InnoDB" /><title>Configuring MySQL on Redhat Linux while utilising network (iSCSI) storage.</title><content type="html">&lt;span style="font-weight: bold;"&gt;Challenges:&lt;/span&gt;
&lt;br /&gt;MySQL only allows a single location to be specified as the default data store for all databases. 
&lt;br /&gt;
&lt;br /&gt;Consider the following typical scenario:
&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A database server running one instance of MySQL has its datastore located at /mysql/databases.&lt;/li&gt;&lt;li&gt;This server will contain multiple databases for multiple applications.&lt;/li&gt;&lt;li&gt;The database tables are a mixture of InnoDB and MYISAM storage engines.&lt;/li&gt;&lt;li&gt;The storage is provided by a SAN and separate storage volumes (iSCSI targets) are provisioned for each database.&lt;/li&gt;&lt;/ul&gt;In this scenario, you would want all your MYISAM files (*.MYI, *.MYD, *.frm) and all your InnoDB table spaces to be contained on the same iSCSI volume on a per-database basis.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution:&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;This is easily achieved by mounting the iSCSI target on a sub-folder of /mysql/databases.  For example:
&lt;br /&gt;
&lt;br /&gt;Mount iqn.openfiler.com:2006-06:blog-db-storage on /mysql/databases/blog
&lt;br /&gt;
&lt;br /&gt;Here is a sequence of steps that need to be carried out to make this work.
&lt;br /&gt;
&lt;br /&gt;&lt;ol&gt;&lt;li&gt;in /etc/my.cnf set datastore=/mysql/databases&lt;/li&gt;&lt;li&gt;in /etc/my.cnf set innodb_file_per_table (&lt;a href="http://dev.mysql.com/doc/refman/5.0/en/innodb-multiple-tablespaces.html"&gt;http://dev.mysql.com/doc/refman/5.0/en/innodb-multiple-tablespaces.html&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Configure SELINUX and user/group rights appropriately for MySQL.  There is heaps on this on the internet but please comment if you would like me to add some detail here.&lt;/li&gt;&lt;li&gt;Start the mysqld service&lt;/li&gt;&lt;li&gt;configure the mysql root password if necessary
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;login to mysql as root&lt;/li&gt;&lt;li&gt;create the blog database (create database blog;)  This creates the blog directory in /mysql/databases/blog  At this point there is nothing inside it.
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;log out of mysql.&lt;/li&gt;&lt;li&gt;Mount your iscsi storage volume on /mysql/databases/blog&lt;/li&gt;&lt;li&gt;Configure your system so that the iscsi storage volume has a persistence and is always mounted on this location.  Redhat have a great tutorial on how to do this.  Basically it involves checking the WID of your iscsi target and then applying that to a udev rule that creates a consistently named block device under /dev&lt;/li&gt;&lt;li&gt;Now go ahead and create your tables.  All the MYISAM and InnoDB tables will be created inside the /mysql/databases/blog directory.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-weight: bold;"&gt;Code / Scripts:&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;I am happy to provide scripts or code if people want.  The following links should get you started.
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Links:&lt;/span&gt;
&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.0/en/innodb-multiple-tablespaces.html"&gt;http://dev.mysql.com/doc/refman/5.0/en/innodb-multiple-tablespaces.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.5/en/option-files.html"&gt;http://dev.mysql.com/doc/refman/5.5/en/option-files.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization/sect-Virtualization-Virtualized_block_devices-Configuring_persistent_storage_in_Red_Hat_Enterprise_Linux_5.html#form-Virtualization-Configuring_persistent_storage_in_Red_Hat_Enterprise_Linux_6-Single_path_configuration"&gt;http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization/sect-Virtualization-Virtualized_block_devices-Configuring_persistent_storage_in_Red_Hat_Enterprise_Linux_5.html#form-Virtualization-Configuring_persistent_storage_in_Red_Hat_Enterprise_Linux_6-Single_path_configuration&lt;/a&gt;
&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-2035395986736988125?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/2035395986736988125/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=2035395986736988125" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/2035395986736988125?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/2035395986736988125?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2011/08/configuring-mysql-on-redhat-linux-while.html" title="Configuring MySQL on Redhat Linux while utilising network (iSCSI) storage." /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUYDSHk6fSp7ImA9WhdXFkw.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-5559689326043721312</id><published>2011-08-29T21:18:00.007+12:00</published><updated>2011-08-29T22:19:39.715+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-29T22:19:39.715+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="process" /><category scheme="http://www.blogger.com/atom/ns#" term="Customers" /><category scheme="http://www.blogger.com/atom/ns#" term="customer satisfaction" /><title>MUST FOLLOW PROCESS...</title><content type="html">&lt;span style="font-style: italic; font-weight: bold;"&gt;MUST FOLLOW PROCESS.... MUST FOLLOW PROCESS...&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;Starting with the premise that we need our customers to be happy with us, what do we need to do as an organisation to keep them that way?
&lt;br /&gt;
&lt;br /&gt;We are working through steps to improve our customer satisfaction at work by carefully considering how our daily work routines, processes and actions impact our customers.
&lt;br /&gt;
&lt;br /&gt;Consider this fairly typical example of how an organisation might respond to a customer request:
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-style: italic;"&gt;[NOTE: This is a little bit (A LOT) satirical and not meant to in anyway be a real representation of an actual process.  It's designed to highlight how strict adherence to process can lead to unhappy customers.]&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;A customer needs a new type of widget.  Your organisation sells gadgets that are very similar to widgets so they approach you to design and build one for them.  They are willing to pay for the service but they need this new widget to work for them.
&lt;br /&gt;
&lt;br /&gt;Luckily your organisation has a process to handle this type of request.  It's called Customer Request Acceptance Process.  It is a sequence of actions scraped out of a managerial text book written in the early 1900's.
&lt;br /&gt;
&lt;br /&gt;So the sales rep in your organisation finds the appropriate template and begins...
&lt;br /&gt;
&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The sales rep spends 2 hours working out how best to express his customer's requirements on the template.  The template is designed to be all encompassing providing options for everything.  Clearly (from looking at the template) anything not covered by it's fields are not valid for submission.  &lt;span style="font-style: italic; font-weight: bold; color: rgb(0, 102, 0);"&gt;[Templates have their place but be careful of over detailing them - they get confusing.  A good place to start is a subject and details box.  Leave the rest to the technical guys to nut out.]&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The working group that handle inbound requests receive the completed form and instantly find gaps in information.  They make assumptions about some of the more obvious omissions and request clarification from the sales rep on the others.  &lt;span style="font-style: italic; font-weight: bold; color: rgb(0, 102, 0);"&gt;[Leave the mind reading to the professionals]&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The sales rep is very confident that he understands 90% of the questions and answers them straight away and on the other 10% he seeks clarification.&lt;span style="font-style: italic; font-weight: bold;"&gt; &lt;span style="color: rgb(0, 102, 0);"&gt;[More mind reading...]&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Finally the requirements are gathered (from the sales rep and via a series of mini assumptions about unimportant details)&lt;/li&gt;&lt;li&gt;A quote is hastily written up and the sales rep informed.  The sales rep sells the solution to the customer. &lt;span style="font-weight: bold; font-style: italic; color: rgb(0, 102, 0);"&gt;[the solution has to be sold???  I thought the customer asked for it in the first place.  Be careful! If you have to **sell** the solution to a customer request then it's probably not what they wanted.]&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The tech team receive the go-ahead and begin work on the widget.  The widget is FANTASTIC.  It's so damn clever, some individuals are already talking about it to their contacts in an effort to drum up even more revenue. &lt;span style="font-weight: bold; font-style: italic; color: rgb(0, 102, 0);"&gt;[Woooah there Silver, Does it work for the customer?  Has anyone asked them?]&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The widget is delivered more or less on schedule. &lt;span style="font-weight: bold; font-style: italic; color: rgb(0, 102, 0);"&gt;[Good work guys - go eat pizza and have a celebration.]&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The customer finds that it sort-of does what it's supposed to do but they don't complain because they have come to expect this sort of thing from the organisation.&lt;span style="font-weight: bold; font-style: italic; color: rgb(0, 102, 0);"&gt;[What???  This is acceptable to you Mr. Customer?  Find another provider already!]&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Your organisation sends the customer a survey asking how happy they are and soon it becomes apparent that they are not. &lt;span style="font-weight: bold; font-style: italic; color: rgb(0, 102, 0);"&gt;[By sending a survey out you send a message saying that you need to know what's wrong before you can fix it.  If you don't fix it your customer will assume your are being cynical about the whole survey thing and not bother answering it.]&lt;/span&gt;
&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;My point with this extremely obvious example is that:
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;a happy customer is very simply a customer that you talk to all the time!&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;So while your organisation might have a process and tools to manage that process, it's useless if you don't know what your customer really wants.
&lt;br /&gt;
&lt;br /&gt;Some customers are not too good at telling us what they really want. 
&lt;br /&gt;Most of the time, I suggest that we are not placing the appropriate individuals in our organisations together.  IE: Customer end user of WIDGET next to the provider technical person designing the WIDGET.  It makes sense that these two should work closely together. 
&lt;br /&gt;
&lt;br /&gt;Providers should develop fast prototypes and be less precious about the their solutions in case they end up not being fit for purpose.  Every time a mistake is corrected, your product is improved.
&lt;br /&gt;
&lt;br /&gt;It is impossible to gather all the requirements in one go.  Requirements have a way of evolving as the design takes shape.
&lt;br /&gt;
&lt;br /&gt;No amount of technology based tools to manage your processes will help you if your processes do not include the customer at every step.
&lt;br /&gt;
&lt;br /&gt;Every step in your process that does not include the customer results in your product diverging further from the customer's requirements.
&lt;br /&gt;
&lt;br /&gt;We should all evaluate all the time how what we do impacts the customer.  If you don't know how your job impacts your customers, you should make it your number one concern to find out.  Customers pay your salary.  Not your boss or your manager.
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-5559689326043721312?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/5559689326043721312/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=5559689326043721312" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/5559689326043721312?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/5559689326043721312?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2011/08/must-follow-process.html" title="MUST FOLLOW PROCESS..." /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEUBRX8yeCp7ImA9WhdSEkk.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-590308651690282409</id><published>2011-07-21T22:59:00.002+12:00</published><updated>2011-07-21T23:04:14.190+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-21T23:04:14.190+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux Security" /><title>REBLOG!!! Sticky bit, suid and guid</title><content type="html">I have to reblog this article in it's full just in case the original author removes it.&lt;br /&gt;&lt;br /&gt;Here is the original.&lt;br /&gt;http://bashscript.blogspot.com/2010/03/unixlinux-advanced-file-permissions.html&lt;br /&gt;&lt;br /&gt;Here in plain text to ** FORCE ** it into my rubbish layout.&lt;br /&gt;&lt;br /&gt;UNIX/Linux Advanced File Permissions - SUID,SGID and Sticky Bit&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   After you have worked for a while with Linux you discover probably&lt;br /&gt;that there is much more to file permissions than just the "rwx" bits.&lt;br /&gt;When you look around in your file system you will see "s" and "t"&lt;br /&gt;&lt;br /&gt;$  ls -ld /tmp&lt;br /&gt;drwxrwxrwt 29 root root 36864 Mar 21 19:49 /tmp&lt;br /&gt;&lt;br /&gt;$  which passwd&lt;br /&gt;/usr/bin/passwd&lt;br /&gt;&lt;br /&gt;$  ls -l /usr/bin/passwd&lt;br /&gt;-rwsr-xr-x 1 root root 22984 Jan  6  2007 /usr/bin/passwd&lt;br /&gt;&lt;br /&gt; What is this "s" and "t" bit? The vector of permission bits is really&lt;br /&gt;4 * 3 bits long. Yes there are 12 permission bits,not just 9.The first&lt;br /&gt;three bits are special and are frequently zero. And you almost always&lt;br /&gt;learn about the trailing 9 bits first.Some people stop there and never&lt;br /&gt;learn those first three bits.&lt;br /&gt;&lt;br /&gt; The forth permission bit is used only when a special mode of a file&lt;br /&gt;needs to be set. It has the value 4 for SUID, 2 for SGID and 1 for the&lt;br /&gt;sticky bit. The other 3 bits have their usual significance.&lt;br /&gt;&lt;br /&gt; Here we will discuss about the 3 special attributes other than the&lt;br /&gt;common read/write/execute:&lt;br /&gt;&lt;br /&gt;     1.Set-User-Id (SUID)&lt;br /&gt;        2.Set-Group-Id (SGID)&lt;br /&gt;        3.Sticky Bit&lt;br /&gt;&lt;br /&gt;Set-User_Id (SUID): Power for a Moment:  &lt;br /&gt;&lt;br /&gt; By default, when a user executes a file, the process which results in&lt;br /&gt;this execution has the same permissions as those of the user. In fact,&lt;br /&gt;the process inherits his default group and user identification.&lt;br /&gt;&lt;br /&gt; If you set the SUID attribute on an executable file, the process res-&lt;br /&gt;ulting in its execution doesn't use the user's identification but the&lt;br /&gt;user identification of the file owner.&lt;br /&gt;&lt;br /&gt; The SUID mechanism,invented by Dennis Ritchie,is a potential security&lt;br /&gt;hazard. It lets a user acquire hidden powers by running such a file&lt;br /&gt;owned by root.&lt;br /&gt;&lt;br /&gt;$ ls -l /etc/passwd /etc/shadow /usr/bin/passwd&lt;br /&gt;-rw-r--r-- 1 root root  2232 Mar 15 00:26 /etc/passwd&lt;br /&gt;-r-------- 1 root root  1447 Mar 19 19:01 /etc/shadow&lt;br /&gt;&lt;br /&gt; The listing shows that passwd is readable by all, but shadow is unre-&lt;br /&gt;adable by group and others. When a user running the program belongs to&lt;br /&gt;one of these two categories (probably, others), so access fails in the&lt;br /&gt;read test on shadow. suppose normal user wants to change his password,&lt;br /&gt;How can he do that? He can do that by running /usr/bin/passwd. Many&lt;br /&gt;UNIX/Linux programs have a special permission mode that lets users&lt;br /&gt;update sensitive system files –like /etc/shadow --something they can't&lt;br /&gt;do directly with an editor. This is true of the passwd program.&lt;br /&gt;&lt;br /&gt;$ ls -l /usr/bin/passwd&lt;br /&gt;-rwsr-xr-x 1 root root 22984 Jan  6  2007 /usr/bin/passwd&lt;br /&gt;&lt;br /&gt;The s letter in the user category of the permission field represents a&lt;br /&gt;special mode known as the set-user-id (SUID). This mode lets a process&lt;br /&gt;have the privileges of the owner of the file during the instance of&lt;br /&gt;the program. Thus when a non privileged user executes passwd, the eff-&lt;br /&gt;ective UID of the process is not the user's, but of root's – the owner&lt;br /&gt;of the program. This SUID privilege is then used by passwd to edit&lt;br /&gt;/etc/shadow.&lt;br /&gt;&lt;br /&gt;What is effective user-id:&lt;br /&gt;&lt;br /&gt; Every process really has two user IDs: the effective user ID and the&lt;br /&gt;real user ID. (Of course, there's also an effective group ID and real&lt;br /&gt;group ID.Just about everything that's true about user IDs is also true&lt;br /&gt;about group IDs) Most of the time,the kernel checks only the effective&lt;br /&gt;user ID. For example, if a process tries to open a file, the kernel&lt;br /&gt;checks the effective user ID when deciding whether to let the process&lt;br /&gt;access the file.&lt;br /&gt;&lt;br /&gt;  Save the following script under the name reids.pl and make it&lt;br /&gt;executable (chmod 755 reids.pl). &lt;br /&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;# print real UID&lt;br /&gt;print "Real UID: $&lt;\n";&lt;br /&gt;# print real GID&lt;br /&gt;print "Real GID: $(\n";&lt;br /&gt;# print effective UID&lt;br /&gt;print "Effective UID: $&gt;\n";&lt;br /&gt;# print effective GID&lt;br /&gt;print "Effective GID: $)\n";&lt;br /&gt;&lt;br /&gt;check file permissions:&lt;br /&gt;&lt;br /&gt;$ ls -l reids.pl&lt;br /&gt;-rwxr-xr-x 1 venu venu 203 Mar 24 10:40 reids.pl&lt;br /&gt;&lt;br /&gt;Note: For security reasons the s-bit works only when used on binaries&lt;br /&gt;(compiled code) and not on scripts (an exception are perl scripts).&lt;br /&gt;Scripts,i.e. programs that cannot be executed by the kernel directory&lt;br /&gt;but need an interpreter such as the Bourne shell or Java,can have&lt;br /&gt;their setuid bit set, but it doesn't have any effect. There are some&lt;br /&gt;platforms that honor the s bits even on scripts ( some System V vari-&lt;br /&gt;ants, for example), but most systems don't because it has proven such&lt;br /&gt;a security headache - most interpreters simply aren't written with&lt;br /&gt;much security in mind. Set the SUID bit on shell script is useless,&lt;br /&gt;that's why I am using perl script here.&lt;br /&gt;&lt;br /&gt; When you run the script you will see that the process that runs it&lt;br /&gt;gets your user-ID and your group-ID:&lt;br /&gt;&lt;br /&gt;$ ./reids.pl&lt;br /&gt;Real UID: 500&lt;br /&gt;Real GID: 500 500&lt;br /&gt;Effective UID: 500&lt;br /&gt;Effective GID: 500 500&lt;br /&gt;&lt;br /&gt;Note: If you get an error like this:&lt;br /&gt;Can't do setuid (cannot exec sperl)&lt;br /&gt;&lt;br /&gt;In Debian install perl-suid using following command:&lt;br /&gt;apt-get install perl-suid&lt;br /&gt;&lt;br /&gt;In Centos install perl-suidperl using following command:&lt;br /&gt;yum install perl-suidperl&lt;br /&gt;&lt;br /&gt; Now change owner ship to  another user (Do it as an administrator).&lt;br /&gt;&lt;br /&gt;# chown king /home/venu/reids.pl&lt;br /&gt;# ls -l /home/venu/reids.pl&lt;br /&gt;-rwxr-xr-x 1 king venu 203 Mar 24 10:40 /home/venu/reids.pl&lt;br /&gt;&lt;br /&gt;Now run the script again.&lt;br /&gt;&lt;br /&gt;$ ./reids.pl&lt;br /&gt;Real UID: 500&lt;br /&gt;Real GID: 500 500&lt;br /&gt;Effective UID: 500&lt;br /&gt;Effective GID: 500 500&lt;br /&gt;&lt;br /&gt; What you observed, the output of the program depends only on the user&lt;br /&gt;that runs it and not the one who owns the file.&lt;br /&gt;&lt;br /&gt;How to assign SUID permission: &lt;br /&gt;&lt;br /&gt; The SUID for any file can be set (mostly by the superuser) with a&lt;br /&gt;special syntax of the chmod command. This syntax uses the character s&lt;br /&gt;as the permission. Now add SUID permission to the script reids.pl :&lt;br /&gt;&lt;br /&gt;# chmod u+s /home/venu/reids.pl     (Do it from root account)&lt;br /&gt;&lt;br /&gt;Now return from the super user mode to the usual non privileged mode.&lt;br /&gt;&lt;br /&gt;$ ls -l reids.pl&lt;br /&gt;-rwsr-xr-x 1 king venu 203 Mar 24 10:40 reids.pl&lt;br /&gt;&lt;br /&gt; To assign SUID in an absolute manner, simply prefix 4 to whatever&lt;br /&gt;octal string you would otherwise use (like 4755 instead of 755).&lt;br /&gt;&lt;br /&gt; The file reids.pl is owned by king and has the s-bit set where norma-&lt;br /&gt;lly the x is for the owner of the file. This causes the file to be&lt;br /&gt;executed under the user-ID of the user that owns the file rather than&lt;br /&gt;the user that executes the file. If venu runs the program then this&lt;br /&gt;looks as follows:&lt;br /&gt;&lt;br /&gt;$ perl reids.pl&lt;br /&gt;Real UID: 500&lt;br /&gt;Real GID: 500 500&lt;br /&gt;Effective UID: 503&lt;br /&gt;Effective GID: 500 500&lt;br /&gt;&lt;br /&gt; Effective user id of process is 503, this is not the venu's , but of&lt;br /&gt;king's - the owner of the program. As you can see this is a very powe-&lt;br /&gt;rful feature especially if root owns the file with s-bit set. Any user&lt;br /&gt;can then do things that normally only root can do.&lt;br /&gt;&lt;br /&gt;Caution:    When you write a SUID program then you must make sure that&lt;br /&gt;it can only be used for the purpose that you intended it to be used.&lt;br /&gt;As administrator, you must keep track of all SUID programs owned by&lt;br /&gt;root that a user may try to create or copy. The find command easily&lt;br /&gt;locate them:&lt;br /&gt;&lt;br /&gt;# find /home -perm -4000 -print | mail root&lt;br /&gt;&lt;br /&gt;  The extra octal bit (4) signifies the SUID mode, but find treats the&lt;br /&gt;  "–" before 4000 as representing any other permissions.&lt;br /&gt;&lt;br /&gt;Set-Group_Id (SGID):&lt;br /&gt;&lt;br /&gt; The set-group-id (SGID) is similar to SUID except that a program with&lt;br /&gt;SGID set allows the user to have the same power as the group which&lt;br /&gt;owns the program. The SGID bit is 2,and some typical examples could be&lt;br /&gt;chmod g+s reids.pl or chmod 2755 reids.pl.&lt;br /&gt;You can remove SGID bit using following commands:&lt;br /&gt;&lt;br /&gt;$ chmod g-s reids.pl&lt;br /&gt;$ chmod 755 reids.pl       (Absolute manner)&lt;br /&gt;&lt;br /&gt; It is really useful in case you have a real multi-user setup where&lt;br /&gt;users access each others files. As a single homeuser I haven't really&lt;br /&gt;found a lot of use for SGID. But the basic concept is the same as the&lt;br /&gt;SUID,Similar to SUID, SGID also grants privileges and access rights to&lt;br /&gt;the process running the command, but instead of receiving those of the&lt;br /&gt;file's owner it receives those of the file's group. In other words,the&lt;br /&gt;process group owner will be set to the file's group. &lt;br /&gt;&lt;br /&gt; I explain it with an example. I have created two user accounts king &lt;br /&gt;and venu with same home directory project. king belongs to king and&lt;br /&gt;development groups, venu belongs to venu and development groups.&lt;br /&gt;&lt;br /&gt;# groups king venu&lt;br /&gt;king : king development&lt;br /&gt;venu : venu development&lt;br /&gt;&lt;br /&gt;venu's default group is venu and king's default group is king.&lt;br /&gt;&lt;br /&gt; Login as king and create reids.pl  file again and make it executable&lt;br /&gt;(using  chmod 755 reids.pl) .&lt;br /&gt;&lt;br /&gt;$ id&lt;br /&gt;uid=503(king) gid=503(king) groups=501(development),503(king)&lt;br /&gt;$ ls -l reids.pl&lt;br /&gt;-rwxr-xr-x 1 king development 203 Mar 25 19:00 reids.pl&lt;br /&gt;&lt;br /&gt;Now login as venu and run the program:&lt;br /&gt;&lt;br /&gt;$ id&lt;br /&gt;uid=501(venu) gid=504(venu) groups=501(development),504(venu)&lt;br /&gt;$ perl reids.pl&lt;br /&gt;Real UID: 501&lt;br /&gt;Real GID: 504 504 501&lt;br /&gt;Effective UID: 501&lt;br /&gt;Effective GID: 504 504 501&lt;br /&gt;&lt;br /&gt;The effective GID of the process is the venu's,but not of the king's &lt;br /&gt;-the owner of the program.&lt;br /&gt;&lt;br /&gt;Now login as king and assign SGID bit to reids.pl program:&lt;br /&gt;&lt;br /&gt;$ chmod 2755 reids.pl; ls -l reids.pl&lt;br /&gt;-rwxr-sr-x 1 king development 203 Mar 25 19:00 reids.pl&lt;br /&gt;&lt;br /&gt;Now login as venu and run the reids.pl program:&lt;br /&gt;&lt;br /&gt;$ perl reids.pl&lt;br /&gt;Real UID: 501&lt;br /&gt;Real GID: 504 504 501&lt;br /&gt;Effective UID: 501&lt;br /&gt;Effective GID: 501 504 501&lt;br /&gt;&lt;br /&gt; Real GID and Effective GID are different,here Effective GID is the&lt;br /&gt;king's - the owner of the program.&lt;br /&gt;&lt;br /&gt;Set SGID on a directory:&lt;br /&gt;&lt;br /&gt; When SGID is set on a directory it has a special meaning. Files crea-&lt;br /&gt;ted in a directory with SGID set will inherit the same group ownership&lt;br /&gt;as the directory itself,not the group of the user who created the file.&lt;br /&gt;If the SGID is not set the file's group ownership corresponds to the&lt;br /&gt;user's default group.&lt;br /&gt;&lt;br /&gt; In order to set the SGID on a directory or to remove it, use the&lt;br /&gt;following commands:&lt;br /&gt;&lt;br /&gt;$ chmod g+s directory     or     $ chmod 2755 directory&lt;br /&gt;$ chmod g-s directory     or     $ chmod 755 directory&lt;br /&gt;&lt;br /&gt; As I mentioned earlier venu and king's home directory is same that is&lt;br /&gt;/home/project. I changed group ownership of /home/project directory&lt;br /&gt;to development.&lt;br /&gt;&lt;br /&gt;# ls -ld /home/project/&lt;br /&gt;drwxrwxr-x 16 root development 4096 Mar 26 00:22 /home/project/&lt;br /&gt;&lt;br /&gt;Now login as king and create a temp file.&lt;br /&gt;&lt;br /&gt;$ whoami&lt;br /&gt;king&lt;br /&gt;$ pwd&lt;br /&gt;/home/project/&lt;br /&gt;$ touch temp; ls -l temp&lt;br /&gt;-rw-r--r-- 1 king king 0 Mar 26 12:34 temp&lt;br /&gt;&lt;br /&gt; You can see from the ls output that the group owner for project is&lt;br /&gt;development, and that the SGID bit has not been set on the directory&lt;br /&gt;yet. When king creates a file in project, the group for the file is&lt;br /&gt;king (king's primary gid).&lt;br /&gt;&lt;br /&gt; Set SGID bit on project directory. For that login as administrator&lt;br /&gt;and set SGID bit using following command:&lt;br /&gt;&lt;br /&gt;# chmod g+s /home/project/&lt;br /&gt;# ls -ld /home/project/&lt;br /&gt;drwxrwsr-x 15 root development 4096 Mar 26 12:34 /home/project/&lt;br /&gt;&lt;br /&gt; From the ls output above, you know the SGID bit is set because of the&lt;br /&gt;s in the third position of the group permission set,which replaces the&lt;br /&gt;x in the group permissions.&lt;br /&gt;&lt;br /&gt;Now login as king and create temp2 file.&lt;br /&gt;&lt;br /&gt;$ whoami&lt;br /&gt;king&lt;br /&gt;$ touch temp2; ls -l temp2&lt;br /&gt;-rw-r--r-- 1 king development 0 Mar 26 13:49 temp2&lt;br /&gt;&lt;br /&gt; Notice the group ownership for temp2 file. It inherits group permiss-&lt;br /&gt;ion from the parent directory.&lt;br /&gt;&lt;br /&gt; Enabling SGID on a directory is extremely useful when you have a&lt;br /&gt;group of users with different primary groups working on the same set&lt;br /&gt;of files.&lt;br /&gt;&lt;br /&gt;        For system security reasons it is not a good idea to set many&lt;br /&gt;program's set user or group ID bits any more than necessary,since this&lt;br /&gt;can allow an unauthorized user privileges in sensitive system areas.If&lt;br /&gt;the program has a flaw that allows the user to break out of the inten-&lt;br /&gt;ded use of the program, then the system can be compromised.&lt;br /&gt;&lt;br /&gt;Sticky bit:&lt;br /&gt;&lt;br /&gt; The sticky bit(also called the saved text bit) is the last permission&lt;br /&gt;bit remaining to be discussed. It applies to both regular files and&lt;br /&gt;directories. When applied to a regular file, it ensures that the text&lt;br /&gt;image of a program with the bit set is permanently kept in the swap&lt;br /&gt;area so that it can be reloaded quickly when the program's turn to use&lt;br /&gt;the CPU arrives. Previously, it made sense to have this bit set for&lt;br /&gt;programs like vi and emacs. Today,machines with ultra-fast disk drives&lt;br /&gt;and lots of cheap memory don't need this bit for ordinary files and&lt;br /&gt;that is also useless.&lt;br /&gt;&lt;br /&gt; However, the sticky bit become a useful security feature when used&lt;br /&gt;with a directory. The UNIX/Linux system allows users to create files&lt;br /&gt;in /tmp, but none can delete files not owned by him. That's possible&lt;br /&gt;because sticky bit set for /tmp directory.&lt;br /&gt;&lt;br /&gt; The /tmp directory is typically world-writable and looks like this&lt;br /&gt;in a listing:&lt;br /&gt;&lt;br /&gt;# ls -ld /tmp&lt;br /&gt;drwxrwxrwt 32 root root 36864 Mar 27 12:38 /tmp&lt;br /&gt;&lt;br /&gt; Everyone can read,write and access the directory.The t indicates that&lt;br /&gt;only the user (root and owner of the directory,of course) that created&lt;br /&gt;a file in this directory can delete that file.&lt;br /&gt;&lt;br /&gt; In order to set or to remove the sticky bit, use the following&lt;br /&gt;commands:&lt;br /&gt;&lt;br /&gt;$ chmod +t directory     or    $ chmod 1754 directory&lt;br /&gt;$ chmod -t directory     or    $ chmod  754 directory&lt;br /&gt;&lt;br /&gt; Note: 754 permissions for a directory are powerful enough to guard&lt;br /&gt;your directories from intruders with malicious intentions, that's why&lt;br /&gt;I used 754 as default,if yow want you can change it.&lt;br /&gt;&lt;br /&gt;Example: &lt;br /&gt;&lt;br /&gt;I logged in as king and created a temp file.&lt;br /&gt;&lt;br /&gt;$ whoami&lt;br /&gt;king&lt;br /&gt;$ pwd&lt;br /&gt;/home/project/&lt;br /&gt;$ touch temp; ls -l&lt;br /&gt;-rw-r--r-- 1 king  king           0 Mar 27 13:44 temp&lt;br /&gt;&lt;br /&gt;Now logged in as venu and try to delete temp file.&lt;br /&gt;&lt;br /&gt;$ whoami&lt;br /&gt;venu&lt;br /&gt;$ rm temp&lt;br /&gt;rm: remove write-protected regular empty file `temp'? Y&lt;br /&gt;$ ls temp&lt;br /&gt;ls: temp: No such file or directory&lt;br /&gt;&lt;br /&gt;So what happened? venu deleted file owned by king.&lt;br /&gt;&lt;br /&gt;Assign sticky bit to the project directory.As a owner of the directory&lt;br /&gt;or administrator.&lt;br /&gt;&lt;br /&gt;# chmod +t /home/project&lt;br /&gt;# ls -ld /home/project/&lt;br /&gt;drwxrwxr-t 15 root development 4096 Mar 27 13:46 /home/project/&lt;br /&gt;&lt;br /&gt; From the ls output above, you know the sticky bit is set because of&lt;br /&gt;the t in the third position of the other permission set,which replaces&lt;br /&gt;the x in the other permissions.&lt;br /&gt;&lt;br /&gt;Now repeat same steps again,then you get the following message:&lt;br /&gt;&lt;br /&gt;$ whoami&lt;br /&gt;venu&lt;br /&gt;$ ls -l temp&lt;br /&gt;-rw-r--r-- 1 king king 0 Mar 27 17:36 temp&lt;br /&gt;$ rm temp&lt;br /&gt;rm: remove write-protected regular empty file `temp'? y&lt;br /&gt;rm: cannot remove `temp': Operation not permitted&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Observation: Login as normal user and create a file.&lt;br /&gt;[venu@localhost ~]$ touch sample&lt;br /&gt;[venu@localhost ~]$ ls -l sample &lt;br /&gt;-rw-rw-r-- 1 venu venu 0 Dec 21 03:41 sample&lt;br /&gt;&lt;br /&gt;Now change permissions to 644&lt;br /&gt;&lt;br /&gt;[venu@localhost ~]$ chmod 644 sample &lt;br /&gt;[venu@localhost ~]$ ls -l sample &lt;br /&gt;-rw-r--r-- 1 venu venu 0 Dec 21 03:41 sample&lt;br /&gt;&lt;br /&gt;Now assign SUID permission.&lt;br /&gt;&lt;br /&gt;[venu@localhost ~]$ chmod u+s sample &lt;br /&gt;[venu@localhost ~]$ ls -l sample &lt;br /&gt;-rwSr--r-- 1 venu venu 0 Dec 21 03:41 sample&lt;br /&gt;&lt;br /&gt;After setting SUID, if you see 'S' then it means that the file has no &lt;br /&gt;executable permissions for that user.&lt;br /&gt;&lt;br /&gt;Now remove SUID permission and change permissions to 744. Then assign &lt;br /&gt;SUID permission. You should see a smaller 's' in the executable permi-&lt;br /&gt;ssion position.&lt;br /&gt;&lt;br /&gt;[venu@localhost ~]$ chmod u-s sample &lt;br /&gt;[venu@localhost ~]$ chmod 744 sample &lt;br /&gt;[venu@localhost ~]$ chmod u+s sample &lt;br /&gt;[venu@localhost ~]$ ls -l sample &lt;br /&gt;-rwsr--r-- 1 venu venu 0 Dec 21 03:41 sample&lt;br /&gt;&lt;br /&gt;Same is applicable for SGID and Stickybit.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Posted by venu k at 10:51 AM&lt;br /&gt;Labels: Article&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-590308651690282409?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/590308651690282409/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=590308651690282409" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/590308651690282409?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/590308651690282409?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2011/07/reblog-sticky-bit-suid-and-guid.html" title="REBLOG!!! Sticky bit, suid and guid" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;D0UESX8zfip7ImA9Wx9bGU4.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-1509074336704699866</id><published>2011-03-01T12:14:00.002+13:00</published><updated>2011-03-01T12:20:08.186+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-01T12:20:08.186+13:00</app:edited><title>Switch Google Desktop Search to search desktop by default</title><content type="html">I recently installed the latest version of Google Desktop.  I found, however, that when searching either from the sidebar searchbox or the Ctrl Ctrl popup box, GD would always select Search Web by default.&lt;br /&gt;&lt;br /&gt;This can now be changed using a small registry edit on Windows XP it is:&lt;br /&gt;HKEY_CURRENT_USER\Software\Google\Google Desktop\Deskbar\ change search_type to "Search Desktop"&lt;br /&gt;&lt;br /&gt;That's it.  Hopefully this will save some of you some time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-1509074336704699866?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/1509074336704699866/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=1509074336704699866" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1509074336704699866?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1509074336704699866?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2011/03/switch-google-desktop-search-to-search.html" title="Switch Google Desktop Search to search desktop by default" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEMAR3g4fyp7ImA9Wx9XEk0.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-2074376349478379090</id><published>2011-01-05T17:35:00.003+13:00</published><updated>2011-01-05T17:40:46.637+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-05T17:40:46.637+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="design principals" /><category scheme="http://www.blogger.com/atom/ns#" term="unix philosophy" /><category scheme="http://www.blogger.com/atom/ns#" term="software design" /><title>Some programming guidlines</title><content type="html">This is a very simple post. I found these principals very useful in solving a problem I have with a particular project I am currently working on...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Unix_philosophy"&gt;http://en.wikipedia.org/wiki/Unix_philosophy&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;1.Small is beautiful.&lt;br /&gt;2.Make each program do one thing well.&lt;br /&gt;3.Build a prototype as soon as possible.&lt;br /&gt;4.Choose portability over efficiency.&lt;br /&gt;5.Store data in flat text files.&lt;br /&gt;6.Use software leverage to your advantage.&lt;br /&gt;7.Use shell scripts to increase leverage and portability.&lt;br /&gt;8.Avoid captive user interfaces.&lt;br /&gt;9.Make every program a filter.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Have a read. It's well worth remembering these guidelines. Even if you have read them before, it might be useful to refresh your memmory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-2074376349478379090?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/2074376349478379090/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=2074376349478379090" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/2074376349478379090?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/2074376349478379090?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2011/01/some-programming-guidlines.html" title="Some programming guidlines" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEMNQHw_eSp7ImA9Wx9RE04.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-4698141050409864266</id><published>2010-12-15T03:18:00.001+13:00</published><updated>2010-12-15T03:21:31.241+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-15T03:21:31.241+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ssl" /><category scheme="http://www.blogger.com/atom/ns#" term="python web-service" /><title>Python Basic HTTPS webservice</title><content type="html">The basic webservice module in my previous posting does not support https or ssl encryption.&lt;br /&gt;&lt;br /&gt;Here is how I finally managed to work it out:&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;# Basic https web server&lt;br /&gt;&lt;br /&gt;import socket, ssl&lt;br /&gt;&lt;br /&gt;host = ''&lt;br /&gt;port = 8080&lt;br /&gt;&lt;br /&gt;sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;br /&gt;sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)&lt;br /&gt;sock.bind((host, port))&lt;br /&gt;sock.listen(1)&lt;br /&gt;&lt;br /&gt;while 1:&lt;br /&gt;    osock, caddr = sock.accept()&lt;br /&gt;    csock = ssl.wrap_socket(osock,&lt;br /&gt;                                server_side=True,&lt;br /&gt;                                certfile="servercert.cer",&lt;br /&gt;                                keyfile="serverkey.key",&lt;br /&gt;                                ssl_version=ssl.PROTOCOL_SSLv23)&lt;br /&gt;                                &lt;br /&gt;    cfile = csock.makefile('rw', 0)&lt;br /&gt;&lt;br /&gt;    # Protocol exchange - read request&lt;br /&gt;    msg = "GO AWAY!"&lt;br /&gt;    while 1:&lt;br /&gt;        line = cfile.readline().strip()&lt;br /&gt;        if line == "GET /echotest HTTP/1.1":&lt;br /&gt;            msg = "ECHOTEST OK"&lt;br /&gt;        if line == '':&lt;br /&gt;            cfile.write("HTTP/1.0 200 OK\n\n")&lt;br /&gt;            cfile.write("&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Eh?&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;")&lt;br /&gt;            cfile.write("&amp;lt;h1&amp;gt;%s&amp;lt;/h1&amp;gt;" % msg)&lt;br /&gt;            cfile.close()&lt;br /&gt;            csock.close()&lt;br /&gt;            osock.close()&lt;br /&gt;            break&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-4698141050409864266?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/4698141050409864266/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=4698141050409864266" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4698141050409864266?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4698141050409864266?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/12/python-basic-https-webservice.html" title="Python Basic HTTPS webservice" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0UAQXw6eSp7ImA9Wx5aEUQ.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-3221041641936240519</id><published>2010-11-08T17:36:00.005+13:00</published><updated>2010-11-08T17:40:40.211+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-08T17:40:40.211+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pana" /><category scheme="http://www.blogger.com/atom/ns#" term="Fedora 14" /><title>Compile Pana (Amarok 1.4 clone) on Fedora 14 x86_64</title><content type="html">After meeting all the various dependencies, I had to make one small actual code change to the source code.  I would have liked to submit it on the Pana website but could not find a way to do that.&lt;br /&gt;&lt;br /&gt;Anyway here is the patch.&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;[dave@fedora junk]$ diff [source tree]/pana/src/osd.h [source tree]/pana/src/osd.h.original&lt;br /&gt;40c40&lt;br /&gt;&amp;lt;         void show( const QString &amp;text, QImage newImage = QImage() );&lt;br /&gt;---&lt;br /&gt;&amp;gt;         void show( const QString &amp;text, QImage newImage = QImage::QImage() );&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-3221041641936240519?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/3221041641936240519/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=3221041641936240519" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/3221041641936240519?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/3221041641936240519?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/11/compile-pana-amarok-14-clone-on-fedora.html" title="Compile Pana (Amarok 1.4 clone) on Fedora 14 x86_64" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DE4DSXkyeyp7ImA9Wx5UEEg.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-3321240928575817052</id><published>2010-10-14T21:04:00.007+13:00</published><updated>2010-10-15T00:49:38.793+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-15T00:49:38.793+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gpg" /><category scheme="http://www.blogger.com/atom/ns#" term="mod_perl" /><category scheme="http://www.blogger.com/atom/ns#" term="gnupg" /><category scheme="http://www.blogger.com/atom/ns#" term="python web-service" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="Apache" /><category scheme="http://www.blogger.com/atom/ns#" term="mod_python" /><category scheme="http://www.blogger.com/atom/ns#" term="pgp" /><title>Python webservice that executes local commands</title><content type="html">There are a few different options when it comes to managing server-side scripting on a web site.  Usually folks use php or perl and even python in many occasions.&lt;br /&gt;&lt;br /&gt;This blog post is about using python to execute code locally on the server in response to http GET requests.&lt;br /&gt;&lt;br /&gt;So far you are thinking so what?  You are already crafting your comment and it is saying something like, "Google mod_python" or "Google mod_perl".  You are right, the best way to do CGI is via mod_perl, mod_php or mod_perl.  The problem is user access and chroot.&lt;br /&gt;&lt;br /&gt;Apache will execute server side scripts as the user / group defined in the main httpd.conf.  In my case: apache / apache.&lt;br /&gt;Apache will also assume a document root of /var/www/ for scripts (on a Centos 5.5 box) even if the userdir module is in use.&lt;br /&gt;&lt;br /&gt;My problem was: How to get apache to execute scripts as dave:dave on doc root = /home/dave/.  It was critical to get this working because the scripts in question interact with the .gnupg/pubkeyring and .gnupg/seckeyring files under /home/dave/.gnupg/.&lt;br /&gt;&lt;br /&gt;Basically, I was making some kind of web based PGP key server.  A web based gui for remote users to manage keys.&lt;br /&gt;&lt;br /&gt;In the end I settled for python and the BaseHTTPServer.&lt;br /&gt;&lt;br /&gt;First of all a simple class that will accept a shell command, execute it and return the stdout.&lt;br /&gt;&lt;br /&gt;&lt;pre class=prettyprint&gt;&lt;br /&gt;import popen2&lt;br /&gt;&lt;br /&gt;class MyShellCommand:&lt;br /&gt; &lt;br /&gt; """execute a command, capture stdout and return it."""&lt;br /&gt; def __callShellCmd(self, cmd):&lt;br /&gt;  &lt;br /&gt;  stdout, stdin = popen2.popen2(command)&lt;br /&gt;  data = ""&lt;br /&gt;  while True:&lt;br /&gt;   c = stdout.read(1)&lt;br /&gt;   if( c ):&lt;br /&gt;    data += c&lt;br /&gt;   else:&lt;br /&gt;    break&lt;br /&gt;  return data&lt;br /&gt; &lt;br /&gt; """concrete example"""&lt;br /&gt; def getPublicGPGKey(self, keyid):&lt;br /&gt;  &lt;br /&gt;  """TODO: Add logic to validate key id..."""&lt;br /&gt;  command = "gpg -a --export '%s'" % keyid&lt;br /&gt;  return self.__callShellCmd(command)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now that we have a utility to retrieve public keys from the gpg keyring, lets call it from a webservice that is owned and operated by user:group, dave:dave.&lt;br /&gt;&lt;br /&gt;&lt;pre class=prettyprint&gt;&lt;br /&gt;import MyShellCommand&lt;br /&gt;import time&lt;br /&gt;import BaseHTTPServer, cgi&lt;br /&gt;&lt;br /&gt;"""Configure host ip and port to listen on.  Use high port for non root users."""&lt;br /&gt;HOST_NAME = '127.0.0.1'&lt;br /&gt;PORT_NUMBER = 8080 &lt;br /&gt;&lt;br /&gt;class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):&lt;br /&gt;&lt;br /&gt; def do_HEAD(s):&lt;br /&gt;  s.send_response(200)&lt;br /&gt;  s.send_header("Content-type", "text/html")&lt;br /&gt;  s.end_headers()&lt;br /&gt;&lt;br /&gt; def do_GET(s):&lt;br /&gt;  s.send_response(200)&lt;br /&gt;  s.send_header("Content-type", "text/html")&lt;br /&gt;  s.end_headers()&lt;br /&gt;&lt;br /&gt;  """Get the path and find the parameters"""&lt;br /&gt;  path, query_string = s.path.split('?', 1)&lt;br /&gt;  params = dict(cgi.parse_qsl(query_string))&lt;br /&gt;  &lt;br /&gt;  """create a shell object"""&lt;br /&gt;  shell = MyShellCommand()&lt;br /&gt;  &lt;br /&gt;  """Validate the call being made"""&lt;br /&gt;  if path == '/publickey':&lt;br /&gt;   """Validate the parameters"""&lt;br /&gt;   if params.has_key('id'):&lt;br /&gt;    s.wfile.write('%s' % shell.getPublicGPGKey(params['id']))&lt;br /&gt;    &lt;br /&gt;   """I dont like descriptive errors."""&lt;br /&gt;   else: s.wfile.write('An error occurred.')&lt;br /&gt;  else: s.wfile.write('An error occurred.')&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt; server_class = BaseHTTPServer.HTTPServer&lt;br /&gt; httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)&lt;br /&gt; print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)&lt;br /&gt; try:&lt;br /&gt;  httpd.serve_forever()&lt;br /&gt; except KeyboardInterrupt:&lt;br /&gt;  pass&lt;br /&gt; httpd.server_close()&lt;br /&gt; print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you execute the above script, you will have a working webservice that responds nicely to only one specific set of GET data.  Call it with a URL like this:&lt;br/&gt;&lt;br /&gt;&lt;pre class=prettyprint&gt;&lt;br /&gt;http://127.0.0.1:8080/publickey?id=mykeyname&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-3321240928575817052?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/3321240928575817052/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=3321240928575817052" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/3321240928575817052?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/3321240928575817052?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/10/python-webservice-that-executes-local.html" title="Python webservice that executes local commands" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0cHSXc4cSp7ImA9Wx5WGU8.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-1251198806890138118</id><published>2010-10-01T23:18:00.003+13:00</published><updated>2010-10-01T23:30:38.939+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-01T23:30:38.939+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="active directory" /><category scheme="http://www.blogger.com/atom/ns#" term="php" /><category scheme="http://www.blogger.com/atom/ns#" term="ldap" /><category scheme="http://www.blogger.com/atom/ns#" term="authentication" /><title>Use PHP to perform an LDAP Bind to Windows Active Directory for User Authentication</title><content type="html">&lt;p&gt;This example shows some basic LDAP bind lookups on a Windows 2003 active directory server.&lt;/p&gt;&lt;p&gt;The sequence is: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Connect &lt;/li&gt;&lt;li&gt;Bind using privileged user &lt;/li&gt;&lt;li&gt;search for 'dn' of supplied credentials&lt;/li&gt;&lt;li&gt;re-bind using this dn and password of supplied credentials&lt;/li&gt;&lt;li&gt;unbind&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The per-requisite is that php_ldap modules are loaded and compiled.  These are fairly standard now days.  In fedora it was just a matter of executing:&lt;/p&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;# yum install php-ldap&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Anyway:  Here is the example.  It's farily well commented so should be a simple matter to make work in your own environment.&lt;/p&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;// example.php&lt;br /&gt;//&lt;br /&gt;// David Latham @ 2010&lt;br /&gt;// david-latham.blogspot.com&lt;br /&gt;//&lt;br /&gt;// This code cannot be executed on the same server as AD is installed on!!!&lt;br /&gt;//&lt;br /&gt;// Active Directory has an Organizational Unit of "_Test_Users" with 3 users loaded&lt;br /&gt;// into it.&lt;br /&gt;// user1 &lt;user1@example.local&gt; | User One&lt;br /&gt;// user2 &lt;user2@example.local&gt; | User Two&lt;br /&gt;//    ldapbind &lt;ldapbind@example.local&gt; | ldap bind&lt;br /&gt;//&lt;br /&gt;// execute with php -q example.php&lt;br /&gt;    &lt;br /&gt;// credentials to test&lt;br /&gt;$user='user2@example.local';&lt;br /&gt;// user='user2'; //Use this one to test binding without an email address.&lt;br /&gt;$pass='2wsx#EDC';&lt;br /&gt;&lt;br /&gt;// AD server details&lt;br /&gt;$ldap_server = "192.168.122.231";&lt;br /&gt;$dn = "OU=_Test_Users,DC=example,DC=local";&lt;br /&gt;&lt;br /&gt;// Connect&lt;br /&gt;$ad = ldap_connect($ldap_server);  //Must be a real active directory server&lt;br /&gt;     //(WIN2003 used in this example)&lt;br /&gt;&lt;br /&gt;// Set some variables&lt;br /&gt;ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3);&lt;br /&gt;ldap_set_option($ad, LDAP_OPT_REFERRALS, 0);&lt;br /&gt;&lt;br /&gt;// Bind to the ldap directory.&lt;br /&gt;// Here we are binding using a fixed user who has privileges to bind to the&lt;br /&gt;// active directory.  This user also has a fixed password.  It can not change&lt;br /&gt;// otherwise this script will break.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$bd = @ldap_bind($ad,"ldap user","pa$$word")&lt;br /&gt; or die("Couldn't bind to AD!");&lt;br /&gt;&lt;br /&gt;// Search the directory for a distinguished name (dn) using the supplied&lt;br /&gt;// credentials.&lt;br /&gt;//&lt;br /&gt;// If $user is an email address then use 'mail' otherwise use 'sAMAccountName'&lt;br /&gt;&lt;br /&gt;if( strpos($user, '@') &amp;gt; 0 ) {&lt;br /&gt; $field='mail';&lt;br /&gt;} else {&lt;br /&gt; $field='sAMAccountName';&lt;br /&gt;}&lt;br /&gt;echo "Searching AD using ...".$field."\n";&lt;br /&gt;&lt;br /&gt;$result = @ldap_search($ad, $dn, "(".$field."=".$user.")", array('dn'));&lt;br /&gt;&lt;br /&gt;// Create result set&lt;br /&gt;$entries = @ldap_get_entries($ad, $result);&lt;br /&gt;&lt;br /&gt;// Show an array of result&lt;br /&gt;print_r($entries);&lt;br /&gt;&lt;br /&gt;// If we have a result then we should 're-bind' using the destinguished name found&lt;br /&gt;// in the search.&lt;br /&gt;if ( $entries[0] ) {&lt;br /&gt; if(@ldap_bind($ad, $entries[0]['dn'], $pass)) {&lt;br /&gt;  // If bind was successful then show some data.  This is user&lt;br /&gt;  // authentication success.&lt;br /&gt;  echo "found: ".$entries[0]['dn'];&lt;br /&gt; } else {&lt;br /&gt;  // Bind failed so this would equate to user authentication failure.&lt;br /&gt;  echo "Failed to bind.";&lt;br /&gt; }&lt;br /&gt;} else { &lt;br /&gt; // Failure to search would indicate a problem with your $dn variable.&lt;br /&gt; echo "failed to search";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//never forget to unbind!&lt;br /&gt;ldap_unbind($ad);&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;the result might look something like this:&lt;/p&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;[dave@fedora php-ldap]$ php -q example.php &lt;br /&gt;Searching AD using ...mail&lt;br /&gt;Array&lt;br /&gt;(&lt;br /&gt;    [count] =&amp;gt; 1&lt;br /&gt;    [0] =&amp;gt; Array&lt;br /&gt;        (&lt;br /&gt;            [count] =&amp;gt; 0&lt;br /&gt;            [dn] =&amp;gt; CN=user2,OU=_Test_Users,DC=example,DC=local&lt;br /&gt;        )&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;found: CN=user2,OU=_Test_Users,DC=example,DC=local&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Have fun authenticating your users against your work active directory.  You will:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Please your security manager&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Avoid the headache of managing passwords password compliance&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Write safer applications in terms of locking them down&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Feel good about yourself&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-1251198806890138118?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/1251198806890138118/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=1251198806890138118" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1251198806890138118?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1251198806890138118?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/10/use-php-to-perform-ldap-bind-to-windows.html" title="Use PHP to perform an LDAP Bind to Windows Active Directory for User Authentication" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkQER3gyeSp7ImA9WxFVFkU.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-288990455498271692</id><published>2010-06-16T21:06:00.002+12:00</published><updated>2010-06-16T21:25:06.691+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-16T21:25:06.691+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="logging" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="Images in wxPython" /><category scheme="http://www.blogger.com/atom/ns#" term="wxPython" /><title>Images from web in python gui</title><content type="html">I have an application that I use to monitor data produced by a webservice.  This webservice produces a new image ( a .png graph to be precise ) every 15 seconds.  Basically I have four cron jobs that execute every minute.  Three of these are configured to sleep for 15s, 30s and 45s respectivley.  So that's one way to make cron do stuff more often than once a minute.&lt;br /&gt;&lt;br /&gt;Anyway, I have been using a web browser and some fancy ajax type functions to continuously display this graph and some other JSON data from the webserver every 15 seconds forever.  We have a group of people who have the job of watching my graphs and data among a whole bunch of other stuff in case they might provide some alert to a problem.&lt;br /&gt;&lt;br /&gt;Anyway, I have been wondering, of late, about the reliablility of using a web browser for monitoring.  The web browser is not refreshing itself and so I am a little worried that it just kind of get's stuck at times.  I think it looses the AJAXIAN plot so to speak.  This is why I started making a python gui using the following python modules:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;httplib&lt;/li&gt;&lt;li&gt;json&lt;/li&gt;&lt;li&gt;urrlib&lt;/li&gt;&lt;li&gt;wx&lt;/li&gt;&lt;li&gt;logging&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I will only show three classes here for reference purposes.&lt;br /&gt;&lt;br /&gt;There is also a threading module required.  This bit of handy code is at the bottom and I must apologies to the author of this code as I failed to take a note of his name / URL and so can not reference the source.&lt;br /&gt;&lt;br /&gt;This is the Web client class that I use to retrieve the http / JSON content and the image content from my webserver.&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;#!/usr/bin/env python&lt;br /&gt;&lt;br /&gt;import httplib&lt;br /&gt;import urllib&lt;br /&gt;&lt;br /&gt;class HTTP_Client(httplib.HTTPConnection):&lt;br /&gt; &lt;br /&gt; def __init__(self, url):&lt;br /&gt;  httplib.HTTPConnection.__init__(self, url)&lt;br /&gt;  &lt;br /&gt; &lt;br /&gt; def getPage(self, page):&lt;br /&gt;  self.request("GET", "/%s" % page)&lt;br /&gt;  r = self.getresponse()&lt;br /&gt;  data = r.read()&lt;br /&gt;  if r.status == 200 and r.reason == "OK":&lt;br /&gt;   return urllib.base64(data)&lt;br /&gt;  else:&lt;br /&gt;   return "E Fetching %s: %s %s" % (page, r.status, r.reason)&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt; hc = HttpClient("www.python.org")&lt;br /&gt; print hc.getPage("parrot.spam")&lt;br /&gt; print hc.getPage("index.html")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is an example of how to display an image on a panel using the wx gui toolkit.  I think this is a mostly coding by google but it's not a big leap to make it useful.  I believe my real program uses the _Image.SetBitmap(_Bitmap) method to update the bitmap.&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;#!/usr/bin/env python&lt;br /&gt;&lt;br /&gt;import urllib&lt;br /&gt;import wx&lt;br /&gt;import cStringIO&lt;br /&gt;&lt;br /&gt;class Panel1(wx.Panel):&lt;br /&gt; """ class Panel1 creates a panel with an image on it, inherits wx.Panel"""&lt;br /&gt; def __init__(self, parent, id):&lt;br /&gt;  wx.Panel.__init__(self, parent, id)&lt;br /&gt;  try:&lt;br /&gt;   url = "http://www.photoshopsupport.com/photoshop-blog/07/2008/photoshop-blog/istockphoto-free-photo-credits.jpg"&lt;br /&gt;   data = urllib.urlopen(url).read()&lt;br /&gt;   stream = cStringIO.StringIO(data)&lt;br /&gt;   bmp = wx.BitmapFromImage( wx.ImageFromStream( stream ) )&lt;br /&gt;   wx.StaticBitmap(self, -1, bmp, (5,5))&lt;br /&gt;  except IOError:&lt;br /&gt;   print "Image file %s is not found" % url&lt;br /&gt;   raise SystemExit&lt;br /&gt;&lt;br /&gt;app = wx.PySimpleApp()&lt;br /&gt;frame1 = wx.Frame(None, -1, "An image on a panel", size=(400,300))&lt;br /&gt;Panel1(frame1, -1)&lt;br /&gt;frame1.Show(1)&lt;br /&gt;app.MainLoop()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is the logger object.  It sets up a logger and a formatter as well as a few actual logging methods.  These just expose the internal methods of the logging module provided in default python.&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;#!/usr/bin/env python&lt;br /&gt;import logging&lt;br /&gt;import logging.handlers&lt;br /&gt;&lt;br /&gt;class CDLogger(object):&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.log = logging.getLogger('cdBurner')&lt;br /&gt;        self.log.setLevel(logging.INFO)&lt;br /&gt;&lt;br /&gt;        hand = logging.FileHandler("cdburner.log", 'a')&lt;br /&gt;        form = logging.Formatter("%(asctime)s %(levelname)-10s %(message)s")&lt;br /&gt;&lt;br /&gt;        hand.setFormatter(form)&lt;br /&gt;        self.log.addHandler(hand)&lt;br /&gt;&lt;br /&gt;    def info(self, message):&lt;br /&gt;        self.log.info(message)&lt;br /&gt;&lt;br /&gt;    def debug(self, message):&lt;br /&gt;        self.log.debug(message)&lt;br /&gt;        &lt;br /&gt;    def warning(self, message):&lt;br /&gt;        self.log.warning(message)&lt;br /&gt;&lt;br /&gt;    def error(self, message):&lt;br /&gt;        self.log.error(message)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here is the threading module that is used to execute the timer.&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;   Code on my laptop so I need to get it from the laptop.  Will do this later.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-288990455498271692?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/288990455498271692/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=288990455498271692" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/288990455498271692?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/288990455498271692?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/06/images-from-web-in-python-gui.html" title="Images from web in python gui" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUEHRHwzeyp7ImA9WxFSGEw.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-439432984435980069</id><published>2010-04-21T13:30:00.004+12:00</published><updated>2010-04-21T13:33:55.283+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-21T13:33:55.283+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Pana" /><category scheme="http://www.blogger.com/atom/ns#" term="amarok 1.4" /><category scheme="http://www.blogger.com/atom/ns#" term="Music Player" /><title>Amarok Script to Pana Script converter</title><content type="html">I use &lt;a href="http://pana.bunnies.net"&gt;Pana &lt;/a&gt;now in favour of Amarok 1.4.  Pana is under active development and includes a fix for the cover fetcher that stopped working some time ago.&lt;br /&gt;&lt;br /&gt;The next step was to find a way to port the amarok scripts over to Pana.  This is easily acheived ( for replay_gain ) anyway with this script:&lt;br /&gt;&lt;br /&gt;Source: &lt;a href="http://air.elementfx.com/phpBB3/viewtopic.php?f=5&amp;amp;t=3#p3"&gt;http://air.elementfx.com/phpBB3/viewtopic.php?f=5&amp;amp;t=3#p3&lt;/a&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;#! /bin/bash&lt;br /&gt;FILE=$1&lt;br /&gt;FILENAME=`echo ${FILE##*/}`&lt;br /&gt;mkdirerr=$(mktemp)&lt;br /&gt;mkdir $FILENAME".tmp" 2&gt; $mkdirerr&lt;br /&gt;if [ -n "`cat $mkdirerr`" ]; then&lt;br /&gt;  cat $mkdirerr&lt;br /&gt;  exit&lt;br /&gt;fi&lt;br /&gt;cd $FILENAME".tmp"&lt;br /&gt;echo "Extracting files to $FILENAME.tmp/ ..."&lt;br /&gt;tar jxvf $FILE &amp;&gt; /dev/null&lt;br /&gt;&lt;br /&gt;currentdir=`pwd`&lt;br /&gt;&lt;br /&gt;for (( i=0 ; $i &lt; `find  . -depth -type d | wc -l` ; i=$(( $i+1 )) ));&lt;br /&gt;do&lt;br /&gt;  directory[$i]=`find  . -depth -type d | head -$(( $i+1 )) | tail -1`&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;for (( i=0 ; $i &lt; ${#directory[@]} ; i=$(( $i+1 )) )); do&lt;br /&gt;  cd ${directory[$i]}&lt;br /&gt;  for file in `find  . -depth -maxdepth 1 -type f ` ; do&lt;br /&gt;      echo "Changing "$file&lt;br /&gt;      NEWNAME=`echo $file | sed 's/amarok/pana/g'`&lt;br /&gt; &lt;br /&gt;      sed -i 's/amarok/pana/g' $file&lt;br /&gt;      sed -i 's/Amarok/Pana/g' $file&lt;br /&gt;      &lt;br /&gt;      if [ "$file" != "$NEWNAME" ]; then&lt;br /&gt; echo "Renaming file $file to $NEWNAME"&lt;br /&gt; mv $file $NEWNAME&lt;br /&gt;      fi&lt;br /&gt;  done&lt;br /&gt;&lt;br /&gt;  cd $currentdir&lt;br /&gt;  if [ -z "`echo ${directory[$i]%/*} | grep 'amarok'`" ] &amp;&amp; [ "${directory[$i]}" != "." ]; then &lt;br /&gt;    &lt;br /&gt;    NEWDIRNAME=`echo ${directory[$i]##*/}`&lt;br /&gt;    NEWDIRNAME=`echo ${NEWDIRNAME} | sed 's/amarok/pana/g'`&lt;br /&gt;    NEWDIRNAME=`echo ${NEWDIRNAME} | sed 's/Amarok/Pana/g'`&lt;br /&gt;    NEWDIRNAME=${directory[$i]%/*}"/"$NEWDIRNAME&lt;br /&gt;    echo "Renaming directory ${directory[$i]} to ${NEWDIRNAME}"&lt;br /&gt;    mv ${directory[$i]} ${NEWDIRNAME}&lt;br /&gt;  fi&lt;br /&gt;  echo "Finished folder ${directory[$i]}"&lt;br /&gt;  echo ""&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;NEWFILENAME=$FILENAME&lt;br /&gt;NEWFILENAME=`echo ${NEWFILENAME} | sed 's/amarok/pana/g'`&lt;br /&gt;NEWFILENAME=`echo ${NEWFILENAME} | sed 's/Amarok/Pana/g'`&lt;br /&gt;&lt;br /&gt;echo "Recompressing files into $NEWFILENAME"&lt;br /&gt;tar jcvf $NEWFILENAME `ls` &amp;&gt; /dev/null&lt;br /&gt;mv $NEWFILENAME ..&lt;br /&gt;cd ..&lt;br /&gt;&lt;br /&gt;echo "rm -f -r ${FILENAME}.tmp/"&lt;br /&gt;# rm -f -r "${FILENAME}.tmp/"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once you have done all this, then just import the new Pana version of your script using the Pana Script Manager.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-439432984435980069?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/439432984435980069/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=439432984435980069" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/439432984435980069?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/439432984435980069?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/04/amarok-script-to-pana-script-converter.html" title="Amarok Script to Pana Script converter" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEAGSXw5eip7ImA9WxBaGU4.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-5265623061867368639</id><published>2010-03-30T19:51:00.004+13:00</published><updated>2010-03-30T20:05:28.222+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-30T20:05:28.222+13:00</app:edited><title>Howto Install Sun JDK with EE into Ubuntu 10.4</title><content type="html">This tutorial is for Ubuntu 10.4 Beta.  10.4 full release is only next month.  Well here you go.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Download Java for linux from the Oracle Sun website.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Download the 32bit version of libstdc++5 from here: &lt;/li&gt;&lt;/ul&gt;&lt;pre class='prettyprint'&gt;http://packages.debian.org/lenny/amd64/libstdc++5/download&lt;/pre&gt; Make sure you get the 32 bit version.  It would seem that the installer for Java requires that you have a 32bit version of this library installed.  I think this is for the installer GUI only.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Extract the library like this:&lt;/li&gt;&lt;/ul&gt;&lt;pre class='prettyprint'&gt;dpkg-deb -x libstdc++5_3.3.6-18_i386.deb libstdc++5&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Copy the library into /usr/lib32&lt;/li&gt;&lt;/ul&gt;&lt;pre class='prettyprint'&gt;sudo cp libstdc++5/usr/lib/libstdc++.so.5.0.7 /usr/lib32/&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Create a simlink to the file in /usr/lib32/&lt;/li&gt;&lt;/ul&gt; &lt;pre class='prettyprint'&gt;sudo ln -s libstdc++.so.5.0.7 libstdc++.so.5&lt;/pre&gt;&lt;br /&gt;Now you can install java like this:&lt;br /&gt;&lt;pre class='prettyprint'&gt;./java_ee_sdk-5_08-jdk-6u18-linux.bin &lt;/pre&gt;All done!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-5265623061867368639?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/5265623061867368639/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=5265623061867368639" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/5265623061867368639?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/5265623061867368639?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/03/howto-install-sun-jdk-with-ee-into.html" title="Howto Install Sun JDK with EE into Ubuntu 10.4" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;CEQNQXo_eCp7ImA9WxBaF0g.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-6045793562767715052</id><published>2010-03-28T17:31:00.002+13:00</published><updated>2010-03-28T17:59:50.440+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-28T17:59:50.440+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="VirtualBox" /><category scheme="http://www.blogger.com/atom/ns#" term="kvm" /><category scheme="http://www.blogger.com/atom/ns#" term="Virtualisation" /><title>VirtualBox - AMD-V and KVM</title><content type="html">I usually use the KVM on my linux host for Virtualisation.  It's default with Fedora and I know it.  Usually ...&lt;br /&gt;&lt;br /&gt;Today I thought I would try the Ubuntu 10.4 Beta 1 on VirtualBox.  I installed the latest VirtualBox ( version 3.1.6 ) and then had a crack at installing the Ubuntu 10.4 64bit.  Of course an error came up saying that while AMD-v was enabled, it was not operational.  After much googleling about, I found that the KVM modules were causing VirtualBox issues with access.&lt;br /&gt;&lt;br /&gt;So a quick "rmmod kvm_amd" and "rmmod kvm" fixed it.&lt;br /&gt;&lt;br /&gt;Next time I want to use KVM, I will need to re-enable these with, I suppose, a quick, "insmod kvm_amd" and "insmod kvm"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-6045793562767715052?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/6045793562767715052/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=6045793562767715052" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/6045793562767715052?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/6045793562767715052?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/03/virtualbox-amd-v-and-kvm.html" title="VirtualBox - AMD-V and KVM" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;D0MCSH4zfSp7ImA9WxBUGE4.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-6727196093033135849</id><published>2010-03-03T22:38:00.005+13:00</published><updated>2010-03-06T13:31:09.085+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-06T13:31:09.085+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Fedora" /><category scheme="http://www.blogger.com/atom/ns#" term="new zealand" /><category scheme="http://www.blogger.com/atom/ns#" term="dvbt" /><category scheme="http://www.blogger.com/atom/ns#" term="mplayer" /><category scheme="http://www.blogger.com/atom/ns#" term="freeview" /><title>Freeview ( DVB-T ) Linux / Fedora in New Zealand.</title><content type="html">I dont have anything fancy other than a fairly good CPU. Its an AMD Athlon(tm) 64 X2 Dual Core Processor 4000+.&lt;br /&gt;&lt;br /&gt;I have an avermedia A800 DVB-T tuner from www.nicegear.co.nz&lt;br /&gt;&lt;br /&gt;I DO NOT have a VDPAU enabled graphics card which can do on board H.264 decoding for me.  That will be soon though.  Need to save a bit of cash first.&lt;br /&gt;&lt;br /&gt;I am in New Zealand so there are some special areas of concern that needed to be addressed.&lt;br /&gt;&lt;br /&gt;Here is a very brief rundown of how i get free view working in my linux.&lt;br /&gt;&lt;br /&gt;**** COMMENT ****&lt;br /&gt;Here is a great website.  I use this now for post processing.&lt;br /&gt;http://quadpoint.org/projects/simplerip#audio_and_video_bitrates&lt;br /&gt;&lt;br /&gt;On my fedora system i have to change -oac copy to -oac pcm and of course I still use my compiled mplayer and the -lavdopts fast:threads=2 option on the 3 lines.&lt;br /&gt;&lt;br /&gt;Steps to get Mplayer working.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;******************** ~./mplayer/channels.conf **********************************&lt;br /&gt;********************************************************************************&lt;br /&gt;&lt;br /&gt;TV ONE:538000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:250+100:300:1200&lt;br /&gt;TV2:538000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:251+101:301+1010:1201&lt;br /&gt;TVNZ 6:538000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:252+102:302+1020:1202&lt;br /&gt;TVNZ 7:538000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:253+103:303+1025:1203&lt;br /&gt;TV3:570000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:450+300:410:1300&lt;br /&gt;C4:570000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:451+301:401:1301&lt;br /&gt;TV3 PLUS1:570000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:452+302:402:1302&lt;br /&gt;Maori Television:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:550+200:600:1400&lt;br /&gt;Parliament TV :666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:551+201:601:1401&lt;br /&gt;Test Channel:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:552+202:602:1402&lt;br /&gt;ChineseTV:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:553+203:603:1403&lt;br /&gt;PRIME:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:554+204:604:1404&lt;br /&gt;Reserved 6KSD:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:0:605:1405&lt;br /&gt;Freeview | HD:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:556+206:606:1406&lt;br /&gt;Radio NZ National:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:0+220:620:2000&lt;br /&gt;Radio NZ Concert:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:0+221:621:2001&lt;br /&gt;BaseFM:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:559+209:609:2002&lt;br /&gt;tvCentral:666000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:560+210:610:1408&lt;br /&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;******************** The DEVEL FILES I INSTALLED ( RELEVANT ONES ) *************&lt;br /&gt;********************************************************************************&lt;br /&gt;&lt;br /&gt;Feb 03 21:38:08 Installed: alsa-lib-devel-1.0.22-2.fc12.x86_64&lt;br /&gt;Feb 04 14:32:30 Installed: xorg-x11-drv-nvidia-devel-190.53-1.fc12.x86_64&lt;br /&gt;Feb 04 14:37:13 Installed: gstreamer-devel-0.10.25.1-3.fc12.x86_64&lt;br /&gt;Feb 04 14:37:15 Installed: gstreamer-plugins-base-devel-0.10.25.1-2.fc12.x86_64&lt;br /&gt;Feb 04 14:37:16 Installed: gstreamer-plugins-bad-devel-0.10.17-2.fc12.x86_64&lt;br /&gt;Feb 04 14:37:17 Installed: gstreamer-plugins-good-devel-0.10.17-4.fc12.x86_64&lt;br /&gt;Feb 04 14:42:59 Installed: libvdpau-devel-0.3-1.fc12.x86_64&lt;br /&gt;Feb 04 15:02:07 Installed: x264-devel-0.0.0-0.26.20091026gitec46ace7.fc12.x86_64&lt;br /&gt;Feb 04 15:52:22 Installed: libXvMC-devel-1.0.4-8.fc12.x86_64&lt;br /&gt;Feb 18 17:46:24 Installed: kernel-devel-2.6.31.12-174.2.19.fc12.x86_64&lt;br /&gt;Feb 23 21:53:46 Installed: lame-devel-3.98.2-3.fc11.x86_64&lt;br /&gt;Feb 23 21:53:47 Installed: xvidcore-devel-1.2.1-3.fc12.x86_64&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Make sure you also have the relevant libraries that go with these development&lt;br /&gt;packages.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;******************* COMPILE MPLAYER WITH MULTI THREADING ***********************&lt;br /&gt;********************************************************************************&lt;br /&gt;&lt;br /&gt;grab mplayer svn&lt;br /&gt;svn checkout svn://svn.mplayerhq.hu/mplayer/trunk mplayer&lt;br /&gt;&lt;br /&gt;now get ffmpeg-mt&lt;br /&gt;git clone git://gitorious.org/ffmpeg/ffmpeg-mt.git&lt;br /&gt;&lt;br /&gt;replace the libav* folders in mplayer-svn with the libav* folders in ffmpeg-mt&lt;br /&gt;&lt;br /&gt;cd mplayer&lt;br /&gt;./configure&lt;br /&gt;*** FOR 64 BIT FEDORA use ./configure --libdir=/usr/lib64&lt;br /&gt;&lt;br /&gt;*** WHEN this completes have a look to see which modules are compiled in.  The&lt;br /&gt;*** video out, video codecs, audio out and audio codecs will be listed.&lt;br /&gt;*** If you are missing any you need or think you might need then install the&lt;br /&gt;*** relevant library and -devel packages and run ./configure again.&lt;br /&gt;&lt;br /&gt;make&lt;br /&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;******************* RESULTS FROM MY ./configure ********************************&lt;br /&gt;********************************************************************************&lt;br /&gt;&lt;br /&gt;  Enabled optional drivers:&lt;br /&gt;    Input: dvdnav(internal) ftp pvr tv-v4l2 tv-v4l tv libdvdcss(internal) dvdread(internal) vcd dvb network &lt;br /&gt;    Codecs: xvid libavcodec(internal) real xanim faad2(internal) libmpeg2(internal) mp3lib(internal) tremor(internal) &lt;br /&gt;    Audio output: alsa oss v4l2 mpegpes(dvb) &lt;br /&gt;    Video output: v4l2 pnm jpeg matrixview opengl mpegpes(dvb) fbdev xvidix cvidix vdpau xv x11 xover yuv4mpeg md5sum tga &lt;br /&gt;&lt;br /&gt;  Disabled optional drivers:&lt;br /&gt;    Input: vstream radio tv-dshow live555 nemesi cddb cdda smb &lt;br /&gt;    Codecs: libschroedinger libdirac x264 libdv libopencore_amrwb libopencore_amrnb qtx win32 faac musepack libdca liba52 libtheora speex toolame twolame libmad liblzo gif OpenJPEG &lt;br /&gt;    Audio output: sun openal jack pulse nas esd arts ivtv dxr2 sdl &lt;br /&gt;    Video output: zr zr2 ivtv dxr3 dxr2 sdl vesa gif89a svga caca aa ggi xmga mga winvidix 3dfx dga xvmc dfbmga directfb bl xvr100 tdfx_vid wii s3fb tdfxfb &lt;br /&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;******************* Here is a link to a person who did it in mandriva **********&lt;br /&gt;********************************************************************************&lt;br /&gt;http://blog.linuxbox.co.nz/2008/08/hauppauge-wintv-hvr900-on-mandriva.html&lt;br /&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;******************* Various mplayer commands ***********************************&lt;br /&gt;********************************************************************************&lt;br /&gt;&lt;br /&gt;RECORD A CHANNEL INDEFINATELY ( KILL OR CTRL+C TO END THE THING )&lt;br /&gt;#!/bin/bash&lt;br /&gt;/home/dave/devel/mplayer-mt/mplayer_svn/mplayer -dvbin file=/home/dave/.mplayer/channels.conf -dumpfile /home/dave/Videos/$1.ts -dumpstream dvb://"$2"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;ENCODE A RECORDING&lt;br /&gt;#!/bin/bash&lt;br /&gt;/home/dave/devel/mplayer-mt/mplayer_svn/mencoder -oac lavc -ovc lavc -of mpeg -mpegopts format=xsvcd -vf scale=480:576,harddup -srate 44100 -af lavcresample=44100 -lavcopts vcodec=mpeg2video:mbd=2:keyint=15:vrc_buf_size=917:vrc_minrate=600:vbitrate=2500:vrc_maxrate=2500:acodec=mp2:abitrate=224:aspect=16/9 -ofps 25 -lavdopts fast:threads=4 -mc 10 -o /data/$1.mpg -quiet $1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;WATCH A RECORDING.  THIS IS THE RAW STREAM CAPTURED DURING BY THE RECORD A CHANNEL SCRIPT ABOVE.&lt;br /&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;/home/dave/devel/mplayer-mt/mplayer_svn/mplayer -vc ffh264 -vo gl -lavdopts fast:threads=4 -vf pp=fd -mc 10 -framedrop -cache 10240 -delay -0.3 /home/dave/Videos/$1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;WATCH TV STRAIGHT.  THIS IS FINE FOR ALL CHANNELS EXCEPT TV3 WHICH IS AT FULL HD AND MY CPU DOESNT DECODE IT FAST ENOUGH.  EVEN IN MULTI THREADING.&lt;br /&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;/home/dave/devel/mplayer-mt/mplayer_svn/mplayer -vo gl -lavdopts fast:threads=2 -mc 10 -framedrop -vf pp=fd -cache 10240 -delay -0.3 dvb://"$1"&lt;br /&gt;&lt;br /&gt;So have fun.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-6727196093033135849?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/6727196093033135849/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=6727196093033135849" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/6727196093033135849?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/6727196093033135849?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/03/freeview-dvb-t-linux-fedora-in-new.html" title="Freeview ( DVB-T ) Linux / Fedora in New Zealand." /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkcCR3syfip7ImA9WxBRGEs.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-4748732937224959957</id><published>2010-01-08T00:11:00.003+13:00</published><updated>2010-01-08T00:34:26.596+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-08T00:34:26.596+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="chomp" /><category scheme="http://www.blogger.com/atom/ns#" term="odbc" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="isql" /><category scheme="http://www.blogger.com/atom/ns#" term="single line" /><category scheme="http://www.blogger.com/atom/ns#" term="linux odbc" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><title>chomping isql and date conversion</title><content type="html">Today a colleague was working on retrieving data from a Windows SQL Server database from within linux.  He needed a bash script that would execute a query against the database and dump the results in comma delimited format.&lt;br /&gt;&lt;br /&gt;The SQL query he wrote was rather long and so was broken up into new lines and indented to ease editing and readability.  This, however, caused a snag in isql.&lt;br /&gt;&lt;br /&gt;isql is a commandline tool that ships with linux ODBC that can be used to connect to an ODBC DSN and execute sql commands as well as execute batch files in unattended mode.&lt;br /&gt;&lt;br /&gt;isql parses batch files ( essentially SQL scripts ) in such a way as that each line is treated as a single command.  It does not recognise the GO statement or any other command terminator.&lt;br /&gt;&lt;br /&gt;Our workaround was to chomp the script prior to piping it into isql.  So here we go:&lt;br /&gt;&lt;br /&gt;Here is an example script.&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;#--- mySqlScript.sql ---&lt;br /&gt;&lt;br /&gt;SELECT   TOP 100 *&lt;br /&gt;FROM     myTable t&lt;br /&gt;WHERE    t.created_at between '2009-01-01' and '2009-12-31'&lt;br /&gt;         AND t.enabled = 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can tell the script is formatted in a nice and legible way which would break in isql batchmode.&lt;br /&gt;&lt;br /&gt;The fix is rather simple but also elegant because we can keep the script in it's original format and remove the newlines ( chomp ) just before it is sent to isql.&lt;br /&gt;&lt;br /&gt;Here is the commandline that does just that.&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;[dave@fedora junk]$ cat mySqlScript.sql | perl -ne 'chomp; print unless /^$/'&lt;br /&gt;SELECT   TOP 100 *FROM     myTable tWHERE    t.created_at between '2009-01-01' and '2009-12-31'         AND t.enabled = 1[dave@fedora junk]$ &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So the final step is to pipe all that into an isql command.&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;[dave@fedora junk]$ cat mySqlScript.sql | perl -ne 'chomp; print unless /^$/' | isql -b -d, my_dsn userName passW0rd&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now the above script failed on my computer because (a) I do not have linux odbc installed at home and (b) I do not have a dsn called my_dsn to connect to.&lt;br /&gt;The chomping, however, does work!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-4748732937224959957?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/4748732937224959957/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=4748732937224959957" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4748732937224959957?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4748732937224959957?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2010/01/chomping-isql-and-date-conversion.html" title="chomping isql and date conversion" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkEHQXk7fip7ImA9WxBSFUs.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-4472522869783195005</id><published>2009-12-23T23:34:00.002+13:00</published><updated>2009-12-23T23:37:10.706+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-23T23:37:10.706+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="time calculations" /><category scheme="http://www.blogger.com/atom/ns#" term="php" /><title>An excellent PHP script to handle time difference</title><content type="html">I am working on a project that involves displaying the time difference between a start and end time on a website.&lt;br /&gt;&lt;br /&gt;The following script is lifted directly from: &lt;a href="http://aidanlister.com/2004/04/making-time-periods-readable/"&gt;http://aidanlister.com/2004/04/making-time-periods-readable/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;/**&lt;br /&gt; * A function for making time periods readable&lt;br /&gt; *&lt;br /&gt; * @author      Aidan Lister &lt;aidan@php.net&gt;&lt;br /&gt; * @version     2.0.0&lt;br /&gt; * @link        http://aidanlister.com/2004/04/making-time-periods-readable/&lt;br /&gt; * @param       int     number of seconds elapsed&lt;br /&gt; * @param       string  which time periods to display&lt;br /&gt; * @param       bool    whether to show zero time periods&lt;br /&gt; */&lt;br /&gt;function time_duration($seconds, $use = null, $zeros = false)&lt;br /&gt;{&lt;br /&gt;    // Define time periods&lt;br /&gt;    $periods = array (&lt;br /&gt;        'years'     =&gt; 31556926,&lt;br /&gt;        'Months'    =&gt; 2629743,&lt;br /&gt;        'weeks'     =&gt; 604800,&lt;br /&gt;        'days'      =&gt; 86400,&lt;br /&gt;        'hours'     =&gt; 3600,&lt;br /&gt;        'minutes'   =&gt; 60,&lt;br /&gt;        'seconds'   =&gt; 1&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;    // Break into periods&lt;br /&gt;    $seconds = (float) $seconds;&lt;br /&gt;    foreach ($periods as $period =&gt; $value) {&lt;br /&gt;        if ($use &amp;&amp; strpos($use, $period[0]) === false) {&lt;br /&gt;            continue;&lt;br /&gt;        }&lt;br /&gt;        $count = floor($seconds / $value);&lt;br /&gt;        if ($count == 0 &amp;&amp; !$zeros) {&lt;br /&gt;            continue;&lt;br /&gt;        }&lt;br /&gt;        $segments[strtolower($period)] = $count;&lt;br /&gt;        $seconds = $seconds % $value;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Build the string&lt;br /&gt;    foreach ($segments as $key =&gt; $value) {&lt;br /&gt;        $segment_name = substr($key, 0, -1);&lt;br /&gt;        $segment = $value . ' ' . $segment_name;&lt;br /&gt;        if ($value != 1) {&lt;br /&gt;            $segment .= 's';&lt;br /&gt;        }&lt;br /&gt;        $array[] = $segment;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    $str = implode(', ', $array);&lt;br /&gt;    return $str;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-4472522869783195005?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/4472522869783195005/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=4472522869783195005" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4472522869783195005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4472522869783195005?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/12/excellent-php-script-to-handle-time.html" title="An excellent PHP script to handle time difference" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkEHSH8zeyp7ImA9WxBTEks.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-4282635357022995792</id><published>2009-12-08T21:10:00.002+13:00</published><updated>2009-12-08T21:23:59.183+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-08T21:23:59.183+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="podcasts" /><category scheme="http://www.blogger.com/atom/ns#" term="gtk-pod" /><category scheme="http://www.blogger.com/atom/ns#" term="iPod" /><category scheme="http://www.blogger.com/atom/ns#" term="gpodder" /><category scheme="http://www.blogger.com/atom/ns#" term="amarok 1.4" /><category scheme="http://www.blogger.com/atom/ns#" term="fedora 12" /><title>Things to do with an iPod and Fedora</title><content type="html">My iPod Nano 8gb. ( not the fancy new one with the video ) works perfectly well inside fedora so long as you bear in mind the following basic points:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The thing doesn't play ogg files so if you have any of those on your system, they can not be synced.&lt;/li&gt;&lt;li&gt;Depending on the application you use, you end up with podcasts being saved under music.&lt;/li&gt;&lt;li&gt;Sometimes you get images sometimes you don't.&lt;/li&gt;&lt;li&gt;Albums with Various Artists do not appear under compilations.  Instead your Artists menu shows a long list of artists most of which only have one track.&lt;/li&gt;&lt;/ol&gt;Applications that ship with fedora and support the iPod:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;gtk-pod ( manage your ipod )&lt;br /&gt;&lt;/li&gt;&lt;li&gt;gpodder ( download podcasts etc - these actually go into the podcasts menu on the device. )&lt;/li&gt;&lt;li&gt;Amarok&lt;/li&gt;&lt;li&gt;Rythmbox&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Other music applications I have played with that support the iPod:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Songbird 2&lt;/li&gt;&lt;/ol&gt;I should not here that once again, I have found that Amarok 1.4 is still the best player out there.  I had to install it using the F11 binaries ( just search for them on google ) and a couple of symlinks:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;ln -s /usr/lib64/libssl.so.10 libssl.so.8&lt;/li&gt;&lt;li&gt;ln -s /usr/lib64/libcrypt.so.10 libcrypt.so.8&lt;/li&gt;&lt;/ol&gt;So there you go!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-4282635357022995792?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/4282635357022995792/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=4282635357022995792" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4282635357022995792?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/4282635357022995792?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/12/things-to-do-with-ipod-and-fedora.html" title="Things to do with an iPod and Fedora" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;Ak8NRHkzfSp7ImA9WxNaEU4.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-7932058327705074585</id><published>2009-11-25T21:47:00.001+13:00</published><updated>2009-11-25T21:48:15.785+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-25T21:48:15.785+13:00</app:edited><title>Bash Plus Spaces In Filenames Equals Headache</title><content type="html">OR NOT...&lt;br /&gt;&lt;br /&gt;Check this out:&lt;br /&gt;&lt;br /&gt;http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-7932058327705074585?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/7932058327705074585/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=7932058327705074585" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/7932058327705074585?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/7932058327705074585?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/11/bash-plus-spaces-in-filenames-equals.html" title="Bash Plus Spaces In Filenames Equals Headache" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D04HQnk8eip7ImA9Wx5WGU8.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-1965469124099945288</id><published>2009-11-21T21:06:00.008+13:00</published><updated>2010-10-01T22:38:53.772+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-01T22:38:53.772+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reverse Proxy" /><category scheme="http://www.blogger.com/atom/ns#" term="Clusters" /><category scheme="http://www.blogger.com/atom/ns#" term="Redhat Kickstart" /><title>Understanding Redhat Kickstart</title><content type="html">Kickstart provides linux system administrators a method for installing linux on pc's in unattended mode.  A properly formatted Kickstart configuration will perform all tasks such as setting the root password, the networking interfaces, the disk partitioning scheme as well as the installation of packages.&lt;br /&gt;&lt;br /&gt;I needed to build a clustered reverse proxy the other day to test if it could be used for SSL termination.  I was looking for a way to aggregate multiple webservers behind a proxy server so that they could have their SSL terminate at the proxy, then the HTTP traffic passed through a Level 7 ( application layer ) scanner to test for sql injection and the like.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vTvDLdWlHeM/SwemHTWifmI/AAAAAAAAAuA/AKDf_LL-opg/s1600/example+reverse+proxy.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 333px; height: 400px;" src="http://1.bp.blogspot.com/_vTvDLdWlHeM/SwemHTWifmI/AAAAAAAAAuA/AKDf_LL-opg/s400/example+reverse+proxy.jpg" alt="" id="BLOGGER_PHOTO_ID_5406472522065673826" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;So I fired up my trusty Virtualbox and built a standard Centos 5.4 server.  I copied the CD into the ftp directory and started NFS with an export to that FTP directory.  This server was to serve as an install NFS server for the 2 proxy servers as well as a yum repository for them.  That's why I placed the CD files in the FTP location.&lt;br /&gt;&lt;br /&gt;So here is my example proxy diagram.  It is very similar to the basic openOffice.org version in my previous post.  I needed to make sure that the proxy servers had apache installed on them for the reverse proxie's and heartbeat.  I ended up manually installing heartbeat.  I had my reasons... :)&lt;br /&gt;&lt;br /&gt;The trick making a successful kickstart file is to take one that is generated for you by anaconda.  Anaconda is the software that installs your new Redhat based system.  After a manual install is complete a copy of the kickstart file for that installation is stored in: /root/anaconda-ks.cfg&lt;br /&gt;&lt;br /&gt;I simply copied this over to /var/www/html/ks.cfg and began editing it with vi.  Here is the result of that editing...&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:78%;"&gt;[root@server html]# cat ks.cfg&lt;br /&gt;# Kickstart file automatically generated by anaconda.&lt;br /&gt;&lt;br /&gt;install&lt;br /&gt;nfs --server 192.168.56.254 --dir=/var/ftp/pub/server&lt;br /&gt;lang en_NZ.UTF-8&lt;br /&gt;keyboard us&lt;br /&gt;network --device eth0 --bootproto dhcp --nameserver 192.168.56.1&lt;br /&gt;rootpw --iscrypted $1$ewn======YEAH RIGHT!==2hBDFz1&lt;br /&gt;firewall --enabled --port=22:tcp&lt;br /&gt;authconfig --enableshadow --enablemd5&lt;br /&gt;selinux --enforcing&lt;br /&gt;timezone --utc Pacific/Auckland&lt;br /&gt;bootloader --location=mbr --driveorder=hda&lt;br /&gt;zerombr&lt;br /&gt;clearpart --all&lt;br /&gt;part / --fstype ext3 --size=0 --grow --ondisk=hda&lt;br /&gt;%packages&lt;br /&gt;@base&lt;br /&gt;@core&lt;br /&gt;@editors&lt;br /&gt;@server-cfg&lt;br /&gt;@text-internet&lt;br /&gt;@web-server&lt;br /&gt;heartbeat&lt;br /&gt;keyutils&lt;br /&gt;trousers&lt;br /&gt;fipscheck&lt;br /&gt;device-mapper-multipath&lt;br /&gt;-cups&lt;br /&gt;-bluez-utils&lt;/span&gt;&lt;/blockquote&gt;This file does the following things in order:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Does an INSTALL and not an UPGRADE&lt;/li&gt;&lt;li&gt;Defines the location of the NFS share from which to install from.&lt;/li&gt;&lt;li&gt;Sets the default language&lt;/li&gt;&lt;li&gt;Sets the default keyboard layout&lt;/li&gt;&lt;li&gt;Sets up the network interface&lt;/li&gt;&lt;li&gt;Specifies the root password ( i have masked mine here )&lt;/li&gt;&lt;li&gt;Turns on the firewall and allows port 22 for SSH through it.&lt;/li&gt;&lt;li&gt;Configures authconfig to allow shadow passwords and md5 encryption.&lt;/li&gt;&lt;li&gt;Turns SELINUX on and sets it to ENFORCING mode.&lt;/li&gt;&lt;li&gt;Sets the timezone.&lt;/li&gt;&lt;li&gt;Defines where the bootloader will be installed.  Master Boot Record on the disk HDA&lt;/li&gt;&lt;li&gt;Zeros the master boot record&lt;/li&gt;&lt;li&gt;Clears all partitions&lt;/li&gt;&lt;li&gt;Defines one partition mounted on / ( root ), filetype ext3, 0 min size configured to grow to extents of disk and on disk HDA&lt;/li&gt;&lt;li&gt;Sets up packages.  Package Groups are preceeded with an @ symbol, individual packages are named normally one per line and packages to exclude are preceeded with a - symbol.&lt;/li&gt;&lt;/ol&gt;There is one very useful feature left out and that is POST INSTALLATION SCRIPTS.  This is a script that will be executed after the system has installed and might used for creating default users or determining which services to turn on and off after an install.&lt;br /&gt;&lt;br /&gt;All going well the above VERY BASIC kickstart file should result in a completly automated install, assuming your NFS share is available and the machine can connect to a DHCP server and be assigned an IP address.&lt;br /&gt;&lt;br /&gt;Try it out some time.  It's quite fun to watch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-1965469124099945288?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/1965469124099945288/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=1965469124099945288" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1965469124099945288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1965469124099945288?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/11/understanding-redhat-kickstart.html" title="Understanding Redhat Kickstart" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_vTvDLdWlHeM/SwemHTWifmI/AAAAAAAAAuA/AKDf_LL-opg/s72-c/example+reverse+proxy.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DE4NSHoyeCp7ImA9WxJaEk0.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-5938971330560828481</id><published>2009-08-02T21:41:00.005+12:00</published><updated>2009-08-02T21:56:39.490+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-02T21:56:39.490+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="scheduled tasks" /><category scheme="http://www.blogger.com/atom/ns#" term="high availability" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Comand Line" /><category scheme="http://www.blogger.com/atom/ns#" term="virtual ip address" /><title>Scheduled Tasks on HA Pairs in Windows</title><content type="html">Sometimes you might find yourself deciding that a Scheduled task is required for some report or file transfer on a production system.  The production system, however, is part of a high availability (HA) pair.  The particular method of dealing with HA in this particular ( hypothetical of course ) case works by moving an IP Address called a Virtual IP address between the servers of the HA Pair.  Whichever server holds the VIP is the current node.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Your application needs to know if it is executing on the current node before starting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wrap your application in a very simple snippet of Comand Line script that:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Looks for the VIP in ipconfig.&lt;/li&gt;&lt;li&gt;If no errors found then jump to the section of your script that launches your application or another script to do the task.&lt;/li&gt;&lt;li&gt;If an error is found then jump to the section of your script that notifies the log.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;@echo off&lt;br /&gt;REM #Testing FIND in IPCONFIG&lt;br /&gt;SET VIPTHATWORKS="192.168.122.1"&lt;br /&gt;SET VIPTHATFAILS="192.168.122.127"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;ipconfig /all | find %VIPTHATWORKS%&lt;br /&gt;if ERRORLEVEL = 1 goto VIP_NOT_FOUND&lt;br /&gt;&lt;br /&gt;REM #We are here becuase the find returned a result.&lt;br /&gt;REM #It is safe to execute the rest of the application.&lt;br /&gt;echo "VIP Found. - Continuing with application..."&lt;br /&gt;&lt;br /&gt;REM #Pause for user input.&lt;br /&gt;pause&lt;br /&gt;goto END_SCRIPT&lt;br /&gt;&lt;br /&gt;:VIP_NOT_FOUND&lt;br /&gt;REM #This part of the script is where you would handle any&lt;br /&gt;REM #error logging or other admin related&lt;br /&gt;echo "Could not find a VIP. - Exiting"&lt;br /&gt;&lt;br /&gt;REM #Pause for user input.&lt;br /&gt;pause&lt;br /&gt;goto END_SCRIPT&lt;br /&gt;&lt;br /&gt;:END_SCRIPT&lt;br /&gt;echo "end of script reached."&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-5938971330560828481?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/5938971330560828481/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=5938971330560828481" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/5938971330560828481?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/5938971330560828481?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/08/scheduled-tasks-on-ha-pairs-in-windows.html" title="Scheduled Tasks on HA Pairs in Windows" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkMHR3sycSp7ImA9WxJaEU0.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-3650090361029896744</id><published>2009-08-01T16:08:00.002+12:00</published><updated>2009-08-01T16:20:36.599+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-01T16:20:36.599+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Audio Books" /><category scheme="http://www.blogger.com/atom/ns#" term="iTunes" /><category scheme="http://www.blogger.com/atom/ns#" term="Pod Cast" /><category scheme="http://www.blogger.com/atom/ns#" term="iPod" /><title>Things to do with an iPod</title><content type="html">I have had my iPod 8gb Nano ( Video ) for about 4 months now and I have been having heaps of fun with it.  I know it's not cool like an iPod Touch or iPhone but it is still plenty powerful.&lt;br /&gt;&lt;br /&gt;I have tried using it with Linux and although it is supported in Amarok ( I am still on Amarok 1.4 due to lack of Fedora packages for the new version which actually has replay-gain for Xine included ) I have found that the support for pod casts is a little limited.  For example: I like to download all the pod casts in a feed at once so that I can catch up to the current feed.  So I stick with iTunes.  This means sticking with a windows pc or if you are lucky to own one, a mac.&lt;br /&gt;&lt;br /&gt;Initially I spent heaps of time building the perfect play list on my iTunes and moving that over to the iPod.  This was fun but only for a short while.  The main problem being that no matter how many weeks of music you have on your iPod, you still end up with the feeling that you have heard it all before.&lt;br /&gt;&lt;br /&gt;I was struck by the "Only options is to rebuild windows" bug recently.  You might know that as the, "My Computer is getting slower and slower and doesn't shut down properly anymore" bug.  Stupidly, I had no backup of my iTunes library so I lost the whole thing.  About 200 CDs worth.  Nice...&lt;br /&gt;&lt;br /&gt;What was initially looking like a bad thing for me has really turned into a blessing in disguise. A friend suggested I try an audio book and pointed me to &lt;a href="http://www.podiobooks.com"&gt;www.podiobooks.com&lt;/a&gt;.  Its a great resource for free audio books, usually read by the Author.  If you sign up you can subscribe to audio books which are exposed via an XML feed which is completely compatible with iTunes.  Just select how you want the feed to be released to you: once a day, once every 3 days etc. and then select the Subscribe Via iTunes button.  If the book is complete, ie: All episodes are available, then you can click the release all episodes now button and then subscribe to the feed provided.  All episodes will be loaded into your iTunes library ready for you to click the "Get All" button.&lt;br /&gt;&lt;br /&gt;All in all I seriously recommend Podiobooks.  I suggest you start off with, "Infected" by Scott Sigler.  Its a dark / fantasy kind of book with horror content but a riveting story.  I was hooked within 5 minutes and found myself looking forward to my next bus trip to work so I could find out more about Perry Dawcey's plight...&lt;br /&gt;&lt;br /&gt;Happy listening.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-3650090361029896744?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/3650090361029896744/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=3650090361029896744" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/3650090361029896744?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/3650090361029896744?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/08/things-to-do-with-ipod.html" title="Things to do with an iPod" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcASHs9fip7ImA9WxJaEE4.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-1034708614529321518</id><published>2009-07-31T22:50:00.002+12:00</published><updated>2009-07-31T23:00:49.566+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-31T23:00:49.566+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="id3v2" /><category scheme="http://www.blogger.com/atom/ns#" term="music" /><category scheme="http://www.blogger.com/atom/ns#" term="rip wav2mp3" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="lame" /><title>Rip from WAV to MP3 and add ID3 tags -- All with Perl</title><content type="html">Ok - so I know I have said before that I am not much of a perl fan. ( yes it's safe, I am wearing my flame proof suit. )&lt;br /&gt;&lt;br /&gt;I will, however, say now; I am coming around.  It would seem that I am starting to see the light.  I needed to extract some files from a CD I have and convert them to MP3.  The CD was not made with extracting to mp3 in mind if you get my drift.  It's ok, because the CD is my copy and I want to listen to it on my iPod.  Regular extracting on iTunes was not working out for me.  So I rolled my chair over to my trusty Linux Box and perl, id3, cdparanoia and lame.&lt;br /&gt;&lt;br /&gt;First thing I did was use cdparanoia to extract all the tracks.  This went swimmingly leaving me with a folder full of files called 01.cdparanoia.wav or something just as useless.  The files played ok but I needed to name them all.  This particular CD was not listed on Music Brainz so I couldn't do anything fancy with FreeCDDB or whatever they call that now days.&lt;br /&gt;&lt;br /&gt;* shudder * - I had to manually edit 17 filenames.  I left the .wav extensions of course.  I thought that I might need to get the tags later so I decided to choose a naming scheme for my file names.&lt;br /&gt;&lt;br /&gt;TRACK-TITLE_ARTIST.wav&lt;br /&gt;01-My Song Title_My Artist Name.wav&lt;br /&gt;&lt;br /&gt;and so on.&lt;br /&gt;&lt;br /&gt;Then I wrote a little script that:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Loops through each file in a folder with the .wav extension&lt;/li&gt;&lt;li&gt;Saves a variable with the file name but with .mp3 instead of .wav&lt;/li&gt;&lt;li&gt;Regexes ( new word ) out the various parts of the file name into $track, $title, $artist ( thanks to the nice naming scheme this was easy. )&lt;/li&gt;&lt;li&gt;Uses Lame to convert the file.  Lame now days is pretty cool.&lt;/li&gt;&lt;li&gt;Uses id3v2 to add the tags extracted from the file name.  I can use amarok to add the album titles etc once it is imported into Amarok.&lt;/li&gt;&lt;/ul&gt;Here is the script:&lt;br /&gt;&lt;pre class='prettyprint'&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;br /&gt;@files = &lt;*.wav&gt;;&lt;br /&gt;&lt;br /&gt;foreach $file (@files) {&lt;br /&gt; &lt;br /&gt; $newfile = $file;&lt;br /&gt; $newfile =~ s/\.wav/\.mp3/;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; $file =~ m/^(.*)-(.*)_(.*).wav/;&lt;br /&gt;  &lt;br /&gt; $track = $1;&lt;br /&gt; $title = $2;&lt;br /&gt; $artist = $3;&lt;br /&gt; &lt;br /&gt; system("lame", "--preset", "cd" ,"$file" ,"$newfile");&lt;br /&gt; system("id3v2", "--artist", "$artist", "$newfile");&lt;br /&gt; system("id3v2", "--song", "$title", "$newfile");&lt;br /&gt; system("id3v2", "--track", "$track", "$newfile");&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-1034708614529321518?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/1034708614529321518/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=1034708614529321518" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1034708614529321518?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1034708614529321518?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/07/rip-from-wav-to-mp3-and-add-id3-tags.html" title="Rip from WAV to MP3 and add ID3 tags -- All with Perl" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkABQH84eyp7ImA9WxJbGUk.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-1633191621585444224</id><published>2009-07-30T22:09:00.004+12:00</published><updated>2009-07-30T22:12:31.133+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-30T22:12:31.133+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server 2008" /><category scheme="http://www.blogger.com/atom/ns#" term="Scite" /><category scheme="http://www.blogger.com/atom/ns#" term="Active State" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Server 2008" /><title>Real simple to connect to MSSQL from Perl</title><content type="html">Again, this took me a little while but here I am.  Connecting to a database ( SQL SERVER 2008 ) from a Windows Server 2008 VM I own ( thanks TECH ED 2008 ) and Active State Perl.&lt;br /&gt;&lt;br /&gt;Install Scite cos it's a nice editor and you are away laughing...&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;#!/usr/bin/perl&lt;br /&gt;&lt;br /&gt;use DBI;&lt;br /&gt;&lt;br /&gt;my $DSN = 'driver={SQL Server};Server=localhost; database=AdventureWorks;TrustedConnection=Yes'; &lt;br /&gt;my $dbh = DBI-&gt;connect("dbi:ODBC:$DSN") or die "$DBI::errstr\n";&lt;br /&gt;&lt;br /&gt;my $sth = $dbh-&gt;prepare('select top 10 * from Sales.vSalesPerson')&lt;br /&gt;    or die "Couldn't prepare statement: " . $dbh-&gt;errstr;&lt;br /&gt;&lt;br /&gt;$sth-&gt;execute();&lt;br /&gt;&lt;br /&gt;while( @data = $sth-&gt;fetchrow_array())&lt;br /&gt;{&lt;br /&gt;    foreach(@data) {&lt;br /&gt;        print "[$_]";&lt;br /&gt;    }&lt;br /&gt;    print "\n\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$sth-&gt;finish;&lt;br /&gt;$dbh-&gt;disconnect;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Results:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;C:\Users\dave\Documents&gt;perl perl1.pl&lt;br /&gt;[268][][Stephen][Y][Jiang][][North American Sales Manager][238-555-0197][stephen&lt;br /&gt;0@adventure-works.com][0][2427 Notre Dame Ave.][][Redmond][Washington][98052][Un&lt;br /&gt;ited States][][][][677558.4653][.0000]&lt;br /&gt;&lt;br /&gt;[275][][Michael][G][Blythe][][Sales Representative][257-555-0154][michael9@adven&lt;br /&gt;ture-works.com][1][8154 Via Mexico][][Detroit][Michigan][48226][United States][N&lt;br /&gt;ortheast][North America][300000.0000][4557045.0459][1750406.4785]&lt;br /&gt;&lt;br /&gt;[276][][Linda][C][Mitchell][][Sales Representative][883-555-0116][linda3@adventu&lt;br /&gt;re-works.com][0][2487 Riverside Drive][][Nevada][Utah][84407][United States][Sou&lt;br /&gt;thwest][North America][250000.0000][5200475.2313][1439156.0291]&lt;br /&gt;&lt;br /&gt;[277][][Jillian][][Carson][][Sales Representative][517-555-0117][jillian0@advent&lt;br /&gt;ure-works.com][1][80 Sunview Terrace][][Duluth][Minnesota][55802][United States]&lt;br /&gt;[Central][North America][250000.0000][3857163.6332][1997186.2037]&lt;br /&gt;&lt;br /&gt;[278][][Garrett][R][Vargas][][Sales Representative][922-555-0165][garrett1@adven&lt;br /&gt;ture-works.com][0][10203 Acorn Avenue][][Calgary][Alberta][T2P 2G8][Canada][Cana&lt;br /&gt;da][North America][250000.0000][1764938.9859][1620276.8966]&lt;br /&gt;&lt;br /&gt;[279][][Tsvi][Michael][Reiter][][Sales Representative][664-555-0112][tsvi0@adven&lt;br /&gt;ture-works.com][1][8291 Crossbow Way][][Memphis][Tennessee][38103][United States&lt;br /&gt;][Southeast][North America][300000.0000][2811012.7151][1849640.9418]&lt;br /&gt;&lt;br /&gt;[280][][Pamela][O][Ansman-Wolfe][][Sales Representative][340-555-0193][pamela0@a&lt;br /&gt;dventure-works.com][1][636 Vine Hill Way][][Portland][Oregon][97205][United Stat&lt;br /&gt;es][Northwest][North America][250000.0000][.0000][1927059.1780]&lt;br /&gt;&lt;br /&gt;[281][][Shu][K][Ito][][Sales Representative][330-555-0120][shu0@adventure-works.&lt;br /&gt;com][2][5725 Glaze Drive][][San Francisco][California][94109][United States][Sou&lt;br /&gt;thwest][North America][250000.0000][3018725.4858][2073505.9999]&lt;br /&gt;&lt;br /&gt;[282][][JosΘ][Edvaldo][Saraiva][][Sales Representative][185-555-0169][josΘ1@adve&lt;br /&gt;nture-works.com][0][9100 Sheppard Avenue North][][Ottawa][Ontario][K4B 1T7][Cana&lt;br /&gt;da][Canada][North America][250000.0000][3189356.2465][2038234.6549]&lt;br /&gt;&lt;br /&gt;[283][][David][R][Campbell][][Sales Representative][740-555-0182][david8@adventu&lt;br /&gt;re-works.com][0][2284 Azalea Avenue][][Bellevue][Washington][98004][United State&lt;br /&gt;s][Northwest][North America][250000.0000][3587378.4257][1371635.3158]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;C:\Users\dave\Documents&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-1633191621585444224?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/1633191621585444224/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=1633191621585444224" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1633191621585444224?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/1633191621585444224?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/07/real-simple-to-connect-to-mssql-from.html" title="Real simple to connect to MSSQL from Perl" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;AkIEQn44fSp7ImA9WxJbFk0.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-278032800834111677</id><published>2009-07-26T23:39:00.002+12:00</published><updated>2009-07-26T23:41:43.035+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-26T23:41:43.035+12:00</app:edited><title>Basic Perl file parser - useful for working with logs</title><content type="html">Really I just need to remember how to do this:&lt;br /&gt;&lt;br /&gt;&lt;pre class='prettyprint'&gt;&lt;br /&gt;#!/usr/bin/env perl&lt;br /&gt;#yum log file&lt;br /&gt;use warnings;&lt;br /&gt;use strict;&lt;br /&gt;&lt;br /&gt;open FILE, "/var/log/yum.log" or die $!;&lt;br /&gt;while (&amp;lt;FILE&amp;gt;) {&lt;br /&gt; /^(.+?)\s(.+?)\s(.+?)\s(.+?)\s(.+?)\s/;&lt;br /&gt; my ($month,$day,$time,$action,$package) = ($1,$2,$3,$4,$5);&lt;br /&gt; if( $action =~ /Installed/ ) {&lt;br /&gt;  my $suffix = 'th';&lt;br /&gt;  if( $day == 1 ){ $suffix = 'st'; }&lt;br /&gt;  if( $day == 21 ){ $suffix = 'st'; }&lt;br /&gt;  if( $day == 31 ){ $suffix = 'st'; }&lt;br /&gt;  if( $day == 2 ){ $suffix = 'nd'; }&lt;br /&gt;  if( $day == 22 ){ $suffix = 'nd'; }&lt;br /&gt;  if( $day == 3 ){ $suffix = 'rd'; }&lt;br /&gt;  if( $day == 23 ){ $suffix = 'rd'; }&lt;br /&gt;  &lt;br /&gt;  print "$day$suffix of $month at $time\n"&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;close FILE&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-278032800834111677?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/278032800834111677/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=278032800834111677" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/278032800834111677?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/278032800834111677?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/07/basic-perl-file-parser-useful-for.html" title="Basic Perl file parser - useful for working with logs" /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkYBRHo4fCp7ImA9WxJbFk0.&quot;"><id>tag:blogger.com,1999:blog-2666170339866438578.post-8144581344507909822</id><published>2009-07-26T20:22:00.008+12:00</published><updated>2009-07-26T21:22:35.434+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-26T21:22:35.434+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="curl" /><category scheme="http://www.blogger.com/atom/ns#" term="gs" /><category scheme="http://www.blogger.com/atom/ns#" term="ghostscript" /><category scheme="http://www.blogger.com/atom/ns#" term="bash" /><category scheme="http://www.blogger.com/atom/ns#" term="wget" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="sed" /><title>Joining multiple PDF documents with Gostscript.</title><content type="html">This really works.&lt;br /&gt;&lt;br /&gt;I downloaded all the chapters of beginning perl as published here: &lt;a href="http://www.perl.org/books/beginning-perl/"&gt;http://www.perl.org/books/beginning-perl/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To do it in a painless way I first used curl to grab the html.&lt;br /&gt;&lt;pre class="prettyprint"&gt;curl http://www.perl.org/books/beginning-perl/ -o bp.txt&lt;/pre&gt;&lt;br /&gt;Then I used grep to grab the hyperlinks to pdf files and piped that into another file.&lt;br /&gt;&lt;pre class="prettyprint"&gt;cat bp.txt | grep -o "&amp;lt;a.*pdf"&amp;gt; bp2.txt&lt;/pre&gt;&lt;br /&gt;Then I used sed to clean up a little bit.&lt;br /&gt;&lt;pre class="prettyprint"&gt;cat bp2.txt | sed "s/^&amp;lt;a href=\"//g"&amp;gt; bp3.txt&lt;/pre&gt;&lt;br /&gt;Then I used wget to download each pdf.&lt;br /&gt;&lt;pre class="prettyprint"&gt;for line in `cat bp3.txt`; do wget $line; done&lt;/pre&gt;&lt;br /&gt;So now I had a whole bunch of pdf files that together make up one book.  A quick hunt on google produced this guy.&lt;br /&gt;&lt;a href="http://www.linux.com/news/software/applications/8229-putting-together-pdf-files"&gt;http://www.linux.com/news/software/applications/8229-putting-together-pdf-files&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And I was away laughing.&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=beginning-perl.pdf 3145_Intro.pdf 3145_Chap*.pdf 3145_App*.pdf 3145_Index.pdf&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2666170339866438578-8144581344507909822?l=david-latham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://david-latham.blogspot.com/feeds/8144581344507909822/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2666170339866438578&amp;postID=8144581344507909822" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/8144581344507909822?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2666170339866438578/posts/default/8144581344507909822?v=2" /><link rel="alternate" type="text/html" href="http://david-latham.blogspot.com/2009/07/joining-multiple-pdf-documents-with.html" title="Joining multiple PDF documents with Gostscript." /><author><name>David Latham</name><uri>https://profiles.google.com/111973346803371597819</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-pq-FrbI5uKY/AAAAAAAAAAI/AAAAAAAABIw/lkS-1EsiOk0/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry></feed>

