Gold Plated Blog Posts
Whatev.
Monday, April 7, 2008

Lightweight PHP Picasa API Version 3.0

After weeks and weeks of toiling away at my desk in my free time, I've finally put the finishing touches on Version 3.0 of my Lightweight PHP Picasa API. I think the extra time has not been wasted, as this version is about a thousand times more robust and feature-rich than versions 1 and 2, as well as being a lot easier to use. For easy access, here are the important links:

Download the API source code

View the Documentation

View the bug and feature request list

Here I'll list the major features, and then go into greater detail on each one. Features include:

  • Automatic query building through the Picasa class
    • Pass in the parameters for your request and the member functions will build and send the query for you.
  • Robust error handling through the Picasa_Exception class
    • 8 different Exception classes that can be caught individually, all of which extend Picasa_Exception to allow any level of granularity your situation requires.
  • Easy-to-use implementation of authorizations through the Picasa class
    • Supports Client Login or AuthSub
    • Supports persistent authorizations using browser cookies
  • Added previously unsupported operations
    • Suports not only fetching feeds, but also posting and deleting images, albums, comments, and tags, as well as updating images and albums.
    • Include access to public and private albums.
  • Added several fields to existing classes
    • Added support for Exif data, GML coordinates, among others
  • Comprehensive documentation using PHPDoc
    • View the Javadoc style manual here.
  • 100% backwards compatible with versions 1 and 2
  • It's still "lightweight"
    • No special requirements, just PHP 5
    • Less than a third the size of the Zend framework
Automatic query building through the Picasa class
The Picasa class is certainly the biggest addition to the new version. It's really the only object that your client code will ever have to instantiate. It handles both authorization as well as data requests and manipulations (posting and updating images, etc). The nice part about how it handles data requests is that you'll literally never have to formulate a query string again. Pretty much any type of feed that can be requested from Picasa is supported through just a few different methods in this class. Just instantiate a Picasa object and then call the method you're looking for. For instance, to get all albums for user "goldplateddiapers" (that's me), use the following code:
$pic = new Picasa();
$albums = $pic->getAlbumsByUsername("goldplateddiapers");
Now $albums will hold a Picasa_Account object that has an array of all my albums. To see exactly what is in a Picasa_Album, you can look at the manual, or you can just print the object. I've added very handy __toString() methods for all the objects. So add this line and see what you get:
print $albums;
If you're viewing this in Firefox (which you should be!), view the page source to get a prettier display. The output should be a nicely formatted printout of every field in the object. Each one of those fields has a getter method so that you can access the data you see.

Of course, oftentimes your request will not be as simple as getting all images from one user. So each of the "get" functions in the Picasa class take a plethora of parameters to suit your needs. For instance, take a look at the definition for Picasa::getImages():
public function getImages($username=null, $maxResults=null,
$startIndex=null, $keywords=null, $tags=null,
$visibility="public", $thumbsize=null, $imgmax=null);

As you can see, none of these parameters are required. Which ones you should supply depend on what you're looking for. To find the first 250 images in Picasa tagged "lolcats", do the following:
$pic = new Picasa();
$images = $pic->getImages(null, 250, null, null, "lolcats");
Now $images will be a Picasa_ImageCollection object with an array of up to 250 of your favorite lols. The same format follows for any methods in the API starting with "get". And of course, all of the parameters for each method are fully described in the documentation.

One thing to be careful of is that all combinations are not supported by Picasa. For instance, calling just Picasa::getImages() with no parameters, Picasa itself will probably yield an error, which will be thrown as a Picasa_Exception with the error message retrieveable through Picasa_Exception::getMessage(). See the next section for more information on exception handling. I've left it up to the client code to send acceptable requests; the API will only throw an exception if Picasa itself responds with an error, the API doesn't catch invalid combinations of parameters and thus they're not documented here. You'll have to play around with different parameter combinations or check Picasa's Developer Guide.

Robust error handling through the Picasa_Exception class
The previous versions of the API didn't do much in the way of error handling, and this aspect is probably the second biggest improvement since then. There is one main exception class, called Picasa_Exception, that all exceptions thrown from the API will be at least subclassed from. It's not an abstract class, so oftentimes an instance of Picasa_Exception itself will be thrown, but a more specific subclass will be thrown when appropriate. Take a look at the subclasses in the documentation or the source code, they're all listed in the Picasa_Exception class.

The Picasa_Exception class extends PHP's Exception class and adds a few nice fields to have. The first is Picasa_Exception::$url, which will contain the offending URL if the exception resulted in a bad request to Picasa. If the exception wasn't thrown as a result of a bad request, this field will be null. The other field that can be useful is Picasa_Exception::$response, which holds the complete response that the exception was thrown as a result of, again only if the exception is thrown because of a bad request.

To give you some background on how the API knows it should throw an exception when it's given a bad request (skip this paragraph if you don't care), basically the method that is used for executing requests (Picasa::do_request()) checks for a response of 200 or 201. If that's not found, it passes the response header to a method (Picasa::getExceptionFromInvalidPost()) that determines which kind of exception to throw. It saves the error message given by Picasa as the result of Exception->getMessage(). However, sometimes the body of the response, even if it was not a 200 or 201 response code, can be useful. For example, if a client is trying to authenticate using Client Login and Picasa requests a CAPTCHA challenge, the response code is 403, but fields are set in the body identifying the URL to the CAPTCHA challenge and the CAPTCHA's token value. The API uses the Picasa_Exception::getResponse() method to get the returned response, determine that it is a CAPTCHA challenge, and parse out the required fields.

The only other exception class in the API that adds any fields to the base Exception class is Picasa_Exception_CaptchaRequiredException. This (as you might have guessed) is thrown when a CAPTCHA challenge is requested by Picasa upon attempting to gain authorization. If you're unfamiliar with this operation, Picasa will ocassionally require a user attempting to login using Client Login to type in letters that appear in a supplied image in order to guarantee that the user is a real person. To login after a CAPTCHA is requested, you do exactly what you did to log in the first time, this time passing in the user's CAPTCHA answer and a token supplied by Picasa (see the next section for how the API deals with logins and CAPTCHAs). The Picasa_Exception_CaptchaRequiredException contains the method Picasa_Exception_CaptchaRequiredException::getCaptchaUrl() for getting the URL to the image to display, the method Picasa_Exception_CaptchaRequiredException::getCaptchaToken() for getting the token to pass along with the re-attempt at authorization, and the methods Picasa_Exception_CaptchaRequiredException::getUsername() and Picasa_Exception_CaptchaRequiredException::getPassword() for getting the user's username and password that they originally used when attempting to sign in.

As an example of how to use the Picasa_Exception classes effectively, here is an example of client code attempting to log in (see the next section for details about how to use the authorization functionality, but I think you can infer what the code is generally doing). Let's assume I've just requested the user's username and password in a form, using the POST method:
// Get the username and password from the POST superglobal
$user = $_POST['username'];
$password = $_POST['password'];

$pic = new Picasa();
try{
$pic->authorizeWithClientLogin($user, $password);
} catch (Picasa_Exception_CaptchaRequiredException $ce) {
print "Please enter the letters you see in the image: ";
print '<img src="'.$ce->getCaptchaUrl().'" />';

/* Put code for generating a form with an input field, setting $ce->getCaptchaToken(),
* $ce->getUsername(), and $cd->getPassword() as hidden fields here
*/
} catch (Picasa_Exception_InvalidUsernameOrPasswordException $ie) {
print "The username or password you have entered is invalid.";

/* Put code for handling re-logins here
*/
} catch (Picasa_Exception $e) {
print "Your attempt to login has failed: ".$e->getMessage();

/* Put code for handling relogins here
*/
}
Easy-to-use implementation of authorizations through the Picasa class
Previous implementations of the Lightweight PHP Picasa API did not support authorizations in any way. This suited my needs personally, but left a lot of people out of luck or on their own to throw something together. With the addition of the Picasa class, though, comes a suite of methods and fields for gaining and keeping authorizations. The first thing you need to know about is the difference between Client Login and AuthSub. Client Login allows you to enter a user's username and password, while AuthSub requires your client to redirect the user to a Google-hosted secure page to enter their username and password. The Picasa class supports both.

To authorize a user using Client Login:
  1. Get their username and password
  2. Call Picasa::authorizeWithClientLogin(), passing in their username and password.
At this point, if the authorization was successful, you have an "authenticated" Picasa object. Now, using this Picasa object, you can do operations that the current user is authorized to do, such as accessing their private albums, posting photos and albums to their account, etc. If the authorization was unsuccessful, a Picasa_Exception is thrown. See the previous section for instructions on how to handle such exceptions.

To authorize a user using AuthSub:
  1. Redirect the user to the Google login page using Picasa::redirectToLoginPage()
  2. On the page supplied in the $next parameter or Picasa::redirectToLoginPage(), call Picasa::authorizeWithAuthSub().

These steps automate a few things that you could also do manually, depending on what your intentions are and what your server configuration gives the API access to. First, if you want to redirect the user manually, you can call Picasa::getUrlToLoginPage() just to get the URL that you should send the user to, and then redirect them using your client code however you want. Second, if the API doesn't have access to the $_GET superglobal (which the token required for Picasa::authorizeWithAuthSub() is in), you can get the "token" parameter out of the URL however you normally would and manually pass it as the first parameter in Picasa::authorizeWithAuthSub(). If it's not passed in, or null is passed instead, the method will look in the $_GET array for the token and if it's not there, throw a Picasa_Exception_FailedAuthorizationException.

A neat feature that is built into the API is persistent login through the use of cookies. Cookies are used because there's no server-side caching mechanism supplied with the API. So by default, if you authorize a Picasa object, it will store the authorization token and the type of authorization used (AuthSub or Client Login) in the users browser cookies. Tokens don't expire for quite a while, so this allows the user to login once and remain logged in as long as you like. You can use the method Picasa::authorizeFromCookie() and it will automatically look in the user's cookies for an authorization token and authorize the object if it finds one. If it doesn't, false is returned and your client code can prompt the user to login again. So here is a snippet for logging in using AuthSub:
$pic = new Picasa();
if ($pic->authorizeFromCookie() === false) {
Picasa::redirectToLoginPage("http://yourdomain.com/samplePage.php");
}
//Perform authorized requests here

On the other hand, if you don't want the API to automatically save the token to the user's cookie and you want to save it yourself in a more secure way, you can pass false as the $saveAuthorizationToCookie parameter of either Picasa::authorizeWithAuthSub() or Picasa::authorizeWithClientLogin(). The token is returned from both methods when a successful authorization is established. To then authenticate a Picasa instance, you can either pass the token along with the type of authorization (represented by the public static members Picasa::$AUTH_TYPE_AUTH_SUB and Picasa::$AUTH_TYPE_CLIENT_LOGIN) into Picasa's constructor when you instantiate it, or call Picasa::setAuthorizationInfo(), also passing in the token and type.

It should also be noted here that Picasa actually returns a "single use token", which is only good for one request, when a user attempts to login through AuthSub. However, the API automatically converts the single use token into a session token and saves that value. There is no parameter to turn that feature off because there is no downside to doing it and a single use token is too worthless to warrant another parameter.

Added previously unsupported operations
Now that authorizations are possible, so are authorized operations. I've done my best to provide pretty much any operation available through Picasa's core Data API in this PHP version. So you can post, update, or delete albums and images from an account that you have permission to do so in once you have have an authorized Picasa instance. You can also post or delete comments and tags, and retrieve private feeds.

The methods for posting, updating, and deleting are extremely similar to the methods for retrieving feeds. There are several "posting" methods, just like there are several "getter" methods described in the first section. So let's say you want to post an album titled "Dwight Schrute's One Night Stand" to the account "goldplateddiapers":
$pic = new Picasa($token, Picasa::$AUTH_TYPE_AUTH_SUB);

if ($pic->isAuthenticated()) {
try {
$album = $pic->postAlbum("goldplateddiapers", //Username
"Dwight Schrute's One Night Stand", //Title
"Dwight and Angela exchange cat pictures.", //Summary
"private", //Access rights
"false" //Commenting enabled
);
} catch (Picasa_Exception_UnauthorizedException $ue) {
print ("You are not authorized to add this album.");
} catch (Picasa_Exception $e) {
print ("An error occured while posting the album: ".$e->getMessage());
}
} else {
Picasa::redirectToLoginPage("http://yourdomain.com/samplePage.php");
}
Yeah, I know, the parameter list gets a little ridiculous. However, I've tried to order them in such a way that they will be as short as possible. For instance, had I wanted that album to be public and allow commenting, I could have left off the last two parameters.

Now that you know how to post an album, posting images, comments, and tags are all done the exact same way, though the parameter list varies. You can also update albums and images, although Picasa doesn't allow comments or tags to be updated. Deleting is allowed for all four types of objects. Read the documentation to see exactly which parameters are accepted for each type.

Added several fields to existing classes
The most noticeable difference here is going to be in the Picasa_Image class. The amount of information that is available for each image has just about doubled. You can see that Exif data and GML information are two things that were not supported in previous versions. One thing you will have to look out for, though, is that some of the fields will be null at times. It just depends on what the Atom feed from Picasa applies. To see what fields are null while testing your client code, just print the result of Picasa::getImages() and play around with the parameter values. The __toString() method will be automatically invoked and you can get a nice view of exactly what the instantiation looks like.

There is a cool new feature for some of the getter fields, too, that alleviates some of the problem associated with the null fields. You'll notice in the past that if you request all albums for a single username, the result would have come in the form of a Picasa_Account, which would have an array of Picasa_Album objects. However, those albums would not contain any images, presumably because it would take a lot of extra time to fetch and transfer the information about each image. Now, however, the method Picasa_Album::getImages() will check to see if the $images array is null and fetch a new instance of the current image, pull out the $images array from that instance, and return it. This way, if you want the value, it will always be there. The same logic follows for Picasa_Image::getComments() and Picasa_Image::getTags().

Comprehensive documentation using PHPDoc
I've gone to great lengths to document the entire API, and I finally went through the trouble of generating the docs and hosting them. I think the documentation will be really helpful in using this API, I have literally spent hours preparing it. One thing to note is that it's split up into two packages: Picasa and Picasa_Exception; the latter can be difficult to spot from the documentation's front page, there's a link to it at the very top. You can find all the documentation here.

I did not generate documentation for the Cam folder because it is not really part of the API and shouldn't be used. I attempted to change the code inside those files to utilize the new Picasa class, but the method names and intentions didn't really make sense in the context of the new version. They're still there, for backwards compatibility sake, and they work. However, if you're a newcomer, I would certainly ignore them.

100% backwards compatible with versions 1 and 2
As with the previous versions, drop the code in where your previous code was and you should have no problem. The one caveat is that you have to have had the classes inside the Picasa folder that was provided with the old versions. That folder is no longer the topmost level, the php folder is, so be careful when doing this. And as I stated earlier, the Cam folder is included for backwards compatibility.

It's still "lightweight"
It really depends on what you call "lightweight", but I think I've held true. The main thing is that there are no special packages needed with PHP in order for it to work. It was tempting to use the cUrl library or the Http classes, but I just implemented all the HTTP responses and requests myself.

Also, it's still a very easy install. You should be able to drop the files into your include path and pretty much be ready to go right away. A lengthier explanation is given in the README, but there's not a whole lot to it other than that.

The future

Obviously I've spent a lot of time trying to make this a product that people can actually use. I didn't expect to, but it remains to be by far the most popular topic on my blog, so I decided to expand on it. To that extent, I've also opened up a Google Code page for it, which I'll mainly use for tracking issues. You can visit that here. While I can't currently see a reason to make a version 4 of the API, I will certainly have future releases. With the added functionality, there will positively come added bugs, and there are enhancements that I have thought up that I did not get time to implement. So if you find a bug, let me know or add it to the bug list, and I'll probably release an update every month or two. It also really depends on the response, whether or not people seem to like the product. Whatever happens, I'll keep all the download links pointing to the latest release, so you can be sure you're getting the most up to date code.

I made this with the intent of making it easy for PHP developers to harness the Picasa service and create really cool new products, so please do so. As always, if you have any commentary, please leave a comment here or send me an email to tell me what you think. I would love to hear that someone really likes or really dislikes anything about the API. If you have features you'd like to see, feel free to let me know or add it to the issue list. And just in case you missed it at the top:

Click here to download the API

Thanks to everyone who has helped with this and everyone who is using it. Now while the bug list is still at zero and my eyes are still open, I'm going to play my Wii...

Comments

Brian said...

Cameron,
Great job on the API. It is very useful and very easy to understand given the great documentation. All I wanted was to display my images from picasa on my website and your library made that easy. BTW thanks so much for the quick E-mail response, all my issues are fixed now!

Brian
brianfietsam.com

Posted Monday, October 20, 2008 at 11:32 AM.
Nikos Dimitrakopoulos said...

Oh! My best wishes and thank you again for taking the time to write this handy library :)

Posted Wednesday, September 10, 2008 at 1:04 PM.
Cameron said...

That's great, thank you! I will get that into the next version when its available for download. I've worked on it a little but unfortunately my pending nuptials have left me with absolutely no time to do anything but wedding plan (as anyone who has looked at my blog in the last two months can tell). :-/ After I get back into the normal swing of things I'll get a new version out, though. Hopefully sometime in October.

Posted Wednesday, September 10, 2008 at 12:57 PM.
Nikos Dimitrakopoulos said...

Hi there Cameron,
I was using your library (which is really useful by the way) and I found a problem.

I've already posted this in google code with a patch.

Cheers

Posted Tuesday, September 9, 2008 at 3:48 PM.
Cameron said...

Anonymous comments is something that I would really like to see as well. My workaround is pretty inventive, I think. I wrote all about it in my Comments:Enabled post. I don't think it's appropriate to add directly into the API, but using the API to implement this idea is pretty easy.

On the other hand, maybe it would be a good idea. Writing my own API is really useless unless it offers something that the "official" API doesn't (which is why the next version will have things like methods to copy an image to another album). So maybe anonymous comments wouldn't be bad to have there. I just wouldn't want Google to get after me for potentially compromising the integrity of their comments.

Hope that helps.

Posted Monday, August 11, 2008 at 1:53 PM.
Tim said...

Hi,

One thing that Google hasn't implemented yet (I guess) is the support for changing the name on a comment.
I would like to create a photo gallery where the users are able to place comments, either by entering a name or logging in to my site.
Then I would like to add a comment for them, using my own credentials, and specifying the comment authors name.

I guess this is at one hand a stupid thing to add, because you couldn't trust the name of the author anymore. However, in my case, it is stupid that you cannot alter the name.

Do you have any ideas about this, because I checked it out and your API doesn't support giving an author name either.

Greetings,

Tim

PS: Check out the current version of the photo gallery on my site (I'm sorry, but it's in Dutch.)

Posted Monday, August 11, 2008 at 1:32 PM.
John said...

I am sorry, I didn't search enough :P
Thank you, this is a great work !
John

Posted Saturday, June 7, 2008 at 6:13 AM.
Cameron said...

Hi John. I think I've already posted what you're looking for in this article. Please let me know if there is anything you have questions on that is not covered there.

Posted Friday, June 6, 2008 at 8:34 AM.
John said...

Hi Cameron,
first of all, thank you for this great work ! :)

My knowledge of php is limited, and I have problems to use your script ! :S

Could you give us some examples of scripts, like displaying albums lists, or pictures form an album ?

Thank you very much !
John

Posted Friday, June 6, 2008 at 6:11 AM.
_jas said...

thnx for your help it worked.
the problem was, the line that u said and some path problems, its working now =).

Thanks for your quick answer.

later

Julio

Posted Thursday, April 10, 2008 at 7:58 PM.
Cameron said...

Hi Julio,

Good question. I think the answer is probably that you only moved the contents of the Picasa folder into your path, whereas Picasa.php is actually in the parent folder, called "php". You should copy all contents of the php folder into your include path.

The other problem could be that you did not include Picasa.php in the page. To do that, put the following line at the top of the php file that is using Picasa:

require_once 'Picasa.php';

If you have followed both of those steps and you're still not able to use the Picasa class, then the files are probably still in the wrong path.

Hope that helps!

Posted Wednesday, April 9, 2008 at 5:36 PM.
_jas said...

hi cameron, just giving a try to this , it looks like pretty interesting,
now i feel a bit ignorant , cuz i cant install the package ...
that include thing,
quoting the readme:
"To install this software, simply place it within your include path.
You can set your include path by calling ini_set('include_path', '/PATH/').
"

Reading that, i make the next steps:
* cheking what was de path.
* coping your picasa dir, on it.

then , i get the next error message:
"Fatal error: Class 'Picasa' not found in C:\bla bla\servers\bla bla\htdocs\index2.php on line 4
"

Where line 4 is:

"$pic = new Picasa();"

so i suppouse that the problem comes from the include path thing...

Is there some php variable that i have active or deactivated to have that thing going on ?

for example , calling the "phpinfo();"
i realize that i have

"allow_url_include Off Off"

well thats enough for now ...
i think you'll see why i feel pretty ignorant u_u.

sorry ir my english isn't the best , but , i speak spanish =p

Forward to hearing an answer.

Julio.

Posted Wednesday, April 9, 2008 at 5:07 PM.
Tuesday, November 6, 2007

Getting the Most From Your Blog

I started out back in May with a blog that accessible on Blog*Spot at cameronhinkle.blogspot.com. Well, that wasn't quite cool enough. I didn't like the URL and I definitely didn't like that ugly blue bar at the top of every Blogger blog. Additionally, I wanted a central place for all my stuff. I wanted cameronhinkle.com to not just be a blog, but to be a place where I do whatever I wanted. This is when I started looking into Blogger's API.

Hopefully you can tell by reading this blog that using Blogger's API has worked pretty well. In fact, because I'm not hosting the blog on Blogger's servers, I have a lot more flexibility with what else can go here, which is why you can also browse my Picasa collection as well as static HTML content. I basically enter my blog posts using the standard Blogger interface, and then when you browse cameronhinkle.com it polls Blogger's servers to get the latest content. While this has worked out really well, there have been some obstacles. If you're thinking about doing this yourself or you're already doing this same thing, maybe this will clear up some of the obstacles.

Duplicate content at your old address

I was not happy about having my blog displayed both at cameronhinkle.blogspot.com and cameronhinkle.com. This is bad for SEO and makes cameronhinkle.com look redundant. I initially solved this by deleting the "Blog" widget from my template and replaced it with static text linking to this site. This worked okay, but it still left cameronhinkle.blogspot.com as an active site and Blog*Spot's RSS feeds still came up in search results. Since the RSS feeds don't link back to cameronhinkle.com, I found this to be a problem.

Blogger has a cool feature that allows you to host your blog on their servers from a unique address. You tell Blogger in your Settings->Publishing tab that you want to host your blog from a custom URL, then you configure your site's DNS entry through your registrar to direct requests for the custome URL to Blogger's servers. Well, I didn't want to host the site on Blogger's servers, so I didn't think this custom URL would work for me. As it turns out, I could configure Blogger to think my blog is at cameronhinkle.com and then just not change my DNS entries. Blogger will then forward all requests for cameronhinkle.blogspot.com to cameronhinkle.com. I did some research using wget and found that it's doing a 301 redirect, which transfers all the PageRank from cameronhinkle.blogspot.com to the cameronhinkle.com. However, there was one small problem...

Paths restricted in custom URLs

My blog is hosted at cameronhinkle.com/blog, which is a path rather than a domain or subdomain. I attempted to put cameronhinkle.com/blog into the Custom URL field of Blogger's Publishing tab, but it wouldn't accept it because it only accepts domains or subdomains. Initially I just lived with the old URL redirecting to cameronhinkle.com, but then I had a better idea. I set up a subdomain called blog.cameronhinkle.com that does a 301 redirect to cameronhinkle.com/blog/. Now any requests to cameronhinkle.blogspot.com will get redirected to blog.cameronhinkle.com, which will in turn link to cameronhinkle.com/blog/. Try this out in Linux if you can by typing the command "wget cameronhinkle.blogspot.com".

Pinging services

You've probably all seen the option to "Send Pings" in Blogger's Settings->Basic tab. This is an important feature, as it alerts several blog services that you have new content. It can be extremely useful in driving visitors to your blog. Unfortunately, since I enter posts into Blogger.com (I have no interest in using Blogger's API to enter new posts since it's not visible to anyone except me and Blogger's interface is just fine), I there was no event on CameronHinkle.com that could be triggered and send off a ping. Additionally, maintaining the list of services to ping and how to ping them is something much better left to experts at Blogger, if at all possible. Unfortunately, before I had set up the configuration described above, Blogger would ping services with an update for cameronhinkle.blogspot.com, but it didn't know about cameronhinkle.com. Since implementing both of the above steps, Blogger knows my actual address, so it will correctly send out pings. Just doing the first step left Blogger sending out pings for cameronhinkle.com (which was okay), but doing step two correctly got Blogger to send pings for blog.cameronhinkle.com. Because of the redirect I set up, this works perfectly.

Blog*Spot RSS Feeds

I often found my blog contents in BlogSpot's RSS feeds, which I did not want. Their feeds would only direct users to cameronhinkle.blogspot.com, which would just be a link to cameronhinkle.com and that wasn't good enough. Even after doing the steps mentioned above, the RSS feeds would have the wrong URL structure; it would link to cameronhinkle.com using Blogger's URL structure because it had no idea I had created my own URL structure. I had already created my own RSS feed using PHP, which is the one I would really like users to find. To remedy this, I used Bloggers "Post Feed Redirect URL" option. It's supposed to be for FeedBurner or other similar services, but it works for this as well. Now Blogger thinks my RSS feed is at http://www.cameronhinkle.com/blog/rss/, which is where it should be.

Comments

There is not, as far as I can tell, a great way to actually incorporate posting comments through the API. Retrieving comments is easy enough, but posting comments requires that all users first log in to Blogger. I don't anticipate a lot of comments so I would really rather that users can post anonymously and I can moderate any spam posts, etc. I did some digging to try to figure out how Blog*Spot does posting to see if I can reverse-engineer it. I found that all blogs on Blog*Spot actually do their posting through Blogger. I think this is for security. To check it out, post a comment on any Blog*Spot blog and you'll see that the page where you enter your comment is hosted at Blogger.com. So given this fact, I didn't mind if comments on my site were entered through Blogger. To make it as seamless an experience as possible, I got the URL for posting comments through Blogger, which is https://www.blogger.com/comment.g?blogID=YOUR_BLOG_ID&postID=YOUR_POST_ID&isPopup=true, and made a link display after every blog post that opens a popup to that page. Specifically, the link says this:

<a href="https://www.blogger.com/comment.g?blogID=YOUR_BLOG_ID&postID=YOUR_POST_ID&isPopup=true" onclick='javascript:window.open(this.href, "bloggerPopup", "toolbar=0,location=0,statusbar=1,menubar=0,scrollbars=yes,width=400,height=550"); return false;'>Add a comment</a>


I took this link straight from another Blog*Spot blog and this ensure that it opens to the correct width and with the correct javascript values set. Now users can comment on any blog post and each comment is displayed through the API (which is, as I said, easy enough to do), but new comments are added through a popup hosted on Blogger.com. So the popup doesn't look like CameronHinkle.com, but this way users can easily login if they want or post an anonymous comment.

Future upgrades

The one thing that I think I'm still missing here is that sometimes I'll find cameronhinkle.com/blog in search results with Blog*Spot's URL structure appended to it. This is a result of Blog*Spot thinking that I'm hosting it on their servers at a different address. So the future enhancement will be to make my site's PHP engine correctly interpret paths from Blogger. The more I look at this problem, the more complicated it could potentially be. I think I will probably settle for a "close enough" solution. That may still be several weeks off.

Learning how to do all of this has been a really rewarding experience because I'm proud of the final outcome. I feel like I have a site that is really easy to customize and an interface for entering blog posts that is I never have to think about. Hopefully these tips will stop someone else from having to do all this research themselves. If anyone has any other good tips, please feel free to let me know!

Sunday, September 9, 2007

Arcadia Beach Roadie 2007

Over Labor Day Weekend, me and the old high school gang got together for a camping trip. While it was without a doubt the worst planned camping trip ever (especially for Labor Day Weekend), it actually turned out pretty well. We had no idea where we were going to stay but we headed out Friday night at about 8:00 for the coast. Without a place to lay our head, we drove up and down the 101 for 45 minutes in the dark of night, stopping wherever we thought we saw a possible campsite. Finally, around 11:00, we found our final destination.

"Camping Prohibited!" said the sign at the front of the beach, but we didn't care. We didn't really have much choice, really. We saw some cars in the parking lot and investigated a little further; indeed, at least 3 other groups had pitched tents on the beach. So we found a place that wasn't too intrusive and started hauling our stuff down the steps to the sand.

Saturday was a gorgeous day. Bright and sunny, but with a little breeze as well. It was one of the nicest days I've spent at the beach. I didn't leave the beach the entire time, except to go back to the car. I did a lot of reading, took a lot of pictures, and watched Heim almost kill himself. Oh yeah, Heim almost killed himself. He climbed up some pretty steep rocks and after he'd gotten about 30 feet off the ground, realized his footing was largely unstable. We realized it too, when we saw large rocks falling from the cliff and making a loud THUD! as they hit the wet sand below. Anyway, he eventually found a way back down, but it was a little tense for a while. He even drew quite a crowd, as you can see in the picture.

The next morning, we awoke to a loud voice, "You are in violation of Oregon State law. It is a $97 fine for camping on the beach. I'm giving you 30 minutes to pack up and leave, at which point I will start handing out citations. You are all banned from the beach for 48 hours." The ranger was pretty cool; he took all of our id information and then pretty much left us along while we packed up. It worked out for the best, really; I wanted to leave early and this gave everyone a reason to pack up as quickly as possible. We're all just glad he somehow missed us on Saturday morning.

In related news, if you'd like to see pictures of our trip, you can now do so here. Some of you may have noticed that the Pictures section is sort of working now. It's not pretty, but you can see all the pictures in my Picasa account, which is a pretty big accomplishment. There aren't any PHP tools available for the Picasa integration like there was for the Blogger integration, so it's ended up being an entirely different experience trying to make the pictures show up. While the style is nowhere near where it needs to be, the pictures are all there. I did a little home-brew API in PHP to handle all the XML parsing from Google's Atom feed. I'll go through what I did to set that up at a later time and post my code for download in case anyone wants it. I'm not taking the time to make it really robust, but if someone wants to add data that I leave out, they can easily add to it. Look for that in the next few weeks and look for the pictures section to be finished later this week.

Thursday, May 17, 2007

How Google almost killed me

I thought I would go over my trip to Pacific City, Oregon last weekend for my girlfriend's 21st birthday so that perhaps I could save some unsuspecting youngster from plummeting to his death! You may not think a search engine could kill a person but Google nearly did.

I hadn't been to Pacific City in a while so I decided to use Google Maps to find the route, as I do before any road trip. I love Google Maps. On the way to the beach, I was thinking how different my life has been in the year and a half that I've been using it. I sometimes sit and just look at other cities or my own city via satellite. I've even discovered areas of Portland I never knew existed. Were you aware that there is 23 square miles of park in the middle of the city?! Neither did I and I've lived here my whole life!

Anyway, going to Pacific City was uneventful but I had to go back a different way because we stopped in Woodburn to visit the outlet mall on the way to. So I put my trust in faithful Google to find the directions from Pacific City to Portland. Around the time that the pavement ended I started to think that might have been a bad idea. At one point we were traveling on logging roads in the Cascade Mountains on loose gravel with no cell phone reception, no power lines, and the only signs of life were a stray dog in the middle of the road, empty beer cans sporadically littered to the side of the road, and a cross on the side of the road. There were no houses or other cars for about 30 minute stretches- which was probably a good thing because it was a one-lane road and I probably would not have seen another car coming around the bend in time to swerve into the ditch! I made it out alive but I'm telling you that had it been raining, snowing (which it is in the satellite photos), or dark, my chance of survival would have been slight. It's a good thing I had a full tank.

Has this ever happened to anyone else? My only other bad experience with Maps was a road that I was supposed to turn left on but legally couldn't (in fact there was a concrete divider, so physically I couldn't either). I heard there was a couple a few months ago who ended up lost in the mountains and died. Does anyone have any horror stories of following the advice of a Maps service? And I wonder if these situations could be a legal concern for map providers. I would assume they have some kind of non-disclaimer that I've failed to read.

Comments

Jennifer Houk said...

I got a good laugh out of your story. In '88 when Steve and I were working for the Department of Justice at several correctional institutes in Florida we had several of those experiences. Most of the institutes were of the beaten path on dirt or gravel roads with little indication, if any, that there would be something at the end of the road. We did laugh through the majority of them. Those days it was a paper map, no cell phone, and swamp land all around (oh, and gators, too)

Posted Tuesday, May 29, 2007 at 4:45 PM.
James Mortensen said...

Your trip from Pacific City to Portland reminds me of some of the dirt roads I've been on in Wyoming and Colorado. They're great for summer weekend excursions, as long as you're prepared and know in advance that it isn't going to snow.

Posted Tuesday, May 29, 2007 at 10:09 AM.
The articles in this blog are authored by Cameron Hinkle, Software Engineer for Nike. The thoughts and opinions expressed are not shared by Nike or any of its affiliates.