Notes: Working With RSS in CF

Presented by Pete Freitag.

Really Simple Syndication. Just an XML file. Like WDDX: They're both syndication structures. But RSS is a defined structure, so it makes it easier to consume because you know exactly what the standards should be for it.

Studies have shown that 69% of those surveyed don't use RSS, 27% are unaware of it, but use RSS, and 4% are aware RSS users. So about 1/3 of population use RSS, but it has successfully evaded technical knowledge requirements for people to use it. RSS feed is one file (called a channel) with multiple articles (called items).

Why publish RSS? Can increase traffic; people subscribed will return to your site when their reader notifies them that new info is available. Also more convenient for your readers. What are the downsides? Easier to steal your content when it is in a prestructured RSS feed. Can actually increase your bandwidth too, because readers may check your feed every hour or something.

How used? Portals like Google Homepage, RSS readers (desktop apps, Google Reader), Aggregators (like MXNA, Fullasagoog), RSS to email. Not just for blogs; can be used for news articles, forums, newsletters.

RSS vs. ATOM. RSS 2.0 is simple and gets the job done. ATOM is more complex with some add'l features. Typically, the add'l features are not used. For instance, you can post multiple versions for different content types (e.g. plaintext vs. HTML).

Generating an RSS Feed

Start by resetting any content. Then immediately do the XML header because it MUST be on the first line.

<cfcontent reset="true"><?xml version="1.0" ?>
<cfheader name="Content-Type" value="text/xml">

Nice thing about setting it to "text/xml" is it will actually display the XML when opening in the browser. Nice for viewing the results. Can also choose "application/RSS+XML".

<rss version="2.0">
  <channel>
    <title>My News Feed</title>
    <description>This is my news feed!</description>
    <language>en-us</language>
    <lastBuildDate>Wed, 27 Jun 2007 16:46:00 GMT</lastBuildDate>
    <item>
      <title>This Article Title</title>
      <link>http://you.com/news.cfm?id=1</link>
      <description>My article content.</description>
      <pubDate>Wed, 27 Jun 2007 16:46:00 GMT</pubDate>
      <guid>http://you.com/news.cfm?id=1</guid>
    </item>
  </channel>
</rss>

Dates in RSS feed must be RFC 822 compliant. Use the GetHttpTimeString() function to display it in the proper format.

So, when doing this with <cfquery>/<cfoutput>, you might do something like:

<rss version="2.0">
  <channel>
    <title>My Feed</title>
    <description>My feed description.</description>
    <language>en-us</language>
    <lastBuildDate>#GetHttpTimeString(Now())#</lastBuildDate>
    <cfoutput query="myArticles">
      <item>
        <title>#myArticles.Title#</title>
        <link>http://you.com/news.cfm?id=#myArticles.ID#</link>
        <description><![CDATA[#xmlFormat(MyArticle.Story)#]]></description>
        <pubDate>#GetHttpTimeString(myArticles.DT)#</pubDate>
        <guid>http://you.com/news.cfm?id=#myArticles.ID#</guid>
      </item>
    </cfoutput>
  </channel>
</rss>

Send your feed to feedvalidator.org to see if it is valid. Helps you get your feed up and running.

You can also use enclosures, which is most used for podcasting. It's like an "attachment" to your feed. Technically, you can only have one enclosure. It may allow multiple enclosures, but because you're not supposed to, this can be problematic.

<enclosure url="http://you.com/audio.mp3" length="12345" type="audio/mpeg" />

Length is in bytes. Can obviously be more than just audio files. Could be a Word or PDF file.

Can also add a <category> tag within the <item> tag. Can add multiple tags. Technorati bases its "tags" on these categories in RSS feeds. Can also add <author> (must be an email). Can also add <source>, where it refers to a source article you may be writing about or rebutting.

More <channel> tags:

  • copyright: Copyright notice.
  • ttl: Time to live. Number of minutes to cache the feed.
  • image: Include an image for the RSS feed.
  • skipDays: Listing of days that the feed will not change.
  • skipHours: Listing of hours where the feed is not changed.

Can see the RSS 2.0 spec for more info.

Feeds in ColdFusion 8

The new <cffeed> tag can create AND parse RSS feeds.

<cffeed action="create"
        name="#feed#"
        outputfile="rss.xml"
        overwrite="true"
        xmlVar="xmlout">

Name will be a struct with the content. xmlVar allows you to put the generated RSS XML into a variable instead of the file.

So create a struct that contains title, description, link, and item which would be an array of structs with the various item elements (title, description, pubDate, link). This way, you can work with familiar ColdFusion structs and arrays when generating this stuff, then just feed it all to <cffeed>.

Parsing feeds is pretty easy.

<cffeed action="read"
        source="http://you.com/rrs/"
        query="feed"
        properties="feedMetaData">

feedMetaData will be the general channel metadata, and the feed variable from the query="" attribute will be a query form of the items.

Problem with the returned query is that it returns a million columns, and the columns you need to use are different for ATOM vs. RSS. It would be nice if there was one common set of fields that are set depending on whether the feed is ATOM or RSS.

So if using RSS, you may do something like:

<h1><cfoutput>#feedMetaData.title#</cfoutput></h1>
<cfoutput query="feed">
  <h2><a href="#feed.rsslink#">#feed.title#</a></h2>
  <p>#feed.description#</p>
</cfoutput>

So <cffeed> is really nice, although problematic due to the different ways it handles ATOM vs. RSS feeds. This isn't really their fault, but it would be nice if there was a black box that took care of the translation between the two feeds.

Notes: Ajax Development with ColdFusion Frameworks

Presented by Joe Rinehart.

What's Ajax? 

Classically, it means "Asynchronous JavaScript and XML", although also used with JSON a lot. For today, it will mean "using JavaScript to update a portion of an already displayed page without reloading."

So, for an example: Deleting a single record is so server-heavy. Make the request, delete the record, then reget the list, and rerender the entire list page. In Ajax, we now make the request, the server just deletes the record and sends a small token indicating that it did it.

So we balance the load between the client and the server more efficiently.  It also doesn't interrupt the experience for the user.  And the experience is just richer in general.

"Unstructured Ajax". Calls made to the server don't return data, they return pre-rendered HTML. Very easy to implement, doesn't require major changes in architecture towards service layers. All we need are some scripts that generate HTML!

But you have now bound your data and presentation together. Isn't flexible for changing. Similarly, Ajax request "handlers" on the server side tend to be very single-purpose. They are used for that specific Ajax call and can't do much else.

"Structured Ajax". Not just replacing regions of screen with the response. Instead, you're taking XML, JSON, or even perhaps delimited lists of strings and using the pure data. No intermingling with presentation. Thus, it will work better with service layers that are focused on data, not presentation. What if you want to update two regions of the page, for instance? Unstructured Ajax would get messy that way, but when returning just data, you can do this.

This is more difficult to implement though. Need extensive knowledge of JavaScript and DOM. And what do you use for your structured data? XML? SOAP? JSON?

When it comes right down to it though, both types use the same technology, the XmlHttpRequest. Just creating this object is troublesome. Very different from one browser to the other. This is where nice JavaScript libraries come in. CFAjax, Spry, Dojo, AjaxCFC, Prototype + Scriptaculous. But there are others! Zoop, Plex, Rico, sajax, MochiKit, Taco, MagicAjax, Microsoft Atlas, yada, yada, yada.

So we will use Prototype and Scriptaculous in this example.

Implementing Ajax with Model-Glue

For today, we'll just do unstructured Ajax. Not the best, but a great way to get started in this demo. Will be faster for demoing.

Prototype. Great, and easy for unstructured Ajax, all on its own. Wraps around the XmlHttpRequest calls. It does have structured Ajax features, but it's custom to Prototype.

Scriptaculous. An "add-on" to Prototype. Provides effects, drag-and-drop, unit testing.

Model-Glue. Framework for developing HTML-based apps that use CFCs for business logic.

Model-Glue can work seamlessly with these Ajax frameworks. Can return some HTML which Prototype will put in a region via unstructured Ajax.

The example app is a list of tasks. You can create, edit, complete, and delete tasks.

What can we Ajaxify? Delete existing items. Add more tasks. Inline item editing.

Ajax Delete. Create an event handler that deletes a task but returns nothing. Then, include our Ajax frameworks and add some JavaScript to call the event handler in an asynchronous manner. Third, use scriptaculous to make the row fade out. Finally, a few more visual clues.

With a two-line delete function in JavaScript, you make the Ajax request and then fade the row with Scriptaculous.  The Ajax request will just call a Model-Glue event that uses the built-in Model-Glue generic database management to delete the record in the database.

First create the MG event, then write the Prototype code to make the Ajax.request(), then write the Scriptaculous code to give visual feedback.

A big problem with Ajax is that it is harder to debug. Use cfcUnit for testing the CFCs. You should do this anyway. It's a lot easier to run unit tests than to put fake data in your forms and seeing what happens, over and over again. On the client side, debug with FireBug! But beyond that, do your client-side testing, even testing DOM results, with Selenium. With cfcUnit and Selenium, you can walk your way up the tiers to see where the errors occurred.

ColdSpring. With it, you can expose existing components as they are to be services for Ajax.  Google "Remote Proxy ColdSpring" to read some articles by Chris Scott on this. ColdSpring will effectively generate the facades for you! Very service-oriented approach and requires no extra code.

Notes: CF8 and Exchange and .NET Integration

<cfexchangecalendar>

Can create events, add attachments, remove attachments, etc. Can create an event struct and assign all of the attributes (requiredAttendees, startTime, endTime, Subject, Message, isRecurring, RecurrenceType, RecurrenceFrequency, RecurrenceDays, RecurrenceEndDate). Then just pass the struct into the event="" attribute of <cfexchangecalendar>.

<cfexchangemail>

Can get, getMeetingInfo, move, set, delete. Can also getAttachments and deleteAttachments. Can use <cfexchangefilter> to only get certain message types or only those sent during a particular time period.

<cfexchangecontact>

Create, get, modify, delete contacts.

<cfexchangetask>

Create, get modify, delete tasks.

Setting up Exchange Server for CFExchange

  • IIS must be set up and running on the Exchange Server.
  • Make sure that /Exchange virtual directory is created in IIS.
  • "Allow" access to "Microsoft Exchange Server" in the "Web Service Extension" of IIS.
  • Mailbox access can be set in "Active Directory Users and Computers". To do this, go to "Users" node, open properties of a user, open "Exchange Advanced Tab", click "Mail Box Rights" button.

Troubleshooting and Error Handling

Make sure the Exchange server is accessible from the CF server; just try pinging it from the CF server. Make sure the mailbox on the Exchange server is accessible from OWA. This is required because this is how CFExchange does its communication.

If using https, must make sure that the Exchange server's cert is in the cert store of CF!

If using form-based auth in Exchange, then make sure you correspondingly have formBasedAuthentication="true" in <cfexchangeconnection>.

Exchange Integration Summary

Makes it easy to access Exchange functionality in a familiar tag-based format. Can access Calendar, Mail, Contact, and Tasks.

Did a demo. Had one user create a meeting in CF, then showed it in the calendar in Outlook. Logged in as another user with CF and was able to see the meeting invitation, and declined it from within CF. Then showed the meeting be declined in the calendar in Outlook.

This could be useful for having one central place for viewing numerous scheduled events for various accounts (the different rooms). Users would login to one app to view all of those things, instead of it being spread across numerous resource accounts.

.NET Integration

Allows you to leverage existing .NET programs. Also allows you to leverage MS products like Word, Excel, PowerPoint, etc.

Can call local or remote .NET assemblies, even outside a firewall. Don't have to have .NET runtime on the CF machine. <cfobject> and CreateObject() can now create .NET objects. However, CFCs cannot be called from .NET, and you cannot use .NET UI components.

Can be as simple as:

var myDotNetObj=CreateObject(".NET",".NET class");

What's difference between using .NET integration vs. web services? Web services have loose coupling and are low performance. They're also stateless. The runtime unification of .NET integration has tight coupling, is stateful, and is high performance. Most useful when working with internal systems of an enterprise or organization.

.NET Integration Summary

Seamless. Don't need to know much about .NET to use. Location independent (local or remote). Platform independent.

In the demo, he created a custom .NET object that made a call to an Access database and returned a query. Then created a CF page that creates the .NET object, pulls the method, and did a <cfdump> of the returned query. Nice!

In another demo, created a .NET object in CF pointing to a global assembly class. With it, he was able to pull all the system processes running on a machine. That was with "System.Diagnostics.Process" .NET object.

He showed how you could also just dump the entire object, and the <cfdump> results would show all of the methods, just like you can do with Java classes. Very, very nice.

Notes: ColdFusion 8 Application Security

Here are the OWASP Top 10 for 2007 and how they relate to ColdFusion development.

10. Failure to Restrict URL Access

Many people will protect sensitive functionality by just hiding the display of links or URLs. But this is not enough. You can obviously access those URLs directly. So we need to actually restrict access to those URLs, either programmatically or with server security.

  • Create an access control matrix during application design. Design a map to every URL and function.
  • Don't assume users are unaware of 'hidden' URLs. Spidering and other technology can make you page suddenly pop up on Google! Oops.
  • Don't just secure the presentation layer. Don't rely on just HTML or JavaScript. The model should have security as well. Server-side should also be checking that it should do what it is being asked.
  • Block access to file types your application should never serve. Eliminates possibility of stuff you might not even know about. Lock it down in IIS or Apache.

9. Insecure Communications

Apps frequently fail to encrypt network traffic when it is necessary to protect sensitive communications.

  • Use SSL for all connections that are authenticated. Think about it. Even the session tokens should be protected, otherwise we're open to session hijacking. This requires SSL.
  • Secure internal infrastructure connections need to be secured also.
    • Talking to the database. Think about what you're writing to the database and is it secure?
    • <cfftp> will be secure in CF8 with SFTP support.

8. Insecure Storage

Web apps rarely use cryptographic functions when storing data.

  • Protect sensitive data. Passwords, credit cards, SSNs. Ask yourself if you really need this info. If not, don't take the burden to store it securely.
  • When you do need it, use encryption before sending it, including to the database.
  • Hash() in ColdFusion. Creates a "fingerprint" or a unique identifier for an original string, but it is impossible to convert the hash back to the original source string. Nice because it doesn't require a key.
  • If you need to read it back, Encrypt() and Decrypt(). Requires a secret key to encrypt and get it back. So the key has to be somewhere were your app can read it, so be sure to protect that key. Off the webroot and in a secure manner.

Starting with CFMX7, can install Java Cryptology Extension (JCE) security providers. Ships with CFMX_COMPAT, AES, Blowfish, DES, DESEDE. CF8 includes RSA BSAFE Crypto J Library, which is FIPS 140 compliant (nice for govt apps).

7. Broken Authentication and Session Management

Some apps may have poor security and authentication processes, which make hacking easier.

  • Passwords. Require a certain level of complexity. Limit the number of invalid login attempts. Store the password as a hash rather than plaintext or encrypted. Don't send passwords via email! Send them a link that goes to a page where they can change their password within a certain time period, and the link expires within a certain time.
  • UI feedback. Tell the user the last time they logged in, it may alert them to an invalid login by a hacker.
  • Log login attempts. If there are a certain number of invalid attempts in a short period of time, lock them out.
  • Authenticate via SSL, transmit session IDs over SSL. Don't pass IDs over the URL. Use J2EE sessions if you can.

6. Information Leakage & Improper Error Handling

Web apps frequently generate error conditions during normal operation. That's fine. An error message should include meaningful messages for the user; error message may include diagnostic info for the site maintainer, but it is better to have this information stored to a database or emailed to the administrator or developer; error message should not include info that an attacker could use.

So robust exception handling shouldn't be on, debugging shouldn't be on.  Those are for your development or QA servers. Use the site-wide error handler and <cferror> or onError for app-wide error handlers. Hide the ColdFusion Administrator; any ColdFusion person knows what the address should be, and that will give them insight into what version of CF you're using.

5. Cross Site Request Forgery

A CSRF attack forces a logged-on victim's browser to send a pre-authenticated request to a vulnerable web app, which then forces the victim's browser to perform hostile actions to the benefit of the hacker.  The typically leverage XSS vulnerabilities.

  • Protect against Cross Site Scripting (XSS).
  • When processing sensitive data, only use POST. Not impossible to get around this, but much harder.
  • If they're doing something very sensitive, ask the user to reauthenticate. This will shut down a CSRF attack.
  • Create a randomized token for each page/form. If the receiving page doesn't get the token it expects, it will reauthenticate or just not process its actions.

4. Insecure Direct Object Reference

Don't make it really clear when you're doing just via a URL or form parameter. For instance, /getfile.cfm?file=c:myfile.txt makes it very clear what the code is doing. An attacker sees this and will try to get ANY file. Could get your CF files!

  • Avoid exposing so directly what you are referencing.
  • Validate the references.
  • Pass credentials, ask every step along the way if they can do this, right through into the model.

3. Malicious File Execution

Allowing attackers to include hostile code and data. Anywhere where you may expose a file that will be included or executed, an attacker could change that file to execute a different file. Particularly dangerous in conjunction with forms that allow uploading of files.

2. Injection Flaws

Allowing hackers to relay malicious code. Typically comes in the form of SQL Injection, especially via URL parameters.

  • Set up a sandbox for the app. Limits how the hacker can exploit the app to get to any system-level stuff, or anything else external to the app.
  • Limit access to <cfexecute>, <cfregistry>, etc. Depending on your app functions, maybe even stuff like <cffile>.
  • Carefully validate data receiving in before using it in database calls. <cfqueryparam>. Especially now that it can be used in cached queries in CF8.
  • Limit database permissions. Use an account with the lightest permissions necessary. You can limit the datasource functions (SELECT/UPDATE/INSERT/DELETE/EXEC/etc) and the RDBMS user's access permissions.

1.  Cross Site Scripting (XSS)

Attacker uses a web app to send malicious code in the form of a script, to a different end user who will then execute it.

Stored and reflective attacks. Reflective is the type when scripts may send sensitive data to another server that will save the info for use. Or will send spam to someone with your info.

Samy from MySpace in Oct 2005 amassed 1 million friends. Everyone who visited his page added him to their friends, but then their profile was affected also, so then everyone viewing an infected person's profile also added him as a friend. GodOfTheNoose did a similar thing in Dec 2005, but did it with Flash, so he exploited the <embed> tag.

  • Enable global script protection in ColdFusion Administrator, or at least in <cfapplication> or application.cfc. Not fire-proof, but a good start.
  • Encode user-supplied output with a UDF like HTMLTrans() (available at cflib.org).
  • Install web server filters like URL Scan (IIS).

Newest stuff in last few years: CSRF, insecure communications, malicious file execution. Stuff that has dropped in importance in last few years: Unvalidated inputs, buffer overflows, denial of service. So a lot of the insecurities in the past were browser application level stuff out of our control. So the impetus is now on web app developers to improve their code.

Unvalidated inputs was #1 in 2004. Consider some of our validation techniques: Using input masks, validation onBlur, onSubmit, or on server side. In CF, use the isValid() function. Supports many common types and can make validation a lot easier.  Remember, validate from your model all the way up to your view.

  Theme Brought to you by Directory Journal and Elegant Directory.