7 ways to copy “protected” photos

March 28, 2008

We updated a website at work this week, and a request of a collaborator of our client was that their photos be “protected” against theft and illegal copy. To them, this meant deactivating the contextual menu to prevent people from clicking on “Save image as…”

We argued that this would not prevent anybody from saving an image and, more importantly, that it would degrade the user experience, but our protestations fell unto deaf ears.

Here are seven ways to download the images you want, even if right click is disabled.

  • Use Opera: Opera doesn’t honour the oncontextmenu directive, so your right clicks will happily give you the menu with the “Save image as…” option
  • View source: “Use the source, Luke!” Find the image you want, it has to have a URL, paste it in the address bar, File => Save, bingo!
  • Use Firebug: This is exactly like viewing the source, but it’s easier to find the URL of the particular image you’re interested in
  • Save entire page: In the File menu of many browsers, there’s a “Save page as…” option, and you can select to save the entire page, not just the HTML. This will download all the media files used on that page, including the “protected” files!
  • wget: wget -r http://website.com. Nuff said.
  • Drag and drop: Open an image editing program, and just drag the “uncopiable” into the canvas. Optionally remove the watermark.
  • Take a screenshot: Just press on PrintScreen, paste the image in any image editing program and get the image.

University of Waterloo and introduction to programming

March 20, 2008

It has been reported that the University of Waterloo dropped Java in favor of Scheme for first year students. A lot of discussion revolves around whether this is a good choice.

I would argue that introducing CS students to programming through Scheme rather than through Java has a lot of beneficial side effects.

  • REPL: The first thing that Scheme has that Java doesn’t is a REPL, a read-eval-print loop. This is a program that is available in a lot of languages, and only the C-family of languages seem to be lacking them. A REPL allows the user to input expressions and get an immediate answer. REPLs are great for exploration, testing and just toying around with the language. And because the result is instantaneous, students are more likely to try different things than they are to make modifications to a program and keep compiling and running it.
  • Small core: Scheme is unarguably a simpler language than Java. The entire R5RS standard is 55 pages (which I assume is the revision they will use, since DrScheme has no plans to move to R6RS as far as I know. I was misinformed regarding R6RS, PLT-Scheme will in fact support it. Thanks John and Jeremy. I wonder if the classes at Waterloo will use it or R5RS.) The book Java in a Nutshell is over a thousand pages long! There’s just a lot less stuff to learn in Scheme than in Java.
  • Simpler syntax: Some people argue with this claim because they get lost in a sea of parentheses and claim that Java has a more “natural” syntax. Nevertheless, in terms of simplicity, Scheme’s syntax wins. You don’t have to remember if a semi-colon goes after this particular line, you don’t have to remember that if there’s only one statement in your if/while/for/etc. you don’t need the braces, etc. A lot of anecdotal evidence suggests that students who learn Java are confused by syntax errors and that they represent the majority of the questions asked in class.
  • Dynamic typing: Without saying that static typing is harmful, I think that the constraints it imposes, while beneficial in the long run, significantly complicate a programming language. If I take Haskell as an example, there are a lot of concepts such as type variables, type classes, monads, etc. that exist solely to satisfy the compiler. In a large production program, this can help the programmer, but to the student, these will get in the way of comprehension.

    You want a tree in Scheme? Just use a list, there’s no need to define a new recursive type.

  • Functional paradigm: Although Scheme is not a strictly functional language, it supports this paradigm much better than Java. Programmers who grew up with BASIC, C, C++ and other imperative languages will tell you that functional programming is a lot harder, but I believe that it is easier for a student to reason about a functional program than about an imperative one. As they show in SICP, all you need to do is expand your function call. For instance, to understand the function map:
    (define (map f xs)
      (if (null? xs)
          nil
          (cons (f (car xs))
                (map f (cdr xs)))))
    
    (define (plus1 n)
      (+ 1 n))
    
    (map plus1 '(1 2))
    (cons 2 (map plus1 '(2)))
    (cons 2 (cons 3 (map plus1 '())))
    (cons 2 (cons 3 '()))
    (2 3)
    

    With imperative programming, you need to keep track of all the variables that get mutated in your program. This is harder.

  • The students learn: With Java, students learn to program in Java. With Scheme, students learn to program. Because the Scheme language is so simple, students can quickly be introduced to more complex topics. In Java, the static typing, the complex syntax and the lacking means of abstraction and combination hinder this fast progress (try writing a general, simple map function in Java.)

Some people voiced concerns over the practicality of showing Scheme instead of Java; those concerns are unfounded in my opinion. First of all, a person that knows programming well shouldn’t have any problems picking up Java. Once you know the fundamental concepts of programming, learning a new language is learning new syntax, idioms and libraries. That is not to mean that it is a trivial task, but the transition is easier. Next, the job of the university is not to teach the currently popular technologies, it is to teach the fundamentals of the discipline. Technologies come and go, but the core of computing changes much more slowly and is applicable to many technologies.


The new and improved {% active %} tag

March 19, 2008

A few months ago, I described a Django template tag that I wrote to identify the currently active page.

At the time, I was satisfied with my solution, and I must say that it worked perfectly for all these months. The one thing I didn’t like about it though was that it wasn’t DRY. I had to specify an regular expression in the tag that would identify the current page. Those regexes were usually a copy of the ones in my urls.py file. This caused me some head scratching a couple of times when I changed a URL regex in urls.py, but forgot to change it in my _nav.html template.

Today, I took the time to remedy the situation and I am satisfied enough with the result to share it.

import re
from django.core.urlresolvers import RegexURLResolver
from project.app import urls

@register.simple_tag
def active(request, view='', pattern=''):
    '''
    Return 'active' if *pattern* matches *request.path* (the current location
    in the browser). The empty string is returned otherwise.  The pattern is
    either given by the user or taken from the URLconf.

    *request* (required): an HttpRequest object
    *view*    (optional): a view name
    *pattern* (optional): a regular expression string
    '''
    path = request.path[1:] # Strip the leading /

    if view != '':
        for urlpattern in urls.urlpatterns:
            # Skip include()s, they don't have the _callback_str attribute.
            if isinstance(urlpattern, RegexURLResolver):
                continue

            if view == urlpattern._callback_str:
                pattern = urlpattern.regex
                break

    if pattern == '':
        return ''

    if re.search(pattern, path):
        return 'active'
    else:
        return ''

active takes two arguments: a request object and either a view name or a regex. If a view string is given, the function will try to find the matching regex in the urls module. If none can be found, the empty string is returned. If a regex pattern is given, this will be used to test the current path. This parameter exists to make sure that you can use any regular expression if you so desire. Leaving both parameters blank will return the empty string.

I hope this helps you.


Trying xmonad

March 10, 2008

For nearly a year now, the cool Haskell folks that procrastinate hang around on Reddit have been boasting about their new and shiny window manager, xmonad. I’ve always wanted to try it, but I always found something less productive to do instead, like playing Dr Mario.

Well, this weekend was the weekend that I gave xmonad a whirl. As far as window managers go, I’m a pretty conservative guy. When I started using Linux back in 2000, I used Window Maker for about a year. After that, I switched to Blackbox, and have been using *box wm’s since then. I went from Blackbox to Fluxbox to Openbox. Thankfully, they all behaved pretty much exactly the same, so it was easy to switch from one to the next. I’ve had the same background image for 4 years and the same Openbox theme for 3 years. If xmonad is gonna get me to switch, it’s gonna have to be pirate awesome (ninjas suck!)

Installation

The installation of xmonad is pretty easy if you have GHC and the proper extensions installed. I only needed to install the latest version of the X11 bindings. Installing xmonad is as easy as runhaskell Setup.hs configure && runhaskell Setup.hs build && runhaskell Setup.hs install. Installing the xmonad-contrib package is equally easy.

Using xmonad

I’ve never used a tiling window manager, and at first, I thought it was a little weird. The window manager says where your windows will appear and what size they’ll be. This takes some time getting used to, I’m not even sure I’m comfortable with it, but I’m trying. The tutorial on the official website was a great way to get started. I quickly got comfortable launching a bunch of urxvt windows, so I went and configured xmonad!

Configuring xmonad

Configuration of xmonad is done by modifying a Haskell script, ~/.xmonad/xmonad.hs. I started by changing some key sequences, which is very easy to do. The documentation says that after you are done, you save the file and you try to open xmonad.hs in GHCi. If you get no error, you can reload the window manager (with mod-q, more on that in a bit) and the changes will automagically appear. Now, how cool is that? A way to check your configuration file. Openbox uses an XML file, and there’s no way to know if you screwed something without trying the configuration. And if you decide not to check your configuration in GHCi and just reload xmonad, what happens? You get an xmessage window telling you there’s an error in your configuration file.

Like I said earlier, mod-q restarts xmonad with your current configuration. Now, it doesn’t restart as you would except. The screen doesn’t even flicker. The new configuration just happens. I don’t know the exact mechanism, but I can tell you that the command-line to do that is pretty long: the entire window manager state is passed as an argument to xmonad when it restarts. ps(1) will show you exactly how long.

One thing to be aware of with mod-q is that by default, it assumes that xmonad is in your PATH. If it isn’t, you will need to put the complete path in xmonad.hs.

-- Restart xmonad
, ((modMask              , xK_q     ),
      broadcastMessage ReleaseResources >> restart "/home/vince/usr/bin/xmonad" True)

Floating layer

Some applications don’t work well in a tiled window manager. For example, The Gimp, MPlayer, Pidgin, etc. are better used as floating windows. Fortunately, xmonad is prepared for those: you can float any window you want, and you can even set windows to be automatically floated in your xmonad.hs configuration. Those floating windows are always above the tiled windows, they can be moved around with mod-button1 (the mouse left button) and resized with mod-button3 (the right button.) Note that only the bottom right corner is used for resizing, so you can’t resize to the left, you will need to move your application to the left and then resize it to the right.

xmonad-contrib

Xmonad has a lot of nice third-party modules. All of them are pretty well documented and for those I tried, work as expected. Using those modules is usually just a matter of importing them in xmonad.hs and binding a key sequence to an action they export.

dzen and dmenu

Xmonad follows the general UNIX philosophy of doing one thing and doing it well. It xmonad’s case, that is laying out windows. Xmonad lets other application do tasks it shouldn’t be doing. For example, instead of having its own launcher, the default xmonad configuration has shortcuts for dmenu and gmrun. Also, instead of having its own status bar code, xmonad users can use dzen or xmobar. With the help of a plugin, DynamicLog, you can control what appears on those bars (by piping information to dzen or xmobar.)

Performance

A lot of programmers think that “if it’s not C or C++, it’s slow and memory hungry.” That is, of course, a myth, but one that seems to cling with way too many smart programmers. Xmonad is neither slow, nor memory hungry. The system loads in less than a second, and memory usage stays low. You definitely don’t need 32 GB of memory to be able to use it.

Documentation and community

Both are great! The #xmonad IRC channel on Freenode has nearly 100 users, and every time I asked for help, I got a fast, courteous and correct answer (and if you can’t get an answer, keep asking, dons will eventually wake up and answer you. dons++)

The documentation for xmonad is much longer than its code, something rarely heard of in the open source community. There’s a tutorial for users, a tutorial for developers, a tutorial for extension developers, every third-party module has documentation, the entire source code is commented, etc. It’s hard not to find what you are looking for.

Features that are missing

So far, I really like xmonad, I will try it for about a week to see if it can displace Openbox. One thing that I like to do in Openbox is to start a movie in MPlayer and set the window to be displayed on all workspaces, always on top. Xmonad doesn’t seem to have an easy way to toggle a “display on all workspaces” action, but since anyone can code a plugin, I see this as something that I should resolve. There’s also another action that I want to look into, making it possible to disable the border (the red line that indicates the current active window) on a per-window basis.


Follow

Get every new post delivered to your Inbox.