macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Build Your Own Blogging Application, Part 2
Pages: 1, 2

Copying Image Files to the iDisk

Remember that note we made about being able to rename our image files (specified with an absolute path) relative to their location on the iDisk? This is it! Below is the complete script. I've added statements to remove spaces from the path and filename and to copy the image files to a location designated by the last argument given to the script.

The first argument is used by the <> (diamond) operator. The diamond operator reads lines from the filenames contained in the command line arguments array with the exception of the last one, which we removed with the pop operator. In this case, we only need to specify two arguments: the filename for the diamond operator to process and the location to copy the updated file. The first argument is the file newentry referenced in the editor.tcl script, and the last argument is the directory to copy the modified file. In our case, this directory is our iDisk directory, which we can access as a local mount point (more on that in just a moment).

#!/usr/bin/perl
#usage: %processImages inputFile copyLocation

#pop the copy location off of ARGV 
#before the diamond operator gets it
$copyLocation = pop(@ARGV);

#edit file in place and backup the original
local $^I = ".bak"; 
while (<>) {
	if (m/<img src='(.*\/)(.*?)'(.*) \/>/) {
		$filePath = $1;
		$fileName = $2;

	    s/<img src='(.*\/)(.*?)'(.*) \/>/<img src='$fileName'$3 \/>/;
		$filePath =~ s/ /\\ /g;
		$fileName =~ s/ /\\ /g;
		system "cp $filePath$fileName $copyLocation";
	}
  print "$_"; #write lines back to the file
}

A Convention for Organizing a Simple Blog

One last thing to do is to design a convention for organizing the multiple entries that will be written to the blog. A simple approach is to append the newest entry to the top of the blog with each post. To do this, we need only define the boundaries of the blog's content and how to separate the entries. An elaborate implementation in XML with XSLT is the industrial strength solution, but a much simpler solution, which serves our purpose, is available by using XHTML comment tags to designate these boundaries.

Let's agree on the following convention for our simple XHTML-based blog entries.

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head><title>Sample Blog Format</title></head>
<body>
<!--STARTBLOG-->
<!--ENDBLOG-->
</body>
</html>

The most relevant part to our application is the text enclosed between the body tags of the page. You can feel free to use whatever XHTML features or styles you'd like to spice other things up. HTML features will work as well, but based on our previous discussion, XHTML is the wave of the future, and it's really worth it to go the extra mile. No matter which decision you make, be aware of the decision's impact on the longevity and display of your site.

If you log into your .Mac account and go to your homepage section, you're presented with a lot of nice layouts for your page. If you click on the advanced tab, you're able to select an external HTML page like the very simple (and boring) one presented above. All that is required is that you copy the page to the Sites folder of your iDisk, which you can navigate to using Finder or in the terminal at /Volumes/<.Mac username>/Sites. A much more interesting option, however, is to choose your favorite layout already designed by the .Mac gurus, salvage out the parts like the 'Send me a message button' and the counter, and insert the lines

<!--STARTBLOG--> <!--ENDBLOG-->

just inside the body tags so that the blogging app will know where to post entries. Note that depending on how much of the page you do or don't salvage, your Document Type Definition may change from XHTML document version to some version of HTML. For example, if you view the source of the standard pages included with your .Mac membership, you'll notice the following line at the top of the page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

This is obviously an HTML 3.2 compliant document, which is different from the tag at the top of the sample file that specified the XHTML 1.0 Transitional Document Type. More specifics about the XHTML document types can be found at W3Schools.

Since the Perl code for this task is much more intuitive than the previous Tcl/Tk code we developed, I've included inline comments in lieu of a separate discussion. Examine this file and think about how it fits into the project. Remember that the Perl man pages are always there if you need them.

#!/usr/bin/perl
#The blog entry must be contained in a file 
#entitled "newentry"
#-------------------------------------------------

#some special values used in writing the entry
my $startTag 		="<!--STARTBLOG-->";
my $endTag   		="<!--ENDBLOG-->";
my $startEntry		="<!--STARTENTRY-->";
my $endEntry  		="<!--ENDENTRY-->";

#----------------------------------------------
#get a timestamp of the form MMDDYYYYHHMMSS
#----------------------------------------------
sub getTimeStamp {
	# Get the all the values for current time
	($Second, $Minute, $Hour, $Day, $Month, 
	 	$Year, $WeekDay, $DayOfYear, $IsDST) = 
		localtime(time);

	#months start at 0, so increment by 1
	$Month += 1;

	#pad with a 0 if necessary
	if ($Month < 10) {$Month = "0" . $Month;}

	#don't need to increment day but must pad it
	if ($Day < 10) {$Day = "0" . $Day;}

	#do the same for the hour, minute, and second
	if ($Hour < 10) {$Hour = "0" . $Hour;}
	if ($Minute < 10) {$Minute = "0" . $Minute;}
	if ($Second < 10) {$Second = "0" . $Second;}

	#add 1900 to the year
	$Year += 1900;

	#return value is the last value computed
	#in a Perl subroutine
	my $returnValue= $Month . $Day .$Year . 
	   $Hour . $Minute . $Second; 
}

#----------------------------------------------
#get a timestamp of the form MM-DD-YYYY HH:MM
#----------------------------------------------
sub getFormattedTimeStamp {
    # Get the all the values for current time
    ($Second, $Minute, $Hour, $Day, $Month, 
     $Year, $WeekDay, $DayOfYear, $IsDST) = 
	localtime(time);

    #months start at 0, so increment by 1
    $Month += 1;


    #do the same for the minute, and second
    if ($Minute < 10) {$Minute = "0" . $Minute;}

    #add 1900 to the year
    $Year += 1900;

    #return value is the last value computed
    my $returnValue= $Month . "-" . $Day. "-" . 
       $Year . " " . $Hour . ":" . $Minute;
}


#-------------------------------------------------
#wrap the time stamp between its tags
#-------------------------------------------------
sub wrapTimeStamp {
	#last value computed is the value returned
	my $returnValue = "<!--TIME" . &getTimeStamp .
   		"-->";
}

#------------------------------------------------
#open a file handle, get the input and wrap it 
#in the appropriate tags
#------------------------------------------------
sub getNewEntry {
	my $returnValue = ''; 
	open NEWENTRY, "newentry";
	while (<NEWENTRY>) {
		$returnValue = "$returnValue" . "$_";
	}
	close NEWENTRY;

	#last calc performed is automatically the 
	#return value, but first replace any \n 
	#with <br />\n

	$returnValue =~ s/\n/<br \/>\n/g;
	$returnValue = 
		"$startEntry\n" . &wrapTimeStamp . 
	    "\n" . &getBlogHeader . 
		"\n<p>$returnValue</p>\n" . 
		"$endEntry\n";
}


#-------------------------------------------------
#a blog header that separates entries
#-------------------------------------------------
sub getBlogHeader {
	my $returnValue = "<p><hr><strong>" . 
		&getFormattedTimeStamp . "</strong></p>";
}

#-------------------------------------------------
#read through the file line by line.
#when the special tag $startTag is found, 
#insert the new entry padded with appropriate 
#tags. Then continue processing the rest of the 
#file
#-------------------------------------------------

local $^I = '.bak';	#edit file in place and backup
while (<>) {
	print "$_";
	if (/$startTag/) {
		print  "\n" . &getNewEntry . "\n";
	}
}

Putting It All Together

Related Reading

Learning Perl Objects, References, and Modules
By Randal L. Schwartz

Without further adieu, here is the sprinkle of Bash, script updateBlog.sh, that was promised from the last article, the last piece of information you need to make your blogging app functional. It's intended to be an executable Bash script, so you'll need to type chmod u+x updateBlog.sh in your terminal while in the same directory as this file. Repeat those steps for processImages.pl and postEntry.pl. The script updateBlog.sh simply acts as glue for the two perl scripts by executing and passing arguments into them.

To put it all together one last time, do the following things to post your first entry to your blogging app:

  1. Copy updateBlog.sh, processImages.pl, postEntry.pl, and editor.tcl to the same directory, making sure executable permissions are set on the first three files. You'll also need write permissions to the directory in which you place these files.
  2. Either use the sample XHTML file provided or create your own by salvaging features from ones on .Mac. Ensure this file is copied to your iDisk and specified in updateBlog.sh
  3. Ensure your iDisk is mounted; it may not be mounted if you've recently rebooted.
  4. Fire up editor.tcl in your terminal by typing wish editor.tcl, making sure your paths are set up to point to the version of the Wish shell you've chosen.
  5. Type some text in your editor, mark it up, add some reasonably sized images, and post the entry. If everything worked without error, your blog entry is now available for the world to view. Type the URL of your webpage into your browser and see for yourself.

Final Thoughts

Wow! You've learned a lot and now have a blogging application you can use to muse poetry, found your own technology forum, or whisper your feelings to the world. Using your newly honed skills and building blocks of this project, you are empowered to make your application as elaborate as you like. Add in some JavaScript to produce a calendar to navigate your blog or go out and learn about Cascading Style Sheets in order to produce a higher quality display for your readers. You could also use you new friend Perl to organize blog entries into weekly sections and to introduce a navigation bar allowing users to provide an alternative to scrolling down one really long page.

Matthew Russell is a computer scientist from middle Tennessee; and serves Digital Reasoning Systems as the Director of Advanced Technology. Hacking and writing are two activities essential to his renaissance man regimen.


Return to the Mac DevCenter