#182
Oct 05, 2009

Cropping Images

Present a slick user interface for cropping image attachments using Jcrop and Paperclip.
Tags: plugins
Download (46.3 MB, 14:07)
alternative download for iPod & Apple TV (22.4 MB, 14:07)

Resources

# models/user.rb
class User < ActiveRecord::Base
  has_attached_file :avatar, :styles => { :small => "100x100#", :large => "500x500>" }, :processors => [:cropper]
  attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
  after_update :reprocess_avatar, :if => :cropping?
  
  def cropping?
    !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
  end
  
  def avatar_geometry(style = :original)
    @geometry ||= {}
    @geometry[style] ||= Paperclip::Geometry.from_file(avatar.path(style))
  end
  
  private
  
  def reprocess_avatar
    avatar.reprocess!
  end
end

# users_controller.rb
def create
  @user = User.new(params[:user])
  if @user.save
    if params[:user][:avatar].blank?
      flash[:notice] = "Successfully created user."
      redirect_to @user
    else
      render :action => "crop"
    end
  else
    render :action => 'new'
  end
end

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    if params[:user][:avatar].blank?
      flash[:notice] = "Successfully updated user."
      redirect_to @user
    else
      render :action => "crop"
    end
  else
    render :action => 'edit'
  end
end

# lib/paperclip_processors/cropper.rb
module Paperclip
  class Cropper < Thumbnail
    def transformation_command
      if crop_command
        crop_command + super.sub(/ -crop \S+/, '')
      else
        super
      end
    end
    
    def crop_command
      target = @attachment.instance
      if target.cropping?
        " -crop '#{target.crop_w.to_i}x#{target.crop_h.to_i}+#{target.crop_x.to_i}+#{target.crop_y.to_i}'"
      end
    end
  end
end
<!-- views/users/crop.html.erb -->
<% title "Crop avatar" %>
<% content_for(:head) do %>
<%= stylesheet_link_tag "jquery.Jcrop" %>
<%= javascript_include_tag "jquery.Jcrop.min" %>
<script type="text/javascript" charset="utf-8">
$(function() {
  $('#cropbox').Jcrop({
    onChange: update_crop,
    onSelect: update_crop,
    setSelect: [0, 0, 500, 500],
    aspectRatio: 1
  });
});

function update_crop(coords) {
  var rx = 100/coords.w;
  var ry = 100/coords.h;
  $('#preview').css({
    width: Math.round(rx * <%= @user.avatar_geometry(:large).width %>) + 'px',
    height: Math.round(ry * <%= @user.avatar_geometry(:large).height %>) + 'px',
    marginLeft: '-' + Math.round(rx * coords.x) + 'px',
    marginTop: '-' + Math.round(ry * coords.y) + 'px'
  });
  var ratio = <%= @user.avatar_geometry(:original).width %> / <%= @user.avatar_geometry(:large).width %>;
  $("#crop_x").val(Math.round(coords.x * ratio));
  $("#crop_y").val(Math.round(coords.y * ratio));
  $("#crop_w").val(Math.round(coords.w * ratio));
  $("#crop_h").val(Math.round(coords.h * ratio));
}
</script>
<% end %>

<%= image_tag @user.avatar.url(:large), :id => "cropbox" %>

<h4>Preview:</h4>
<div style="width:100px; height:100px; overflow:hidden">
  <%= image_tag @user.avatar.url(:large), :id => "preview" %>
</div>

<% form_for @user do |f| %>
  <% for attribute in [:crop_x, :crop_y, :crop_w, :crop_h] %>
    <%= f.hidden_field attribute, :id => attribute %>
  <% end %>
  <p><%= f.submit "Crop" %></p>
<% end %>

RSS Feed for Episode Comments 56 comments

1. Fredrik Oct 05, 2009 at 15:20

You keep surpassing my expectations every monday. Exactly what I was looking for in my on-going project, many thanks for the time you spend at creating these screencasts.


2. dotemacs Oct 05, 2009 at 16:00

Ryan, thank you for another great cast. Even though it was a bit late, it was well worth the wait. Also thanks to jschwindt for creating a great tool.


3. cascadeclimbers Oct 05, 2009 at 16:22

Thanks again, Ryan. Anybody know of a similar plugin or jslib for drawing on an image?


4. laserlemon Oct 05, 2009 at 17:26

Great cast! I didn't know that digging into the Paperclip processors was that accessible. I'd love to figure out how to rock some rounded corners or other such coolness.


5. Kris Oct 05, 2009 at 18:49

This....is cool...

Great timing too; I was just thinking over the weekend that this would be a great feature for one of my projects.


6. iblue Oct 05, 2009 at 18:55

Ryan, I'm not sure, but what happens if some evil attacker modifies the crop_* parameter to something like `dd if=/dev/zero of=/dev/hda` or any other evil stuff?

Wouldn't that lead to a remote command injection vulerability in cropper.rb, line 14?


7. Junio Vitorino Oct 05, 2009 at 19:23

Amazing very useful too. Thanks Ryan once again.


8. Lin He Oct 05, 2009 at 20:16

Ryan, u r so awesome!!!!! seriously, I was looking for ways to do this last week and now you've done an episode for us.


9. Ryan Bates Oct 05, 2009 at 21:07

@iblue, good point. I think a quick "to_i" in the processor should solve this problem. I'll update the code.


10. Juan Schwindt Oct 05, 2009 at 22:01

Hi, Ryan.

I couldn't believe my eyes when I saw my little rjcrop example in your screencast, it's a great honor. I learn so much from you every week that contributing back feels very good.

Greetings from Buenos Aires, Argentina.
 


11. Nithin Bekal Oct 06, 2009 at 02:38

Thanks for the screencast. I've been storing images directly in the databases in my current application, and have been looking for a good way to crop the images before saving.

But will Jcrop cause problems with prototype? I always seem to run into trouble when I use jquery plugins, although jquery works fine in noconflict mode.


12. luciano Oct 06, 2009 at 05:50

Ryan,
One more time you made an awesome screencast!
Thanks a lot!


13. Brian Armstrong Oct 06, 2009 at 06:01

Wow...cropping gets into some more heavyweight stuff, this is great. Thanks Ryan!


14. Eric Berry Oct 06, 2009 at 07:05

Wow!

I am extremely impressed on the depth of this screencast. This is probably my new favorite. Please keep the more advanced screencasts coming. Outstanding job!


15. nemo Oct 06, 2009 at 11:22

Hey Ryan,
Excellent screencast....really helpful and concise.

Also, why dont you add recaptcha to your comments section to avoid all the spammars!

Thanks again and great job.


16. Florian Witteler Oct 06, 2009 at 12:25

Hi Ryan!

This is an amazing screencast. I didn't know that something like that is possible in such a cool ruby-on-rails way.
It is definitely a very useful feature and absolutely an eyecatcher on a website.


17. Dave Spurr Oct 06, 2009 at 12:47

Ryan,

An excellent screencast as usual, which was actually quite timely as I was just wondering how to pass cropping parameters to Paperclip.

Also thanks for mentioning my Prototype & script.aculo.us cropper. It was very good timing as I was actually in the process of releasing a new version, which is now live.

@Nithin Bekal - if you don't want to use jQuery and prototype together then look into my cropper (mentioned in the screencast & linked to in the show notes) that is Prototype & script.aculo.us based.


18. Nelson Rojas Oct 06, 2009 at 14:33

Hi Ryan! that good news was to see the new railscast appear.
I was wondering do you have something happened to the idol of Monday?
I also take your time to thank and congratulate the videos of "Everyday ActiveRecord" and "Mastering Rails Forms" are excellent.
Thanks and best regards from Chile!
Sincerely, Nelson.


19. Jaime Iniesta Oct 07, 2009 at 01:52

Thanks Ryan! Great stuff.

I use the prototype alternative for this, I'm not a jQuery guy :)


20. Larry Sprock Oct 07, 2009 at 06:15

Hi Ryan,
Another useful screencast! I would like to personally volunteer to weed out the spam and moderate the comments. I would suggest shutting down comments after a given time period. The amount of spam is crazy!


21. Karl Oct 07, 2009 at 08:40

Awesome RailsCast as always!

Ryan, you might want to check your mail, you've got 138 new messages! :)


22. Andreas Lyngstad Oct 07, 2009 at 12:28

Thanks! I check in every monday.


23. Emerson Oct 08, 2009 at 17:58

Hey Ryan,

Thanks for this. I am in the middle of developing an application that requires users to upload images and this is exactly the screen-cast I needed.

Also in the middle of learning how to use that GeoKit plugin... it's amazing.


24. -jul- Oct 08, 2009 at 18:07

It's simple, it's elegant, and it's *awesome*! Best screencast ever! I'll recommend this episode to my PHP friends as well, I don't think they would mind :)

However, you should update your commenting system, because of the spam it collects.

I once had a simple commenting / voting system which was abandoned for a couple of years, and... umm... well, when I had a look on it, I had to remove about 20000 spam messages. And, the commenting feature.


25. Matthew Savage Oct 09, 2009 at 09:22

For anyone who might be interested I have created a similar processor to handle rotation.

This was created because a) it seemed hacky using RMagick by hand when paperclip had all the bits available and b) it was the cleanest way to handle rotation with images hosted in S3 storage.

The required code can be found in the following gist: http://gist.github.com/206145

Enjoy!


26. Stewie Oct 09, 2009 at 16:19

Next weeks episode: filtering spam?

thanks


27. Jonas Arnklint Oct 13, 2009 at 06:50

Big fan of what you are doing. As I noticed the spam you get here, maybe something like the URL I submitted as "Website URL" can help get rid of it?
Keep up the good work!


28. Memiux Oct 13, 2009 at 10:39

Yeap, I agree with #37. Stewie, filtering spam will be great.


29. JB Oct 14, 2009 at 01:15

Hi,

Thanks for this great episode ! Just a tip for those who are wondering : I wanted to be able to re-crop the image without uploading it again, but the problem was that ":large" style was already cropped. I didn't found a clear documentation on this, but you can apply processors or other properties to some styles only. For instance :

:styles => { :small => "100x100#", :large => "500x500>" },
:processors => [:cropper]

could become :

:styles => {
  :small => {:geometry => "100x100#", :processors => [:cropper]},
  :large => {:geometry => "500x500>"}
}

This way ":large" image isn't cropped, but ":small" is. Then you can define an action to recrop your image, keeping the same code in the view.


30. Brent Collier Oct 14, 2009 at 11:48

Yeah, Jcrop is really nice. I recently used it to add user avatar cropping to one of our apps, but I set it up to work entirely from a single page. I didn't want an avatar change to lead the user away from the profile edit screen, so I used the responds_to_parent plugin to upload the image via ajax, and then immediately render the image for cropping. I'm pretty happy with how it turned out.


31. Veward Drawson Oct 15, 2009 at 06:14

Uhm... Am I falling behind or? I didn't think that coders where a target group for uggs and hair straighteners. But maybe I'm just falling out of style...


32. Erez Ben Shoham Oct 17, 2009 at 00:05

To validate images content types in IE you need to add to your validation 'image/pjpeg' and 'image/x-png'


33. supriya Oct 26, 2009 at 06:06

I followed step by step as you explained in the tutorial. Its working for me till the form in crop view. I can choose the dimensions I want, but when click submit it don't crop the image. It gives the same only the small version(default thumbnail).

I get an error in the terminal,which is

[paperclip] An error was received while processing: #<Paperclip::PaperclipError:
 There was an error processing the thumbnail for paperclip-reprocess,4716,0>
Please help me with this issue.
Thanks


34. supriya Oct 26, 2009 at 23:14

I also tried your project episode-182 but its giving the same error. I also installed the latest Imagemagick. But not working for me.


35. Yavor Ivanov Oct 29, 2009 at 06:54

Hi! I have a very strange problem.

When I try to do this cast I end up getting with a page that loads forever and nothing in the log.

Any idea if this is caused by imagemagic or something else?

btw I updated imagemagic.

Thanks in advance!


36. Yavor Ivanov Oct 29, 2009 at 11:15

I've spend the whole day trying to make this work. And implementing it in my app just doesn't work.

I've tried it on a side project and no problem.

Maybe it's something from my configuration... memcached or something... I am considering everything but still without getting any errors it's damn hard to know what the problem is.

Someone else experienced similar difficulties?


37. Michael Filbin Nov 02, 2009 at 19:34

Hi everyone,

I am not certain if anyone is still monitoring this thread since the last post that did not appear to be spam was on the 29th of October, but I hoping someone can point me in the right direction if you are still listening.

I have run into a snag when trying this example out on an app I've deployed to the Heroku platform. I am using AWS S3 as my asset host because Heroku has a read-only filesystem. I am pretty sure the problem I am having is coming from the way AWS handles assets in the cloud.

Here is the pastie: http://pastie.org/681007

In my app, instead of having an user model with an avitar attribute, I have a submissions model with a photo attribute. I am able to create a submission via the new action and upload a photograph as the paperclip attachment, but when we move create action in the submissions controller, paperclip raises NotIdentifiedByImageMagickError

It would appear that the call to Paperclip::Geometry.from_file() was expecting submissions/1/large.JPG but the url to this photo on AWS S3 is submissions/1/large.JPG?1257217300. The appended 1257217300 appears to be a cache identifier.

Does it appear that I am on the right track here? Does anyone have any suggestions for a work around?


38. Saket Nov 03, 2009 at 07:30

Great Ryan.. Amazing..........


39. Andrea Dec 12, 2009 at 09:30

@Michael Filbin

I had the same problem. To solve this I replaced "avatar.path(style)" with "avatar.to_file(style)" in the avatar_geometry method into the model... seems to work... With Heroku I've another problem with crop, the cropped image seems mantain the original ratio.


40. Hooston Dec 12, 2009 at 22:02

Thanks, very good...


41. Kristian Gerardsson Jan 15, 2010 at 14:40

Just a gotcha.. Windows/ImageMagick doesn't seem to like single quotes in the argument in the reprocessing.

" -crop '#{target.crop_w.to_i}x#{target.crop_h.to_i}+#{target.crop_x.to_i}+#{target.crop_y.to_i}'"

I changed the single quotes ' to \" (escaped double quote), and it worked right away.


42. Matenia Rossides Feb 23, 2010 at 03:21

I have just tried this tutorial, great walkthrough by the way.

I end up with the :large image outputting twice and no crop options overlaid .... the submit button works but .... doesnt seem to let me crop :(
anyone want to help me tackle this?


43. Matenia Rossides Feb 23, 2010 at 14:54

OK, Just fixed 50% of my own problem ....
(n00b = me) forgot to include jquery library
I get the crop options, however, It is not saving the cropped version :( and its still outputting 2 of the :large items ...


44. Matenia Rossides Feb 23, 2010 at 15:02

Never mind ... another N00B mistake ...
MY APOLOGIES TO ALL ..
there was a sneaky image output tag that was hiding ... and i didnt see it until after a good night sleep and a strong coffee in the morning ...

KEEP UP THE AWESOME RAILSCASTS ...


45. Juan Schwindt Mar 15, 2010 at 13:40

Have you tried the new kid in the block for image handling: dragonfly? I find it excellent, well done and very flexible. I update my RJCROP project to work with dragonfly: http://github.com/jschwindt/dragonfly_crop


46. Till Mar 20, 2010 at 10:30

Thank you for your great screencasts! i've already learned A LOT from you!

Unfortunately i got a problem with the cropping process in this screencast:

Everything works fine, the image can get cropped, it even crops the right section and it gets saved...

But then, after saving, the cropped image is in a wrong size. Even though i defined the size to be 100x100# (as in your movie)... It is 167x100 ... an STRECHED..

has anybody got an idea what this could be? i already looked 3 times through all files of this process..

Thanks for your answers! and sorry for my bad english, i'm from switzerland ;)


47. Trek Glowacki Mar 21, 2010 at 09:09

If you're using S3 as a storage mechanism, you can't use the avatar_geometry method as shown (it assumes a local file). Paperclip can convert from S3 file to local TempFile with the `Paperclip::Geometry.from_file`: http://gist.github.com/339380


48. Till Mar 22, 2010 at 03:16

Thank you for your answer Trek Glowacki.

But unfortunately i'm not using Amazon S3... The photos are stored on the local server..

i think the photos are in the right ratio, but the file-dimensions are calculated wrong.. so, avatar_gemoetry seems to work


49. Monty Mar 23, 2010 at 23:37

I'm having the same problem as @Till, inspite of having the size given as 392x306# it is cropping image of size 392x392, which is something very weird, and help needed from the experts regarding this, I'm staring at the issue for quite sometime with no solution.

Thanks in advance


50. Andre Apr 13, 2010 at 08:23

Awesome, thank you very much for the cast!


51. Jonathan Spooner Apr 16, 2010 at 09:30

You rock! Thank You!


52. Brett D Apr 17, 2010 at 15:32

obviously the form can be hacked quite easily so i.e. a user can crop another users avatar/image by playing with HTML source,

I added an extra field to the model
photo.security_code

on creation assign security_code to Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{rand(50000)}--")[0,18]

in the model
attr_accessor :crop_left, :crop_top, :crop_width, :crop_height, :security_code
   

def reprocess_image
     photo.reprocess! if self.security_code ==security_code
  end

in the crop image form ...

<%= form.hidden_field security_code, :value=>@current_user.photo.security_code %>

I'm sure you get the idea of the above code, its stops anyone from cropping/hacking the source for an image that they dont own :-)


53. kalle Apr 22, 2010 at 02:03

@supriya

ad this in the environment:

Paperclip.options[:swallow_stderr] = false

if you get sth like: -crop *x*y+*w*h-
false argument. try to add an whitespace at the end of the processor command

in the crop_command method:

" -crop '#{target.crop_w.to_i}x#{target.crop_h.to_i}+#{target.crop_x.to_i}+#{target.crop_y.to_i}' "

in lib/paperclip_processors/cropper.rb


54. Ken Mayer May 11, 2010 at 19:48

If you are having trouble getting the aspect ratio correct on Heroku, try adding a bang ("!") to the end of the geometry string in the crop_command method.

e.g. " -crop '...!'"

From the ImageMagick manual "Width and height emphatically given, original aspect ratio ignored", http://www.imagemagick.org/script/command-line-processing.php#geometry


55. Joberto May 20, 2010 at 15:14

I'm having some problem with the validation i had before the cropping. See, I'm validating the "group_id" of the user in the model. So when I try to crop, the validation raises errors. I tried this: validates_presence_of [:name, :group_id], :unless => :cropping?

but it doesnt work.
Anyone could help me out?


56. Joberto May 20, 2010 at 16:14

Nevermind, i figured it out


57. Dale May 24, 2010 at 22:30

Hi all. I have tried to get this to work for hours but no luck. Everything goes smooth until I hit the crop button and I get a No Method Error:

NoMethodError in PeopleController#update

private method `sub' called for ["-resize", "200x", "-crop", "200x200+0+33", "+repage"]:Array

RAILS_ROOT: /Users/dale/code/event_log
Application Trace | Framework Trace | Full Trace

/Users/pasley/code/event_log/lib/paperclip_processors/cropper.rb:6:in `transformation_command'

I have checked my ImageMagick install and it works. I have triple checked all of my files against the screencast, but I keep getting the above. Any idea on what is going on here?


58. Michael Smith Jun 02, 2010 at 03:59

@Dale I had the same problem. It seems like paperclip has changed the way it handles processor command line arguments. They used to use a String for that, but now they're using an Array. This is why you get an error on super.sub, because it's trying to remove the -crop attributes using regular expressions which don't work on an array.

Below is my modified cropper.rb. That seems to be working. It's quickly hacked together, there may be a cleaner way to do it so anyone feel free to suggest a different approach.

http://pastie.org/988870

On another note I encountered some weird behavior. I don't seem to have to do the ratio adjustment. In fact when I do the ratio adjustment in the javascript code to the crop_x and crop_y etc, the thumbnail becomes extremely small (not visible anymore in fact). When I leave out the ratio factor, everything works great and I don't have a problem with the crop not being centered. I'm puzzled.

Thirdly, I haven't really researched this, but wouldn't it be a good idea to restrict those crop_x, crop_y etc attributes to be integers only? I think they get passed through unsanitized to cropper.rb and could therefore be used to execute commands. After all crop_x, crop_y etc can be set to any value by a malicious user.

Ryan, you're the man! Great job on the Railscasts. Keep it up!


59. Michael Smith Jun 02, 2010 at 07:34

My previous fix contained a bug. It makes sense, but it escaped me, of course you have to crop *before* you resize! Now the javascript ratio adapt is required as well, so ignore that in my previous comment.

Here's the updated fix for the cropper.rb: http://pastie.org/988870


60. Chris Your Jun 07, 2010 at 11:49

@Michael @Dale @Ryan

I also encountered the Paperclip array returned in the transformation_command super method.

I simply joined the array returned from super, performed the substitution Ryan used in his screencast, then split it back into an array.

http://pastie.org/995357


61. Michael Smith Jun 07, 2010 at 19:35

@Chris That's a much cleaner way to do this. Thanks!


62. Chris Your Jun 10, 2010 at 08:23

@Michael

No problem! Glad to help.


63. acne scar cream Jun 17, 2010 at 00:31

Wow, thank you for sharing. I will copy this. Thanks!


64. Carlos André Oliveira Jul 06, 2010 at 19:57

Thanks Ryan for these fantastic screen casts.

@Kristian (41) thanks for the clue!


65. Maikon Mattiello Jul 12, 2010 at 14:19

I have a doubt.

Suppose I want to make the crop in only two styles (:small, :large) and a third (:medium) I just wanted to use the resize without crop.

How can I do this?

Thanks for the great tutorial!

http://pastie.org/1041573


66. webtasarim Jul 15, 2010 at 09:01

web tasarımı, kurumsal site tasarımı, profesyonel web sitesi tasarımı, profesyonel web tasarımı

<a href="http://www.webtasarimturk.net" title="web tasarımı">web tasarımı</a>


67. Dan Hixon Jul 15, 2010 at 14:56

If you want to use this technique with heroku (and the S3) you'll need this gist instead:

http://gist.github.com/477586

The command needs to be an array for reasons unknown to me.


68. Julian Jul 19, 2010 at 03:11

I've had trouble trying to get this to work on Heroku too, was working before a few days ago.

I've used Dan's code (Comment #128) which stops the crop from breaking but the aspect ratio is not being kept correctly.

Previously I was using Key Mayer's change (Comment #60), appending a bang on the end of the command, which was working but isn't working anymore.


69. kinopyo Jul 29, 2010 at 10:35

I encountered 3 problems when I tried Paperclip + jcrop.

1. Paperclip has a dependency on ImageMagick, so you do have to install that first. http://www.imagemagick.org/

2. I'm using rails3 beta4, and papercli 2.3.3, when I created the Cropper class, it seems that it can't be auto-loaded. So if you have the same problem maybe you just need to require it explicitly.

3. You need to change the Cropper class because maybe there're some changes happened to paperclip so that neither Ryan or rjcrop's code will produce an error now. You can use 62.@Chris Your's code, thank you @Chris Your btw. If you use heroku or S3 so maybe you should check 65@Dan Hixon's code.


70. kinopyo Jul 30, 2010 at 10:48

Your voice is really sexy!


71. free directory list Aug 11, 2010 at 22:37

It is marvellous! I like it!


72. Joba Aug 19, 2010 at 06:31

Great stuff!
How can I set a maximum width/height to be cropped?


73. wholesale new era caps Aug 20, 2010 at 20:22

That was a great piece of information., I enjoyed reading it..,


74. buy jordans Aug 20, 2010 at 22:53

Thanks for the code. Good article, Each and every point is good enough. I really enjoy watching the RailsCasts. I think type of site that is useful in sharing information and it is important to share. Great site. This could probably have the refactoring tag added t it.


75. PDF to Images Converter Aug 24, 2010 at 23:11

Some times, to a certain need, we have to convert PDF to image for enjoyment.


76. black strappy sandals Aug 25, 2010 at 00:44

it's a good application. Thanks


77. error fix Aug 25, 2010 at 00:53

Ryan, thank you for another great cast. Even though it was a bit late, it was well worth the wait. Also thanks to jschwindt for creating a great tool.


78. Wholesale Electronics Aug 25, 2010 at 01:35

Discount Wholesale Electronics, Wholesale Cell Phones, Electronic Gadgets and More from the Best Dropship Wholesaler


79. louis vuitton shoes Aug 26, 2010 at 23:13

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


80. snow boots Aug 30, 2010 at 20:45

I was just thinking over the weekend that this would be a great feature for one of my projects.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source