<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BluHelix Studios &#187; Inside BluHelix</title>
	<atom:link href="http://www2.bluhelix.com/category/inside-bluhelix/feed/" rel="self" type="application/rss+xml" />
	<link>http://www2.bluhelix.com:81</link>
	<description>The Official BluHelix Home Page</description>
	<lastBuildDate>Wed, 01 Sep 2010 02:34:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>MySQL database class</title>
		<link>http://www2.bluhelix.com:81/2010/08/mysql-database-class/</link>
		<comments>http://www2.bluhelix.com:81/2010/08/mysql-database-class/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 02:12:56 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://www.bluhelix.com/?p=305</guid>
		<description><![CDATA[Developers should always be vigil for XSS and SQL injection attacks. Data from POST and GET should never be trusted. It is trivial to submit arbitrary values to a web page. When it comes to database insertion, strings should always be purged of unsafe entities. PHP&#8217;s MySQL extension offers a good solution. Once a link [...]]]></description>
			<content:encoded><![CDATA[<p>Developers should always be vigil for XSS and SQL injection attacks.  Data from POST and GET should never be trusted.  It is trivial to submit arbitrary values to a web page.  When it comes to database insertion, strings should always be purged of unsafe entities.  PHP&#8217;s MySQL extension offers a good solution.</p>
<p>Once a link identifier ($link) to a database is opened, PHP strings can be cleaned up using
<code>$safe_string = mysql_real_escape_string($unsafe_string, $link);</code></p>
<p>This is simple and convenient.  Below is a similar function to get a feel for what mysql_real_escape_string() is doing.
<code>function escape($str)
{
  $search=array("\\","\0","\n","\r","\x1a","'",'"');
  $replace=array("\\\\","\\0","\\n","\\r","\Z","\'",'\"');
  return str_replace($search,$replace,$str);
}</code><br />
source: <a href="http://php.net/manual/en/function.mysql-escape-string.php">http://php.net/manual/en/function.mysql-escape-string.php</a></p>
<p>I have written a wrapper class for PHP&#8217;s mysql functions that can help with escaping data using mysql_real_escape_string() for safe database insertions.  Additionally, it generally reduces the clutter that PHP&#8217;s built in query functions can cause.</p>
<p>The basic idea is that the class can be instantiated with
<code>$query = new MySqlDB($hostname, $database, $username, $password);</code></p>
<p>And then queries can be executed and an array containing the results can be easily captured like so
<code>$query-&gt;executeQuery('SELECT * FROM `Table` WHERE `Field1` = %s AND `Field2` = %d', 'string', 12);

while ($row = $query-&gt;fetchArray())
{
  $field3 = $row['Field3'];
  // do something amazing
}</code></p>
<p>The query parameter is treated as a format string of sorts where %s is cast as a string and %d is cast as an integer from the provided list of arguments.  A query string and arguments can also be provided directly into the fetchArray() call for a single line return of the first row.  There are also methods to return a single value returned by the query and one to return all rows in a single array.</p>
<p>Some other cool things you can do
<code>// Inserts a row into 'Table' where Field1 = 'string' and Field2 = 12
$insert = array('Field1' =&gt; 'string', 'Field2' =&gt; 12);

$query-&gt;insertAssoc('Table', $insert);

// Updates row where Field3 = 10
$update = array('Field1 =&gt; 'string', 'Field2' =&gt; 12);

$query-&gt;updateAssoc('Table', $update, 'Field3 = %d', 10);</code></p>
<p>You can download MySqlDB on my in my <a href="/snippets/">snippets</a> page or <a href="/pub/classes/mysqldb.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2010/08/mysql-database-class/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Multiplatform Backup Solution with rSync: Part 2</title>
		<link>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-2/</link>
		<comments>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-2/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 21:33:33 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=208</guid>
		<description><![CDATA[Hello, this is part 2 of my rSync backup solution article. Please see part 1 if you have not read it yet. Overview The primary weakness of the rSync bash script covered in part 1 when backing up a Windows computer is that it is unable to transfer any file that might be open by [...]]]></description>
			<content:encoded><![CDATA[<p>Hello, this is part 2 of my rSync backup solution article.  Please see part 1 if you have not read it yet.</p>
<h3>Overview</h3>
<p>The primary weakness of the rSync bash script covered in part 1 when backing up a Windows computer is that it is unable to transfer any file that might be open by the user or operating system.  Microsoft includes a backup application (NTBackup) beginning in Windows XP Service Pack 1 and Windows 2003 that gets around this problem by creating its backup from a <a href="http://en.wikipedia.org/wiki/Volume_shadow_copy">volume shadow copy</a>.  The Volume Shadow Copy creates a snapshot of a specific volume at a specific point in time.  This allows one to backup every file in a volume without the possibility of any being open or partially written to by an application.</p>
<p>Using the volume shadow copy requires a bit of black magic.  We&#8217;ll need to obtain vshadow.exe from one of Microsoft&#8217;s freely available SDK&#8217;s.  Very few programs understand the URI for a volume shadow copy, including rSync, so we&#8217;ll also need an <a href="http://blogs.msdn.com/adioltean/archive/2006/09/18/761515.aspx">application capable of mapping a volume shadow copy to a standard Windows drive letter</a>.  The solution is an small program called <a href="http://blogs.msdn.com/adioltean/archive/2005/10/04/477164.aspx">dosdev.exe</a>, which is a wrapper around <a href="http://msdn.microsoft.com/en-us/library/aa363904.aspx">DefineDosDevice( )</a> Win32 API.</p>
<h3>Setup</h3>
<p>For our setup we will have two machines.  The <strong>Mirror</strong> (192.168.1.2) will be the rSync backup server running a *nix operating system.  The Mirror will create snapshots of the <strong>Target</strong> (192.168.1.3) which is running either Windows XP or Windows Vista.  I will be sure to note when the two Windows operating systems differ in our setup.</p>
<h4>Required software for the Mirror</h4>
<ul>
<li>OpenSSH</li>
<li>rSync</li>
<li>Expect</li>
</ul>
<h4>Required software for the Target</h4>
<ul>
<li>cwRsync</li>
<li>CopSSH</li>
<li>vshadow.exe</li>
<li>dosdev.exe</li>
</ul>
<p>The software needed on the Mirror is pretty minimal, assuming you already setup the snapshot-based backup covered in part 1.  The one new thing we&#8217;ll need is <a href="http://en.wikipedia.org/wiki/Expect">Expect</a> so we can write a short Expect Script.</p>
<p>For Windows, we&#8217;ll need a Windows based rSync.  I picked cwRsync because it is easy to install and runs from Cygwin, which we&#8217;ll need.  There is no need to install Cygwin, however, as cwRsync comes with all the required Cygwin binaries in the installer.  You can find cwRsync at their site: <a href="http://www.itefix.no/i2/node/10650">http://www.itefix.no/i2/node/10650</a></p>
<p>Install cwRsync to the folder of your choice.  Next, download <a href="http://www.itefix.no/i2/node/27">CopSSH</a>.  CopSSH is also a straight forward to install and setup SSH server for Windows.  The program is Cygwin based, and again, includes all the Cygwin binaries needed to do its job.  The trick here is, we want to install CopSSH to the same location as cwRsync so we avoid having two instances of Cygwin running simultaneously.</p>
<p>Next, we&#8217;ll need vshadow.exe.  For Windows XP and 2003 users, you can download <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0B4F56E4-0CCC-4626-826A-ED2C4C95C871&amp;displaylang=en">Microsoft&#8217;s Volume Shadow Copy Service SDK</a>.  Vista user&#8217;s need to download the <a href="http://msdn.microsoft.com/en-us/windows/bb980924.aspx">Windows Vista SDK Update</a>.  It is <strong>very</strong> important you obtain the correct version of vshadow.exe.  For instance, the Windows XP and 2003 versions are <strong>different</strong> and will be found in different directories after the SDK is installed.  If you encounter errors when running vshadow.exe, then do verify you grabbed the correct file.  I suggest copying vshadow.exe and placing it in either the Cygwin bin folder or your System32 folder in Windows.  You may uninstall the SDK if you prefer &#8211; we only need vshadow.exe.</p>
<p>Finally, we need dosdev.exe.  This program is very obscure.  To get the exe from Microsoft, download <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=cebf3c7c-7ca5-408f-88b7-f9c79b7306c0&amp;DisplayLang=en">MPSRPT_CLUSTER.EXE</a>.  If you have a program like 7zip you can extract dosdev.exe directly from the installer.  Otherwise you will need to install the report application and copy dosdev.exe from it.  Again, I suggest copying dosdev.exe and placing it in either the Cygwin bin folder or your System32 folder in Windows.  DO NOT EXECUTE the report&#8230;</p>
<p>Once everything is installed, activate a CopSSH user.  This can be done easily by launching the activate user wizard from the CopSSH start menu entry.  In order to execute vshadow.exe you need to activate a user with Administrator privledges.  In Vista, this probably means the hidden Administrator account.  Vista users, please follow this <a href="http://www.howtogeek.com/howto/windows-vista/enable-the-hidden-administrator-account-on-windows-vista/">How to guide</a> to enable the hidden Administrator account and assign it a password.  If you prefer, you may then <a href="http://forums.techarena.in/vista-help/748249.htm#post2854275">hide the account from the login screen</a>.</p>
<h3>Scripts</h3>
<p>For this setup we&#8217;ll need (sadly) eight files: four on the Mirror and four more on the Target machine.  Place all the Mirror files in the same directory and I have them creating the snapshot in <strong>/snapshot</strong>.  For the Target, I left all four files in the Administrator&#8217;s home dir at <strong>C:\Program Files\cwRsync\home\Administrator</strong>.  I plopped a copy of vshadow.exe and dosdev.exe in <strong>C:\Program Files\cwRsync\bin</strong> so that I could execute them like the Cygwin command line programs.  Again, <strong>C:\Windows\System32</strong> would also work.  Replace all instances of &#8220;password123&#8243; with your Administrator&#8217;s password.  However, the rSync daemon password need not be the same as your Windows authentication password.</p>
<h4>General idea</h4>
<ol>
<li>backup.sh is initiated manually or from a scheduled cron entry</li>
<li>backup.sh cleans up extra files in case the previous execution failed to complete</li>
<li>backup.sh uses an expect script to log into Target via a password authenticated SSH session and begins vshadow.exe as a background process.</li>
<li>backup.sh waits on a VB script that is started remotely to sleep until the rSyncd pid file is detected</li>
<li>vshadow.exe executes a CMD script that maps a volume shadow copy with dosdev.exe and then begins a rSync daemon</li>
<li>rSync daemon creates a pid file and listens for a connection</li>
<li>Remote VB script detects the rSyncd pid file and terminates, allowing the bash script to continue</li>
<li>backup.sh begins the rSync transfer process, which connects to the daemon running on the remote machine</li>
<li>After the transfer is complete, backup.sh kills the daemon process on the remote machine</li>
<li>With the rSync daemon terminated, the CMD script continues and unmaps the drive letter used for the volume shadow copy.</li>
<li>vshadow.exe completes and destroys the volume shadow copy.</li>
<li>backup.sh cleans up extra files and terminates.</li>
</ol>
<h4>Mirror</h4>
<ul>
<li>backup.sh</li>
<li>exclude_users</li>
<li>rsync.secret</li>
<li>sshlogin.exp</li>
</ul>
<h4>Target</h4>
<ul>
<li>rsyncd.secrets</li>
<li>sleep-rsyncd.vbs</li>
<li>vsrsync.cmd</li>
<li>rsyncd.conf</li>
</ul>
<ul>
<li>The files backup.sh and exclude_users are recognizably close to what we used in part 1.   If you are a Vista user do note that you will need to exclude <a href="http://www.svrops.com/svrops/articles/jpoints.htm">certain junctions and soft links</a> that Microsoft included to maintain XP-like paths or rSync will error and/or backup the same files more than once.  The junctions might be surprising to some Windows users since Vista OS keeps them hidden from the user during normal use.</li>
<li>There are some differences between my backup.sh on XP and Vista; however, it turns out the Vista version will run on XP so I will only provide my Vista script in this guide to keep things simpler.</li>
<li>Notice that we call vshadow.exe and taskkill using an expect script rather than the usual public key authentication.  Public key authentication in Cygwin/SSH bypasses Windows authentication (because no Windows password was provided to authenticate) and in Cygwin 1.5.x, the version I used in my setup, the context switch used to support public key authentication causes a slight difference in the environment that prevents vshadow.exe from running successfully.  The win32 app taskkill also fails on Vista when used with public key authentication (it completed successfully on XP, however).</li>
<li>For some reason the PID printed to the rsyncd pid file in Vista was inaccurate.  In XP it was correct and I used the contents of the pid file to kill the process.</li>
<li>Also take note that we&#8217;re using a rSync clinet/daemon model instead of tunneling rSync over SSH.  This means we&#8217;ll need a password file to avoid an interactive password prompt and our transfer is sent over the clear instead of being encrypted.  Advanced users may consider <a href="http://www.netbits.us/docs/stunnel_rsync.html">tunneling rSync over STunnel</a> to achieve encryption.</li>
<li>We set the modify window parameter to 2 seconds to the <a href="http://support.microsoft.com/kb/127830">2 second timestamp resolution of FAT32 file systems</a>.</li>
<li>Finally, while Windows paths are not case sensitive, *nix and by extension, Cygwin, paths are.  On my XP machine the Windows directory is all capitals, so be sure to verify the casing in the paths I entered below match your system.</li>
</ul>
<p><strong>backup.sh</strong>
<code>#!/bin/bash
unset PATH

# USER VARIABLES
BACKUPDIR=/snapshots                                # Folder on the backup server where the backups shall be located
KEY=/root/rsync/rsync-key                           # SSH key
TARGET_HOST=192.168.1.3                             # The address of the production server
TARGET_USER=Administrator                           # The user of the production server
EXCLUDES_USERS=/root/backup/exclude_users           # File containing the excluded directories
DAYS=30                                             # The number of days after which old backups will be deleted

# PATH VARIABLES
CSCRIPT=/cygdrive/c/Windows/System32/cscript.exe    # Remote location of cscript exe
TASKKILL=/cygdrive/c/Windows/System32/taskkill.exe  # Remote location of taskkill.exe
CAT=/bin/cat                                        # Remote location of cat bin
SED=/bin/sed                                        # Remote location of sed bin

CP=/bin/cp;                                         # Location of the cp bin
FIND=/usr/bin/find;                                 # Location of the find bin
ECHO=/bin/echo;                                     # Location of the echo bin
MK=/bin/mkdir;                                      # Location of the mk bin
SSH=/usr/bin/ssh;                                   # Location of the ssh bin
DATE=/bin/date;                                     # Location of the date bin
RM=/bin/rm;                                         # Location of the rm bin
GREP=/bin/grep;                                     # Location of the grep bin
RSYNC=/usr/bin/rsync;                               # Location of the rsync bin
TOUCH=/bin/touch;                                   # Location of the touch bin

##                                                      ##
##      --       DO NOT EDIT BELOW THIS HERE     --     ##
##                                                      ##

# CREATING NECESSARY FOLDERS
$MK $BACKUPDIR
CURRENT=$BACKUPDIR/current
OLD=$BACKUPDIR/old
$MK $CURRENT
$MK $OLD
# CREATING CURRENT DATE / TIME
NOW=`$DATE '+%Y-%m'-%d_%H:%M`
NOW=$OLD/$NOW
$MK $NOW

# INITIALIZE VOLUME SHADOW COPY AND RSYNC DAEMON
$SSH -i $KEY $TARGET_USER@$TARGET_HOST "rm rsyncd.pid"

./sshlogin.exp $TARGET_USER@$TARGET_HOST                                 \
  "vshadow.exe -script=vss-setvar.cmd -exec=vsrsync.cmd C\:" &#038;

# SLEEP UNTIL RSYNCD PID FILE IS FOUND
$SSH -i $KEY $TARGET_USER@$TARGET_HOST "$CSCRIPT sleep-rsyncd.vbs"

# RUN RSYNC INTO CURRENT
$RSYNC                                                                   \
        -apvz --delete --delete-excluded                                 \
        --exclude-from="$EXCLUDES_USERS"                                 \
        --password-file=rsync.secret                                     \
        --modify-window=2                                                \
        $TARGET_USER@$TARGET_HOST::C/Users/                              \
    $CURRENT ;

# TERMINATE RSYNC DAEMON AND VOLUME SHADOW COPY
./sshlogin.exp $TARGET_USER@$TARGET_HOST "$TASKKILL -f -im rsync.exe"
$SSH -i $KEY $TARGET_USER@$TARGET_HOST "rm rsyncd.pid vss-setvar.cmd"

# UPDATE THE MTIME TO REFELCT THE SNAPSHOT TIME
$TOUCH $BACKUPDIR/current

# MAKE HARDLINK COPY
$CP -al $CURRENT/* $NOW

# REMOVE OLD BACKUPS
for FILE in "$( $FIND $OLD -maxdepth 1 -type d -mtime +$DAYS )"
do
  $RM -Rf $FILE
  # $ECHO $FILE
done
exit 0</code></p>
<p><strong>sshlogin</strong>
<code>#!/usr/bin/expect -f

# set Variables

# set password [lindex $argv 0]
set host [lindex $argv 0]
set scriptname [lindex $argv 1]
set timeout -1
# now connect to remote UNIX box (ipaddr) with given script to execute
spawn ssh -p 22 $host $scriptname
match_max 100000

expect {
       -re ".*Are.*.*yes.*no.*" {
       send "yes\n"
        expect {
          "&gt;" { }
          "$" { }
        }
       exp_continue
       #look for the password prompt
       }

       "assword:" {
       send -- "password123\n"
        expect {
          "&gt;" { }
          "$" { }
        }
       #the expect command will now return
       }
       
       default {
        send_user "Login failed\n"
        exit
       }
}

sleep 2
send_user "Finished\n"
exit</code></p>
<p><strong>rsync.secret</strong>
<code>password123</code></p>
<ul>
<li>For the Target machine we&#8217;ll need a CMD and VB Script, as well as a configuration file for the rSync daemon.</li>
<li>Volume shadow copies in XP and Vista are temporary and only exist as long as the process that created it exists.  In our case the process that creates the volume shadow copy is vshadow.exe (Windows 2003 users can create a persistent volume shadow copy).  Fortunately, vshadow.exe allows us to send it a CMD script to execute &#8211; hence the purpose of vsrsync.cmd below.  vsrsync.cmd executes after the volume shadow copy is created but before it is destroyed.  During this time we need to use dosdev to map the volume shadow copy to a standard Windows drive letter that rSync can read from.  Next, it will create the rSync daemon using a configuration file and secrets file.  And finally, after the remote script kills the rSync daemon process, the CMD script will unmap the volume shadow copy drive letter.</li>
<li>Because we need to initiate the rSync transfer after the volume shadow copy is created but before it is destroyed, we need a small VB Script that halts the remote script from executing until it detects the daemon is ready to begin the transfer.  It performs this check by watching for the rSyncd pid file.</li>
</ul>
<p><strong>rsyncd.secrets</strong>
<code>Administrator:password123</code></p>
<p><strong>sleep-rsyncd.vbs</strong>
<code>Const Flag = "C:\Program Files\cwRsync\home\Administrator\rsyncd.pid"

While DoesFileExist(Flag)=0
   wscript.sleep 10000
Wend

function DoesFileExist(FilePath)
Dim fso
   Set fso = CreateObject("Scripting.FileSystemObject")
   if not fso.FileExists(FilePath) then
      DoesFileExist = 0
   else
      DoesFileExist = 1
   end if
   Set fso = Nothing
end function</code></p>
<p><strong>vsrsync.cmd</strong>
<code>@ECHO OFF
call vss-setvar.cmd

SET PATH=%PATH%;"C:\Program Files\cwRsync\bin"

dosdev X: %SHADOW_DEVICE_1%
rsync --daemon --config=rsyncd.conf --no-detach
dosdev -r -d X:</code></p>
<p><strong>rsyncd.conf</strong>
<code>use chroot = false
strict modes = false
pid file = rsyncd.pid
[C]
path = /cygdrive/X/
read only = yes
ignore nonreadable = yes
hosts allow = 192.168.1.2
auth users = Administrator
secrets file = rsyncd.secrets</code></p>
<p>I hope this guide provided some help to anyone wanting to setup something similar.  My setup is largely based on the one covered at <a href="http://www.goodjobsucking.com/?p=62">http://www.goodjobsucking.com/?p=62</a></p>
<h3>Additional notes</h3>
<ul>
<li>If you have files with special characters in the file name, you may need to upgrade your Cygwin DLL to the Unicode aware version.
<ul>
<li><a href="http://phaq.phunsites.net/2006/10/28/interoperability-problems-samba-windows-rsync-and-unicode/">http://phaq.phunsites.net/2006/10/28/interoperability-problems-samba-windows-rsync-and-unicode/</a></li>
<li><a href="http://www.okisoft.co.jp/esc/utf8-cygwin/">http://www.okisoft.co.jp/esc/utf8-cygwin/</a></li>
</ul>
</li>
<li>There are a lot of moving parts in the above script.  If something hangs or you just need to abort and try again you may need to reboot the Windows machine to ensure all the pieces are ready for another trial.  In my experience, however, killing the rSync process from Task Manager was frequently enough to bring the entire script back to a state where I could try another test run.</li>
<li>cwRsync will simply abort execution if the pid file already exists.  My script has an extra delete before vshadow.exe is called to try and avoid this problem.</li>
<li>vshadow.exe will fail on XP and Vista if another instance of it is already running on the same volume.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Multiplatform Backup Solution with rSync: Part 1</title>
		<link>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-1/</link>
		<comments>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-1/#comments</comments>
		<pubDate>Sun, 21 Dec 2008 04:16:17 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=160</guid>
		<description><![CDATA[A long time ago I used to be very good at making regular backups of my system. It was a very manual process &#8211; I didn&#8217;t use any software. I simply kept my files in a few places and periodically synced the folders up with a second computer. It worked well but I have a [...]]]></description>
			<content:encoded><![CDATA[<p>A long time ago I used to be very good at making regular backups of my system.  It was a very manual process &#8211; I didn&#8217;t use any software.  I simply kept my files in a few places and periodically synced the folders up with a second computer.  It worked well but I have a lot more than a few megabytes of data now, and more than one computer with data to backup.</p>
<p>For my personal computer, I have used file sync tools like <a href="http://www.2brightsparks.com/downloads.html">SyncBack</a> to maintain a mirror of my documents on an external hard drive.  However, with a web server and other computers in my network a more centralized approach became very appealing.</p>
<p>Having a spare computer lying around and enough money to invest in a pair of hard drives I set out to give an old PC a new purpose in life &#8211; to become my network&#8217;s dedicated backup server.  I didn&#8217;t want to have to maintain scheduling policies on each machine (what a pain) so I also wanted my server to be able to pull backups directly from each computer in my network.  Additionally, I wanted to keep the option of setting up the backup server in a remote location to further protect my data &#8211; so Samba was something I wanted to avoid, if possible.</p>
<p>At first I was drawn to a project called <a href="http://lifehacker.com/362062/create-your-own-cross+platform-backup-server">RESTORE</a> which is an easy to get rolling multiplatform backup system built on Xubuntu.  I had difficulty getting it to backup a Windows system, however.  SFTP to a Windows machine seemed to be broken and Windows share connections was not reliable.  And again, I preferred to stay away from Windows shares anyhow.</p>
<p>So I turned my attention to an old tool in the *nix world known as rSync.  My friend at <a href="http://benford.bluhelix.com/">Benford Does Stuff</a> pointed me to the tool.  He setup a backup server that used rSync to mirror a web server we used to maintain at our University.  After sending me to a pair of HowTo guides I was well on my way to scripting my own incremental snapshot backup of my web server.</p>
<p><strong>You may find the guides below</strong></p>
<ul>
<li> <a href="http://www.howtoforge.com/mirroring_with_rsync">Mirror Your Web Site With rsync</a></li>
<li><a href="http://www.howtoforge.com/rsync_incremental_snapshot_backups">Create Incremental Snapshot-style Backups With rSync And SSH</a></li>
</ul>
<p>The above solution works great and I am using exactly that to snapshot my web server running Ubuntu Server 8.04.</p>
<p>With some minor tweaking the above script will snapshot a Windows-based computer decently.  In particular, however, the script falls short when attempting to backup files that are currently open by the user or operating system.  Open files on a Windows system are locked and cannot be read by other applications.  There is a resolution but instructions and examples are rare, and I spent a considerable amount of time getting it working right in my setup.  In my next article I will detail the modifications I made to Stephan Jau&#8217;s incremental snapshot script to mirror my windows systems.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/12/a-multiplatform-backup-solution-with-rsync-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More Memory!</title>
		<link>http://www2.bluhelix.com:81/2008/11/more-memory/</link>
		<comments>http://www2.bluhelix.com:81/2008/11/more-memory/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 04:30:21 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=158</guid>
		<description><![CDATA[The last of the scheduled hardware upgrades for a while has just completed. The total memory on the server has been extended to an even 2.0 GB. Quite a change from 3 years ago when we ran the server on a windows machine with 92 MB of RAM]]></description>
			<content:encoded><![CDATA[<p>The last of the scheduled hardware upgrades for a while has just completed.  The total memory on the server has been extended to an even 2.0 GB.</p>
<p>Quite a change from 3 years ago when we ran the server on a windows machine with 92 MB of RAM <img src='http://www2.bluhelix.com:81/wordpress/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/11/more-memory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgraded</title>
		<link>http://www2.bluhelix.com:81/2008/09/upgraded/</link>
		<comments>http://www2.bluhelix.com:81/2008/09/upgraded/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 14:21:08 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=154</guid>
		<description><![CDATA[Very covert-like, this server was completely rebuild on 9/20 without any posts announcing it! Alright, so news has been incredibly dry around here for some time. Just take a look around and everything is about boring servers. Sorry folks, it will probably be a bit before anything exciting happens. However, the server upgrade is nice. [...]]]></description>
			<content:encoded><![CDATA[<p>Very covert-like, this server was completely rebuild on 9/20 without any posts announcing it!  Alright, so news has been incredibly dry around here for some time.  Just take a look around and everything is about boring servers.  Sorry folks, it will probably be a bit before anything exciting happens.</p>
<p>However, the server upgrade is <em>nice</em>.  It now runs on a hyper threaded P4 clocking at 2.8 GHz.  That&#8217;s twice as fast as the previous CPU in clock speed alone.  I also threw in two extra sticks of RAM since the new motherboard has two slots more than the previous system.  We&#8217;re only at 1.5 GB RAM at this point but I&#8217;m looking into upgrades.  Incidentally, the new motherboard only has SATA connectors so I had to toss out the old hard drives and add a single large-ish one.  So the server got a bit of unplanned capacity in the upgrade as well.</p>
<p>We are in the process of gearing our second linux server.  More (boring) information to come.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/09/upgraded/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Server Accessibility</title>
		<link>http://www2.bluhelix.com:81/2008/08/server-accessibility/</link>
		<comments>http://www2.bluhelix.com:81/2008/08/server-accessibility/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 00:45:37 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=150</guid>
		<description><![CDATA[No our server is not dying. But my IP updater is. I am working on it.]]></description>
			<content:encoded><![CDATA[<p>No our server is not dying.  But my IP updater is.  I am working on it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/08/server-accessibility/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Of WordPress and RPG&#8217;s</title>
		<link>http://www2.bluhelix.com:81/2008/02/of-wordpress-and-rpgs/</link>
		<comments>http://www2.bluhelix.com:81/2008/02/of-wordpress-and-rpgs/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 00:00:11 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=146</guid>
		<description><![CDATA[Hey all, It has been awefully quiet at BluHelix, and I appologize.  Lots and lots of things have been creeping into my to-do list but only a handfull of things are actually progressing at the moment. Among the changes I&#8217;m tossing around are a number of site upgrades, including a overhall of the sub-domain mechanics [...]]]></description>
			<content:encoded><![CDATA[<p>Hey all,</p>
<p>It has been awefully quiet at BluHelix, and I appologize.  Lots and lots of things have been creeping into my to-do list but only a handfull of things are actually progressing at the moment.</p>
<p>Among the changes I&#8217;m tossing around are a number of site upgrades, including a overhall of the sub-domain mechanics (consolidation and streamlining, with a possible extension to allow users to access their own settings!), as well as, duh duh duh, WordPress integration.  Ben at <a href="http://benford.bluhelix.com/">http://benford.bluhelix.com/</a> has successfully deployed a WordPress engine already on the Czin server and I have been considering doing the same.  This would do away with the sometimes clunky forum integration and ease the transition to phpBB3.  I&#8217;m not sure if there would be any historical postings.  Perhaps there will.  Anyway this might be a long ways off, but it&#8217;s something on the list.</p>
<p>Also on the list &#8211; Kevin has given me a copy of RPG Maker XP that is Vista compatible!  The question is: Resurrect my current project or start anew.  It&#8217;s a question I&#8217;m continuously debating and would like to hear feedback on.  My former project made the increadible milestone of 50% maps complete (which is not to be confused with 50% complete).  Any thoughts?  If this spurs interest I might post the old projects page on this from last year.  Currently, only the screen shots are accessible.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2008/02/of-wordpress-and-rpgs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updates and&#8230; updates</title>
		<link>http://www2.bluhelix.com:81/2007/11/updates-and-updates/</link>
		<comments>http://www2.bluhelix.com:81/2007/11/updates-and-updates/#comments</comments>
		<pubDate>Wed, 14 Nov 2007 05:21:01 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=138</guid>
		<description><![CDATA[First on the updates agenda, I uploaded new versions of both my Content Negotiation class (which is renamed to Content Negotiator) and shorten_text. Very minor changes, mostly just the before-mentioned name change and I changed my double quotes back to single quotes. I had been using single quotes throughout my time at the Berglund Center [...]]]></description>
			<content:encoded><![CDATA[<p>First on the updates agenda, I uploaded new versions of both my Content Negotiation class (which is renamed to Content Negotiator) and shorten_text.  Very minor changes, mostly just the before-mentioned name change and I changed my double quotes <em>back</em> to single quotes.  I had been using single quotes throughout my time at the Berglund Center and began moving to double quotes.  But then I read an article saying single quotes are faster and I felt kind of foolish.  I just wish the newline escape was supported.  I mean seriously, that&#8217;s like the only disallowed escape sequence I ever try to use!</p>
<p>The next item on the agenda is regarding the eventual update to this web site.  Yup, if you have not already heard, I am going to update the <strong>BluHelix Studios</strong> web site soon (TM).  But while this is still in the drafting stage I wanted to pose a question to you, my one (more?) reader.  Is the calendar useful at all?  Has anyone actually browsed to it?  The calendar used to be tied into my front page and show a &#8220;what&#8217;s coming up this week&#8221; box.  Unfortunately the script for the box was buggy and so I disabled it, but the calendar remains functional.  Anyway, I see three possibilities:</p>
<ol>
<li> Keep the same calendar system, with possible code upgrades</li>
<li>Ditch the custom calendar and tie in a professional web-based one, either an open source PHP solution or a Google integration.</li>
<li>Forget the calendar entirely.</li>
</ol>
<p>Note that I don&#8217;t expect option 2 to be difficult &#8211; we&#8217;d just lose the single-sign-in model.</p>
<p>Please post comments in the forum.  I would make a poll but I fear I just don&#8217;t have the visitor base for it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2007/11/updates-and-updates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Content Negotiation</title>
		<link>http://www2.bluhelix.com:81/2007/11/content-negotiation/</link>
		<comments>http://www2.bluhelix.com:81/2007/11/content-negotiation/#comments</comments>
		<pubDate>Sat, 03 Nov 2007 07:06:42 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>
		<category><![CDATA[Studio Announcement]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=130</guid>
		<description><![CDATA[I am quietly at work planning out my re-design for BluHelix Studios. While one of my goals is to migrate to a system bearing a resemblance to the header/footer system I created for the Berglund Center sites, I have also been meaning to do something else. XHTML. What? Hold it! But you thought BluHelix Studios [...]]]></description>
			<content:encoded><![CDATA[<p>I am quietly at work planning out my re-design for BluHelix Studios.  While one of my goals is to migrate to a system bearing a resemblance to the header/footer system I created for the Berglund Center sites, I have also been meaning to do something else.</p>
<p>XHTML.</p>
<p>What? Hold it! But you thought BluHelix Studios already used XHTML! Isn&#8217;t there a DOCTYPE right now for XHTML 1.0 Transitional?</p>
<p>Well, yes and no.  See, there is a dirty little secret to many of the WWW&#8217;s XHTML web sites: they are really serving your browsers malformed, error-inducing HTML documents.  The errors, of course, are simply XHTML tags that the HTML parser is choking on because they are not part of the HTML specification.  You see, the XHTML DOCTYPE is only used when validated a page (and for setting IE in compliance mode), it is really the MIME type of <em>application/xhtml+xml</em> and the many variants that define an XHTML document.</p>
<p>The reason why these &#8220;real&#8221; XHTML documents are so rarely served is because the most popular browser in the world is not equipped to parse XHTML documents.  IE7 is at least <a href="http://blog.codedread.com/archives/2005/09/16/ie7-will-not-support-applicationxmlxhtml/">slightly better</a>.  Previous versions wouldn&#8217;t have a clue what to do with the non <em>text/html</em> MIME type and would spawn a download prompt as if you were trying to download a ZIP, EXE, etc.  IE7 will successfully display the page &#8211; but using its HTML parser.</p>
<p>Other popular browsers like Firefox, Opera, and Safari are equipped with XML parsers.</p>
<p>So, at first it might seem that serving &#8220;real&#8221; XHTML documents means alienating 85%-90% of your user base.  Luckily there is a technique to, literally, get both worlds.  The solution: content negotiation.</p>
<p>Content negotiation is the process whereby the user agent (your browser in most cases) communicates to the server informing it of the technologies it understands and even which ones it prefers.  The server responds by sending it content in the format the user agent prefers.  This is actually a really cool idea, and if you read up on XHTML 2.0 it appears that this kind of handshaking will eventually be integrated into the technology itself and be very trivial to do.  But for now we must resort to scripting.</p>
<p>There are two approaches to this: setting up those super-rad Apache/IIS URL rewriting to serve the content most appropriate for the requesting user agent.  Or, this functionality can be done through server-side scripts.  I chose the latter and coded up a PHP class to preform XHTML/HTML content negotiating.  This script is pretty easy to use and preforms about a dozen regular expressions on the output buffer in an attempt to transform markup to XHTML and HTML, depending on the needs of the requesting user agent.</p>
<p>The usage is simple.  Just instantiate the class by giving the constructor the type of document you would prefer to transmit, then add style sheets to the class, call the pro log method just before content output, call the style sheet method inside the head tag, and call the finalize method at the bottom of the page.  Done.</p>
<p>I commented both the script and test file for your convenience.  You may download the script <a href="http://www.bluhelix.com/pub/php/classes/contentnegotiator.zip">here</a>.</p>
<p>This is not the only application of content negotiation.  Another common use is to chose between PNG and GIF images, depending on the capabilities of the user agent.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2007/11/content-negotiation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Living behind a proxy</title>
		<link>http://www2.bluhelix.com:81/2007/11/living-behind-a-proxy/</link>
		<comments>http://www2.bluhelix.com:81/2007/11/living-behind-a-proxy/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 04:57:58 +0000</pubDate>
		<dc:creator>Unknown8063</dc:creator>
				<category><![CDATA[Inside BluHelix]]></category>

		<guid isPermaLink="false">http://blog.bluhelix.com/?p=128</guid>
		<description><![CDATA[This is the beginning of another series of comments &#8211; there will be at least one more I will post tomorrow, perhaps a third. If you are reading this posting chances are you are not connected to my Czin web server. As mentioned in the previous post, most of this site now lives being a [...]]]></description>
			<content:encoded><![CDATA[<p>This is the beginning of another series of comments &#8211; there will be at least one more I will post tomorrow, perhaps a third.</p>
<p>If you are reading this posting chances are you are not connected to my Czin web server.  As mentioned in the previous post, most of this site now lives being a proxy server located at Pacific University.  Yeah, it makes things a little slow since your packets have to traverse the Internet twice &#8211; but it continues to run pretty smoothly.</p>
<p>I have begun locking down direct access to Czin &#8211; although I deliberately maintained a &#8220;back door&#8221; via the old URLs of <a href="http://unknown8063.homeip.net:88/">http://unknown8063.homeip.net:88/</a> and <a href="http://bluhelix.homeip.net:88/">http://bluhelix.homeip.net:88/</a>.  These URLs will remain active for at least the rest of the year.  The primary reason is that I will have to update <a href="http://www.bluhelix.com/projects/rocketlander/">RocketLander</a> before I shut down the old URLs.</p>
<p>Migrating my many web sites to the new server topology has been a challenge.  The greatest problem to overcome was that several of my server scripts use server variables to detect their location on the server.  These techniques were employed to maintain generalization and to enable greater portability.  However these techniques backfired when the server was no longer &#8220;visible&#8221; to the user, but rather to another server.  Suddenly these techniques caused the page to &#8220;pop out&#8221; of the proxy.  No good.  Luckily I found a clever and almost invisible hack.  Since these issues are by definition caused by server-side scripting I merely set a directive to force apache to perpend a small script to the top of all server-scripted pages.  This script does an awful and yet brilliant thing.  It abuses PHP&#8217;s lack of constants by overwriting key server variables with their &#8220;expected&#8221; values.  Even better, the script does this intelligently enough that it leaves pages alone if they are being viewed directly by the user.</p>
<p>Thus, using this technique my server can be accessed both through the proxy and directly even though the URL-space is different.</p>
<p>The techniques described didn&#8217;t work on everything, however.  My photo gallery proved to be extra special.  By modifying the configuration file I was able to resolve most of the problems but certain scripts (like the login/logout functions) refuse to use the correct URL.  The gallery&#8217;s attempt to be smart is its own downfall.  Ultimately I had to add a redirect that catches the photo gallery when it goofs.  The result is extra server calls and I hope it&#8217;s merely temporary.</p>
<p>For those wondering why I care about being able to access my server directly at all, consider the example of development work.  This is a bad example because I do typically use the external URL anyway, but still, I prefer to leave the option open.</p>
<h3>Proxy configuration and directory organization</h3>
<p>The proxy technique I came up with is actually really simple and intentionally so.  My goal was to make the proxy server (hosted at Pacific University) as simple and &#8220;dumb&#8221; as possible.  The only way to commit changes over there is restart the server and unlike mine they actually receive a fair amount of traffic.  It is not acceptable for me to be rebooting their Apache service.  In other words, I wanted to be able to create an arbitrary amount of subdomains and have the proxy server &#8220;just work&#8221; for all of them without any additional configuration.</p>
<p>The solution is mod_rewrite.  Oh how I used to hate this module and now I am using it like mad, everywhere.  With a wild card in the virtual host I setup the server at Pacific to accept all requests from <strong>*.bluhelix.com</strong>.  Then mod_rewrite steps in the capture the subdomain (or the lack of) and choses a URL accordingly. Except for the case of no subdomain, the virtual server proxies to my server at http://czin.bluhelix.com:88/subdomain/.  Nothing to it.</p>
<p>So the proxy server doesn&#8217;t need any configuration. Period. It doesnt care at all if there is actually something there where it sends it.  But my server of course does.  But this isn&#8217;t bad either.  I merely need to (a) create a folder with the exact name of the subdomain, or (b) create rewrite rules of my own to fix the URL to something that exists.  An example is when users access the WWW subdomain.  There is no folder on my server by that name, mod_rewrite changes it behind the scenes to line up with the folder bhs.  In case you&#8217;re wondering, the system is generic enough to handle multiple subdomains, however in this case it still maps to only one folder (subdomain1.subdomain2).  However I would be free to rewrite this request on my end for maximum flexibility.</p>
<p>To get a feel for what is going on, try accessing <a href="http://czin.bluhelix.com:88/gallery/v/Bluhelix/RPG_Point_5/">http://czin.bluhelix.com:88/gallery/v/Bluhelix/RPG_Point_5/</a> and note what happens to the URL.</p>
<p>A couple notes about <strong>server-relative</strong> URLs:</p>
<p>While I have not tested these fully, you may encounter unexpected results stemming from the fact that the server-side scripts are going to see a different server root than the client.  I suggest sticking with document-relative URLs for ALL purposes on my server because they are simply going to produce more success.  If you must, realize that server-side scripts see the &#8220;real&#8221; server root, which is typically one folder down from where the client &#8220;thinks&#8221; it is.  Hyperlinks and client scripts will tend to go with what you see &#8211; which makes sense since they are executing from your viewpoint, not the server&#8217;s.  So if your site is located at mysite.bluhelix.com, you server scripts will see the index.php page at <strong>/mysite/index.php</strong> while a hyperlink will find it at <strong>/index.php</strong>.  A significant disadvantage to using server-relative URLs is that you will effectively break your site when viewed outside the proxy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www2.bluhelix.com:81/2007/11/living-behind-a-proxy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
