The Onehub Blog.

Our work, our technologies, and our approach to creating easy to use web applications.

All posts tagged with code.

Encrypting your files with Rails - Part II

0 comments

This is the second post in a two part series (part 1 is here) on adding encryption to attachment_fu for Rails applications.

What about making the file available for download? AVOIDING THE ISSUE OF SCALABILITY FOR A MOMENT (since sendfile is not the right way to serve files from Rails), we want to use a variant of sendfile to do the decryption and send the file. Here’s a modified version of send_file that uses an extra hash parameter (acme) to decrypt if provided:

module ActionController
   module Streaming

   def send_file_x(path, options = {}) #:doc:
      raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)

      options[:length]   ||= File.size(path)
      options[:filename] ||= File.basename(path)
      send_file_headers! options

      @performed_render = false
      logger.warn("Sending file #{path}")
      if options[:stream]
        render :status => options[:status], :text => Proc.new { |response, output|
          logger.info "Streaming file #{path}" unless logger.nil?
          len = options[:buffer_size] || 4096
          if options[:acme]
            c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
            c.decrypt
            c.key = key = options[:acme]
            c.iv = iv = Digest::SHA1.hexdigest("OneFishTwoFish")
          end
          File.open(path, 'rb') do |file|
            while buf = file.read(len)
              if options[:acme]
                output.write(c.update(buf))
              else
                output.write(buf)
              end
            end
          end
        }
      else
        logger.info "Sending file #{path}" unless logger.nil?
        File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
      end
    end  
  end   
end

Post continues, click to read more...


Encrypting your files with Rails - Part I

1 comments

This is the first post in a two part series on adding encryption to attachment_fu for Rails applications.

Let’s say that you’re building an application that will be used by a number of different people, and it involves storing information in files, and providing that information to the right person(s) at the right time.

There are choices about where to store the ‘files’ for users – in a database, in a file system (on disk), or in a specialized store (e.g. Amazon S3). For this example, we’re going to choose storing files ‘on disk’ in a file system – locally, across the network, NAS, SAN – wherever, as long as we can ‘see’ the information as a file.

One traditional way to enforce permissions on files is to have the file system itself enforce whether someone can or can’t have access to a file. In the old days, on *nix systems, that meant juggling user and group databases, and working within the ‘user-group-other’ paradigm. More modern attributed file systems make this easier, however that might not work with your web application, because you might not want to synchronize file system attribute information with your web identity information.

You might ultimately decide to control access yourself using some sort of User information DB (homegrown, LDAP, etc.), and explicitly control access by protecting the URLs which download specific files.

As a further measure, you might want to consider encrypting information on a file level. When a file is uploaded, you would generate an encryption key, encrypt the file on disk with that key, store the key separately, and use that key when a file is accessed (as close to the point that the file is downloaded as possible).

Post continues, click to read more...


Simple Logo Swapping

0 comments

I'll be the first to admit it. As a Web Professional, it is nearly impossible to account for every user scenario, every browser, every configuration. And yet, if you're like me, you're constantly on the look out for ways to improve and simplify your code without sacrificing flexibility or accessibility.

There is a simple but effective logo swapping technique that I utilize on Onehub.com that does both of these things. Before we jump in to the code, let's examine a few situations that dictate the necessity for logo swapping.

For starters, not everyone accesses your site via modern browsers.

Some users visit sites on mobile phones, PDAs, accessibility devices and the like. Their numbers might not look like much on your monthly stats right now, but you can expect those numbers (particularly mobile phones) to increase dramatically in the next 2-3 years.

Were you thinking of using that awesome, transparent .PNG version of your logo? Well then you can go ahead and add IE6 and all other legacy browsers to that list as well.

These are all potential entry points to your site that should be taken in to consideration.

Second, some people still insist on printing web pages.

Site logos are one the most important visual aspects of any brand. Because of this, they are also a common source of debate among Web Professionals. One of those debates surrounds printed versions of sites.

Some designers believe that a site logo is purely a design element and should not be displayed with the content when printed. Others argue that the logo is a contextual element and therefore needs to be included.

It's all semantics. Literally. While I can certainly appreciate the validity of both of these opinions in certain contexts, I'll argue that most clients don't care. If someone is printing out their site, most site owners want their logo to be at the top of that page.

Assuming you have the same request, you'll need to place the logo inline with your HTML because the majority of users aren't sending background images through to their printer.

Last but not least, some times it just looks better.

Sometimes a design calls for placing a light logo on a dark background - because it looks awesome. The reversed Onehub logo at the top of this page is a perfect example. If we served only the reversed logo, users browsing with handheld devices would see this:

Logo comparison

Kind of hard to see that light text on a white background, eh? A solid logo swapping technique is especially useful in these cases.

Alright, let's walk through the technique.

A tale of two images.

We start with two slightly different logos - the standard positive Onehub logo (black text) and the reversed Onehub logo (white text).

Logo comparison

Now, let's take a look at the HTML:
<div id="logo">
    <h1><a href="/"><img src="/images/logo_onehub_pos205x54.png" alt="Onehub" width="205" height="54" /></a></h1>
</div>

Nothing fancy. In fact, without any corresponding CSS it is nothing more than a standard image implementation, right? Look closer, you'll notice that we're actually calling the positive version of the logo - the version that we want to serve to everything but modern browsers. So how does the reverse logo end up there?

It's all in the CSS:
#header #logo a {
    display: block;
    background: transparent url("/images/logo_onehub_rev205x54.png") no-repeat; 
    width: 205px;
    height: 54px;
    margin: 36px 0;
}   

#header #logo img {
    display: block;
    width: 0;
}

Focus on the second declaration first. We set the width of the inline image to 0. This hides it from CSS-enabled devices while retaining the alt text for screen readers and users browsing with images off. The display property is only necessary if you're using a strict doctype for your markup.

Going back to the first declaration. We match the width and height of the containing element to that of the inline image and set the display property to block so that it fills the space we provided. Ignore the margin property as that is strictly for this design.

Lastly, we pull the reversed logo in as the background image of the containing element, essentially swapping it in place for the (now hidden) inline image.

That's it!

So there you have it. By placing the image inline, we have made the image available to printers and the alt text available to screen readers. Then, with very minimal HTML and CSS, we were able to use whichever logo best fit our design while ensuring that an appropriate alternate version was also served in other situations.