Archive for November, 2007

Using CFCONTENT to Serve Images

Friday, November 30th, 2007

This post started from a curiosity about how to store image data in SQL. Not for any particular reason, just how. I’m now firmly convinced that the correct method is: don’t. And for those wondering, here’s just one article i came across that outlines arguments for (not many) and against (more than a few) storing image data on SQL. Its on an ASP-related site, but the same principles apply to Coldfusion (and PHP and whatever else for that matter). There are a couple points the site doesn’t mention, but the general idea is that its much more advisable to just store location pointers for the images in SQL, and then store the images themselves on the file system.

So this idea in conjunction with the CFCONTENT tag gives me really all the control I might want, without having to awkwardly shove my images into a database (even though the binary aspect to that is pretty cool). So here’s an example of how you could use these two things in coordination.

First, the basic html page.

<html>
<head></head>
    <body><img src="fakeimage.cfm?id=1234" />
</body>
</html>

Note the source of the IMG tag is a .cfm page with an associated url parameter. This parameter is what we will use to fetch and serve the correct image to the requester, allowing us to use this single page to serve all the images on our site. Also interesting, even though the page being called is a .cfm page, the html example shown above could have a regular .htm or .html extension.

Next up is the imageserver.cfm page that, you guessed it, serves the images.

<cfif IsDefined("URL.id") AND IsNumeric(URL.id) AND URL.id GT 0>
<cfquery name="fetch" datasource="yourdatabase">
    SELECT imagelocation
    FROM imagetable
    WHERE id = <cfqueryparam cfsqltype="cf_sql_integer" value="#URL.id#">
    LIMIT 1    <!--- MSSQL users discard this line --->
</cfquery> 

<cfif fetch.recordcount AND trim(fetch.imagelocation) NEQ ""> 

    <cfcontent
        type="image/#listlast(fetch.imagelocation,'.')#"
        file="#fetch.imagelocation#"
        reset="true" /> 

</cfif> 

</cfif>

When you store the image’s full path in the database instead of a relative path, you can even store your images outside of your web root (I’ve tested this on Linux and Windows). This could be a good way to keep spiders or other bots from finding your well-hidden images directory. Also, I know some people are purists with their language/s of choice (and I can understand that), but if you really wanted to get fancy here and fetch the correct mime type instead of hoping based on the extension like I did above, you could do this very simply with some nested Java functions:

<cfcontent
    type="#getPageContext().getServletContext().getMimeType(fetch.imagelocation)#"
    file="#fetch.imagelocation#"
    reset="true" />

And remember, since Coldfusion is translated directly to Java bytecode (since version 6), one could maybe argue that the additional functions are really the same as Coldfusion anyway. OK maybe not. Yeah, not really at all. That one sounded better in my head. Anyway, that’s how you could use Coldfusion to serve your site’s images. Some other cool additions to this functionality:

1. You could keep people from leeching your images for their own use, even when they call your imageserver.cfm with the right url parameters. Do this by checking the referer before serving the images, and if its not you, cfabort. Like so:

<!--- strip the referer down to the domain name --->
<cfset request.refererurl = listfirst(replace(CGI.HTTP_REFERER,"http://","","one"),"/") /> 

<!--- if the referer is any site but this one --->
<cfif comparenocase(request.refererurl,cgi.SERVER_NAME) NEQ 0>
    <cfabort/>
</cfif>

I should caution you that technically, CGI variables can be spoofed, but in practice I would count this as few and far between. And if that kind of thing is happening on your site (which you likely won’t know about without some thorough digging anyway), then you likely have larger issues at hand. But this will definitely put the brakes on your average hotlinker. You could even drive the point home by serving up a less-than-pleasant image that they didn’t ask for (if you get my drift lol), instead of aborting.

2. If, for some reason, you wanted to track various statistics on your images and their number of views or whatever, you could do that by databasing any information you want prior to serving the image. Useful information could be anything found in the URL, REQUEST, SESSION, APPLICATION, SERVER, or CGI scopes.

This was fun. I hope this helps someone!

Tutorial: Adding Coldfusion 8 to your Ubuntu LAMP server

Thursday, November 29th, 2007

This post is a semi-tutorial for the installation and configuration of Adobe Coldfusion 8 on an Ubuntu 7.10 Gutsy Gibbon desktop edition LAMP server running apache2, php5, mysql5, and phpmyadmin. I say semi-tutorial cuz this post assumes your set up is like mine as laid out in my previous post, “Tutorial: LAMP Server On Ubuntu 7.10 Desktop“. If your setup differs from mine, this post may not work for you. Oh also, I’m a TOTAL LINUX NEWBIE so thats my upfront disclaimer. This is just what worked for me. At the end of this post, you’ll find links to the sites I found helpful in this process. To the authors of said links, thank you for your help. It was awesome of you to post your experiences, and with them I found it easier to wade through this process. I hope others find my post as helpful. So here we go (this is long).

1. Go to www.adobe.com/go/trycoldfusion. To download cf8, you’ll need an adobe account, but its free and takes one minute to register.

2. The file you want is obviously the linux one: Coldfusion-8-lin.bin. Download it to your machine.

3. Notice the checksum for the file is listed there on the download page. Once its finished downloading, run md5sum in a terminal:

$ cd downloaddirectory
$ md5sum Coldfusion-8-lin.bin

and compare the result against the one posted on the Adobe download page. At the time of this posting, the checksum is:

ce9bb2af5cbf908cbd4403ce506335ef

If the checksums do not match, it means the file is bad, so delete the file and download it again.

4. By default, the binary does not have executable permissions, so if you try to run it, either nothing will happen or it will try to open in a text editor lol. To see what I’m referring to, while still in the terminal in your download directory, enter this:

$ ls -l

and you will see a line preceding the Coldfusion-8-lin.bin file that looks like:

-rw-r--r--

These are the file’s permissions, which show as only for reading and writing, but it needs x’s, so run this:

$ chmod +x Coldfusion-8-lin.bin

and it is now an executable application. To see this via command line, run ls -l again, you’ll see:

-rwxr-xr-x

5. Now run the binary, but you’ll need to run it as sudo, otherwise you’ll get part way into the installation and it will tell you that it requires root privileges to continue:

$ sudo ./Coldfusion-8-lin.bin

The next several steps will walk you through the installation process. Note that at any time you can go back to a previous step in the installation process by typing ‘back’. You may also type ‘quit’ to quit, but quitters never … something something (i stopped listening and missed the rest of the maxim).

6. Language? type ‘1′ for ‘english’.

7. Press enter through all the legal prompts, reading each page line by line of course ;).

8. Install type? For me this will be a developer machine on my home network so number ‘3′, I choose you.

9. Server configuration? I don’t need anything fancy so i type ‘1′ for the standard server configuration. Your mileage may vary.

10. Is there already a server configuration of coldfusion 8 installed? ‘2′ for no.

11. I disabled the documentation but left everything else cuz i might use it. One could make the argument that disabling the documentation is a good idea for security reasons, but like I said before, this machine is on my home network so it doesn’t really matter as much. I just don’t need the documentation. There’s plenty of good sites for that (maybe someday mine will be one of them).

12. Installation folder? I went with the default: /opt/coldfusion8

13. More legal stuff if you are installing Adobe LiveCycle Data Services. I might use Adobe AIR at some point so I went ahead and installed that.

14. Serial number? Left it blank for Developer Edition.

15. Earlier version? ‘2′ for no.

16. Add Web Server Configuration? Here, I diverge from most of the other tutorials I found on this subject. The majority of people seem to be skipping the Apache configuration here, finishing the install, then copying various connector files and restarting various services after the installation is completed. This may have been something necessary for Coldfusion 7. If so, I can’t speak to that. But instead of doing all that, I went the route of adding the configuration for Apache during the installation. So choose the number for ‘Add Web Server Configuration’, then select the number for ‘Apache’ at the next prompt.

17. Key file locations the installation asks for next are:

Apache configuration file: /etc/apache2
Apache binary file: /usr/sbin/apache2
Apache control file: /usr/sbin/apache2ctl

18. Once this is done, you’ll know cuz you’ll see the option to edit the Apache configuration you just added. But we don’t want to do that so type ‘4′ instead to continue the installation.

19. For the web root and Coldfusion Administrator location, I went the default Apache web root on my machine: /var/www

20. Runtime user? Whatever user you want.

21. Password? That user’s password.

22. RDS enabled? I said yes for the moment even though my plan is to set up Subversion at some point in the near future.

23. RDS password? um, macaroni.

24. Review the installation configuration, then press enter to make it all happen. Mmm, feels good. On my machine this last part (of the first part? o_0 ) took less than five minutes. Once its done, you’ll get this:

You have successfully completed
the first step in installing Adobe Coldfusion 8.
To continue with your installation,
go to /opt/coldfusion8/bin and type
"./coldfusion start" to start your server.
Once the server is started,
log in to the configuration wizard at
http://[machinename]/CFIDE/administrator/index.cfm

25. So do that, but as sudo:

$ cd /opt/coldfusion8/bin
$ sudo ./coldfusion start

Coldfusion should start in a few seconds then tell you that it will be writing its logs to /opt/coldfusion8/logs/cfserver.log

26. Now take a breath.

27. Open your preferred browser *cough* firefox *cough* and navigate to http://localhost/CFIDE/administrator/index.cfm. Once you sign in using the username and password you just provided at setup, it should automatically finish its own configuration, then take you to the Coldfusion Administrator’s main page.

28. So lets test Coldfusion by creating and saving a .cfm page that we’ll navigate to in a moment. Create and open the file:

$ gksudo gedit /var/www/index2.cfm

Once the text editor appears, add the below lines and save:

<cfset request.greeting = "hello from coldfusion" />
<cfoutput>#request.greeting#</cfoutput>

29. Now navigate to http://localhost/index2.cfm. Does Coldfusion greet you? I hope so. It did me. I feel all warm and fuzzy-like.

30. Now lets make sure we can connect to the MySQL service. Go back to the Coldfusion Administrator, click the Data Sources link in the left pane, then in the form on the right add the name of one of your MySQL databases, select MySQL (4/5) as your Driver (assuming thats the version you’re running. it is if you followed my lamp server tutorial from yesterday) and click Add.

On the next screen enter the Database name again, set the Server as 127.0.0.1 since MySQL is running on the same machine as Coldfusion, and enter the username and password for your MySQL user account. Click Submit. It should verify the connection for you upon submitting where at the top of the main page you should see:

* data source updated succesfully.

31. So now that we’ve got a data source set up in the Coldfusion Administrator, lets go back and edit our index2.cfm:

$ gksudo gedit /var/www/index2.cfm

adding a query and query output to make sure we can connect to MySQL. Please note that the database name, table name, and field names will change according to your own setup.

<cfquery name="fetch" datasource="testdatabase">
    SELECT *
    FROM thetable
</cfquery>
<cfoutput query="fetch">
    <br/>#fetch.fieldname# - #fetch.otherfieldname#
</cfoutput>

32. Save your changes, and refresh your browser. You should now see the output of your specific table. If so, congratulations, you are now successfully running Coldfusion 8 with Apache 2, and MySQL 5 on Ubuntu 7.10 desktop edition. Think of all the fun acronyms you can refer to your machine as now: CAMU, CAML, MACL, the list goes on.

Extra credit: If you’re tuning in after following my LAMP server tutorial from yesterday, you may want to navigate back to http://localhost/ and notice that the index.php file we created yesterday still echoes “hello there” indicating that PHP is still parsing as it should. The Coldfusion installation and Apache configuration did not break PHP. They are both sharing Apache and running out of the same directory. This is exactly what I wanted as like I said, this is a development machine, wherein I will be writing various things in either PHP or Coldfusion. Maybe both? (Maybe not). The other benefit for Coldfusion of simultaneously running a PHP setup on the same server is that you can use the phpMyAdmin to administer your MySQL needs. And also, there’s one more letter to slap onto your Acronym. I think I’m going to call this setup a CLAMP server. Yes, CLAMP it is. Shiny. Good luck to all and I hope this tutorial helps someone.

Credits and references (thanks again to the authors):

CF8 on Ubuntu Feisty Fawn
CFMX7 on Ubuntu Feisty Fawn
CFMX7.02 on Ubuntu Edgy Eft

Tutorial: LAMP Server On Ubuntu 7.10 Desktop

Wednesday, November 28th, 2007

Toward the end of pursuing various personal projects I decided to set up a LAMP server on my second machine here at home, but wanted to maintain the desktop aspects of what I currently have with Ubuntu desktop so I decided to run the LAMP setup on a clean Ubuntu desktop. I’m aware that I could have went the server route with the LAMP configuration, and then installed the desktop on top of it with:

$ sudo apt-get install ubuntu-desktop

but I decided for now to run similar setups on both machines. So below are my notes for installing the LAMP server on Ubuntu desktop (these notes are as much for my later use as they are for anyone who trips over them whilst running through the interwebs). Overall, its fairly straightforward, and there really aren’t that many steps involved. The community has made this pretty painless IMO. These notes assume that Ubuntu desktop is already installed. An excellent walkthrough for this process can be found here, and mostly what’s below are my adjustments to that excellent walkthrough.

1. Install the LAMP server package using tasksel.

$ sudo tasksel install lamp-server

This tasksel package will install apache2, php5, and mysql5, along with various dependencies and libraries.

2. Set your mysql password when prompted in the terminal. You’ll need it later.

3. Visit http://localhost. If Apache is up in your browser, you’ll see a directory listing.

4. Make sure PHP is up and parsing by placing a test index.php file in the /var/www/ directory. You’ll need sudo for this as it requires root privileges to edit files in this directory. You can do this with any text editor. I chose gedit.

$ gksudo gedit /var/www/index.php

Once open, enter this PHP line and save:

<? echo 'hello there'; ?>

5. Now refresh your browser. If your test page greets you heartily, PHP is up and parsing.

6. On the other hand, if firefox prompts you to download the file cuz it doesn’t know what to do with “PHTML”, make sure the php5 service is enabled with:

$ sudo a2enmod php5

7. If the message returned indicates php5 is already enabled, try just restarting the service:

$ sudo /etc/init.d/apache2 restart

Thats what it took for me. My guess is the alteration of a previously installed service by the subsequent installation of the other items in the same lamp-server package.

8. If you then get the error, “Restarting web server apache2. apache2: Could not reliably determine the server’s fully qualified domain name, using 127.0.1.1 for ServerName” like I did, you’ll need to edit the httpd.conf file:

$ gksudo gedit /etc/apache2/httpd.conf

Add this line and save:

ServerName localhost

9. Once that’s done, refresh your browser again. If you’re like me, the test page performed as intended. So you now know that Apache and PHP are running, but what about MySQL?

10. Try logging in via the terminal and enter that password you created earlier when prompted. If you can login, then MySQL is running:

$ mysql -u root -p

11. If you prefer a web-based interface for your MySQL needs, phpMyAdmin is an excellent way to go. Its not installed with the other packages via the tasksel lamp-server command, but as usual, installing the application is as easy as command line:

$ sudo apt-get install phpmyadmin

you’ll be prompted to allow phpMyAdmin to automatically configure various instances of Apache for PHP use. If you’re following this walkthrough, you’ll want to select the apache2 web service.

12. once the installation is complete, go log in using your mysql login information at http://localhost/phpmyadmin.

13. But if you’re new at this like I am, you may want to verify that PHP can connect to your MySQL instance before you sit down and start writing code, so open up the same index.php file from earlier, add and save this code:

<?php
$hostname = 'localhost';
$username = 'root';
$password = 'yourMySQLpassword';
$conn = mysql_connect($hostname,$username,$password) or die ('could not connect to mysql.');
echo 'OK';
?>

14. Now refresh your browser. If you see the OK, then PHP has no problem connecting to your MySQL.

So hopefully you’re now up and running with your own LAMP server on Ubuntu desktop 7.10. If you’re not up and running, the best place I’ve found for help with anything Ubuntu related is http://ubuntuforums.org/.Good luck.