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 |
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:
- 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.
- 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
- Ensure your iDisk is mounted; it may not be mounted if you've recently rebooted.
- 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. - 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
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 9 of 9.
-
Script updateBlog.sh
2004-11-12 18:04:04 Matthew Russell |
[Reply | View]
-
Script updateBlog.sh
2004-12-19 19:20:34 manuelderieux [Reply | View]
I get the following errors:
./updateBlog.sh: line 13: processImages.pl: command not found
./updateBlog.sh: line 17: postEntry.pl: command not found
./updateBlog.sh: line 13: processImages.pl: command not found
./updateBlog.sh: line 17: postEntry.pl: command not found
while executing
"exec ./updateBlog.sh"
(procedure "WriteToBlog" line 7)
invoked from within
"WriteToBlog"
(procedure "WriteToBlogQuit" line 2)
invoked from within
"WriteToBlogQuit"
(menu invoke)
Here's my updateBlog.sh:
#!/bin/bash
#Glue for the perl scripts
#configuration settings
export BLOG_PATH=/Manuel
export BLOG_PAGE=sampleFormat.html
export BLOG_ENTRY=newentry
#update the image tags in file 'newentry' and
#copy the image files to the iDisk
./processImages.pl $BLOG_ENTRY $BLOG_PATH
#execute the read.pl script and pass args.
./postEntry.pl $BLOG_PATH/$BLOG_PAGE
Any help would be appreciated -
Script updateBlog.sh
2004-12-19 19:32:51 Matthew Russell |
[Reply | View]
Bash is telling you that it can't find executable files by the names of processImages.pl or postEntry.pl in the current directory (the same one that updateBlog.sh is located in)
One of three things is extremely likely:
1) Those files are simply not in the same directory as updateBlog.sh, or
2) You've misspelled their their names/forgot an extension, or most likely:
3) You don't have executable permissions set on these files and therefore it can't 'find' them because they're not 'commands'. To check permissions, type 'ls -al <filename>' and make sure that you see at least one 'x' in the output. Do a 'man ls' for more info on exactly what the output means.
Let me know how it goes.
Matthew -
Script updateBlog.sh
2004-12-20 07:50:40 manuelderieux [Reply | View]
Your points 2 & 3 were my downfall, it's part of the arrogance of considering myself precise.
Thank you. -
Script updateBlog.sh
2004-12-20 07:54:43 Matthew Russell |
[Reply | View]
No sweat. We've all done it and are bound to do it again. Path and permissions related issues are probably 90% of the problems I've ever had to work through.
Matthew
-
Color me intrigued
2004-11-12 16:53:56 restiffbard [Reply | View]
do you have an example of this in action that I could see before I go headlong into writing up the code for the week it will take to get it right? (not cause it's hard, I just make more mistakes) If not that's ok. I certainly do appreciate the article. Looks like it could be fun and a great way to learn a few things I didn't know before. -
Color me intrigued
2004-11-12 17:58:17 Matthew Russell |
[Reply | View]
Thanks for your comment.
<br/><br/>
About the most action I can show you is the screenshot in part 1 of this article. The user interface as presented is really simple: just a text editor look-and-feel with some menus. The engine works behind the scenes and there's nothing to 'see.'
<br/><br/>
As presented, this is pretty simple, but there's a whole lot you can do to make it as elaborate as you'd like. I suggest working up incrementally. -
Color me intrigued
2004-11-13 16:00:43 restiffbard [Reply | View]
Great stuff. I've put it all together. My understanding of Perl is pretty dang limited to what I've learned doing this but you've given me a starting point to work from.
This little app has already given me a bunch of ideas for how I can extend it for my own uses. So, thanks. This is exactly the sort of article I'd like to see more of. -
Color me intrigued
2004-11-13 16:07:28 Matthew Russell |
[Reply | View]
It is my sincere pleasure to have helped you. If you need help on any of those additional ideas, don't hesitate to post them here and I'll try and help you and the rest of the readers take it to the next level...for that matter feel free to post your ideas even if you don't need help--share the knowledge!






My apologies. You need script updateBlog.sh to make your blog functional. It is inserted below for your convenience. I'm sorry it's not inline in the article above. Hopefully, the script tags around it will preserve its structure for you.
#!/bin/bash
#Glue for the perl scripts
#configuration settings
export BLOG_PATH=/Volumes/<insert your .Mac username here>/Sites
export BLOG_PAGE=sampleFormat.html
export BLOG_ENTRY=newentry
#update the image tags in file 'newentry' and
#copy the image files to the iDisk
./processImages.pl $BLOG_ENTRY $BLOG_PATH
#execute the read.pl script and pass args.
./postEntry.pl $BLOG_PATH/$BLOG_PAGE