Monday 25 May 2015

An Issue of Common Courtesy

A common complaint I hear from associates in the field of HR, is failure to show up for interviews. In particular, the candidate failing to turn up and failing to inform the interviewer.

You know how it is - you pick a promising candidate from a list of possible candidates, after a fair bit of deliberation based on information gleaned from his or her resume, and make the call. Assuming you manage to contact said person and he or she is still available, you fix a mutually agreeable time and place for the interview. Sometimes it may even (horrors!) involve staying back after office hours to accommodate the candidate's schedule.


Kept waiting.
And then the candidate fails to show up. You call, nobody picks up. There's no email from this person informing you that he or she can't make it. The candidate has disappeared, and you have just wasted your time. Common courtesy seems to be a thing of the past, you lament.

Bitch, please.

Yes, if a candidate agrees to a time and place for an interview and somehow finds himself or herself unable to attend, it's common courtesy to at least keep the interviewer informed. I agree that deliberately neglecting to do so is pretty frickin' rude. But if that somehow gives you the impression that I feel your pain, perish the thought.

Allow me to explain my curious lack of sympathy for your distress. Your situation is somewhat illustrated below:

Kettle. "Hi Pot, I'm Kettle."
Pot: "Kettle, ya dawg! Whassup, nigga?"

You see, back in the days where I was a fresh graduate, wide-eyed and innocent, filled with boundless enthusiasm - OK, you get the idea - I attended my fair share of interviews. After almost every interview, there was this same refrain.

"We'll let you know in a week whether or not we decide to hire you."

Maybe it was naivete on my part, but I truly believed that I would get an answer. Nope, not a peep. Ten, twenty, fifty interviews. Nothing. Yes, I'm aware that it's common practice to only inform the interviewee if the company is interested in hiring. That doesn't make it any less rude.

So now you complain about getting the exact same treatment you've been dishing out. Sorry, I don't think you have a goddamn leg to stand on. How's that shoe feel when it's on the other foot? Well, see the picture below - this illustrates the fucks I give.

That's right! Nun.
Back when the market was saturated with job-seekers and it was up to you to pick and choose, you got away with that shit constantly. Now we're dealing with a tight labor market. The worm has turned, and you can do absolutely diddly-squat about the candidates who are standing you up.

You know what's that you're tasting right now? That's humble pie, my friend. Chew and swallow.

If you object to anything I said here, give me some feedback. I'll call you.
T___T


Monday 18 May 2015

Web Tutorial: The Lightbox Effect (Part 2/2)

You've created the layout for your Lightbox, you've managed to get it to display content dynamically. What's next? Why, the fun part - making it look good. The cake's already done, all you're doing today is adding the icing.

So add this to your CSS class content_wrapper.
            .content_wrapper
            {
                width:80%;
                height:80%;
                border:1px solid #777777;
                overflow:hidden;
                margin-top:50px;
                margin-left:auto;
                margin-right:auto;
                background-color:#FFFFFF;
                border-radius:9px;
            }


What happened there?

You gave your Lightbox cute round corners. Now the next part is slightly trickier. The Lightbox currently appears and disappears without much fanfare. We're going to change that with some CSS3 animation.

Add a couple more lines to your CSS class content_box and make the following changes.
            .content_wrapper
            {
                width:1px;
                height:1px;
                border:1px solid #777777;
                overflow:hidden;
                margin-top:50px;
                margin-left:auto;
                margin-right:auto;
                background-color:#FFFFFF;
                border-radius:9px;
                -webkit-transition: width 0.5s, height 0.5s; /* For Safari 3.1 to 6.0 */
                transition: width 0.5s, height 0.5s;

            }


What this does, is ensure that when your Lightbox's width and height changes, it'll do so at a measured rate. We also set the width and height properties to 1px at the start.

For more on CSS Transitions, follow this link. (http://www.w3schools.com/css/css3_transitions.asp)

Now, it's time to modify the JavaScript.
            function open_lb(varid)
            {
                document.getElementById("wrapper").style.display="block";                       
               
                setTimeout(function(){document.getElementById("lb_wrapper").style.width="80%";document.getElementById("lb_wrapper").style.height="80%";},100);               
                setTimeout(function(){document.getElementById("lb_content").innerHTML=content[varid];},200);
            }

The last two lines define a timer function to set the lb_wrapper div's height and width properties (which we initially set to 1px) to 80%. This, coupled with the transition specifications we added to the content_wrapper class earlier, ensures that your Lightbox makes a nice slow entrance.

Here's some more material on JavaScript timing functions! (http://www.w3schools.com/js/js_timing.asp)

Why do we need Timer functions for this? Can't we just get it done instantaneously?

For a more detailed explanation, please refer to Establishing a Transition Sequence in CSS3.

OK, we're going to do the same for the Lightbox closing.
            function close_content()
            {           
                document.getElementById("lb_wrapper").style.width="1px";
                document.getElementById("lb_wrapper").style.height="1px";  
             
                setTimeout(function(){document.getElementById("wrapper").style.display="none";},500);           
            }


And we're done! Easy, wasn't it?

Test out your Lightbox now. Does it pop up nicely and disappear nicely? It's one of those very neat but simple tricks that you don't need clunky jquery libraries for.

Seeya. Time to "x close" this chapter,
T___T


Friday 15 May 2015

Web Tutorial: The Lightbox Effect (Part 1/2)

The Lightbox Effect is named after a plugin (Lightbox) created by Lokesh Dhakar.

OK, but what does it do?

It's an overlay on the current page, dimming the entire page with displayed content in the middle, with a button to close it. That's it! Nothing fancy. It's a simple and elegant method of housing content in the Lightbox without having to let it take up precious real estate on the parent page.

Other versions may have fancy borders, loading animations and countless nifty little features. We're going to do none of those today, and just focus on the basics.

So why write our own?

It's fun! Always a good reason to do anything.

Also, I want to show you that it's not all that complex at its core. That is, if you just want a Lightbox Effect without any funny stuff, it's possible with just a few lines of code. No clunky JavaScript libraries. Just good old-fashioned JavaScript and HTML, with a bit of CSS3 thrown in for shits and giggles.


So let's start with this bit of code.
<!DOCTYPE html>
<html>
    <head>
        <title>Lightbox test</title>
        <style type="text/css">
            .content_wrapper
            {
                width:80%;
                height:80%;
                border:1px solid #777777;
                overflow:auto;
                margin-left:auto;
                margin-right:auto;
                margin-top:5%;
                background-color:#FFFFFF;
            }

            .screen_wrapper
            {
                position:fixed;
                z-index:900;
                background: rgba(0,0,0,0.8);   
                left:0px;
                top:0px;
                width:100%;
                height:100%;
            }

            .btn_close
            {
                width:95%;
                margin-left:auto;
                margin-right:auto;
                text-align:right;
                color:#999999;
                cursor:pointer;
            }

            .content_box
            {
                width:95%;
                margin-left:auto;
                margin-right:auto;
            }
        </style>
    </head>

    <body>
        <div id="wrapper" class="screen_wrapper">
            <div id="lb_wrapper" class="content_wrapper">
                <div class="btn_close">
                    x close&nbsp;
                </div>
                <div id="lb_content" class="content_box">
                   
                </div>
            </div>
        </div>

        <div>
            <div>Photo 1</div>
            <div>Photo 2</div>
            <div>Photo 3</div>
            <div>Photo 4</div>
            <div>Photo 5</div>        </div>
    </body>
</html>


Open it in your browser and you should see a translucent grey film over your page, with a white box in the middle. There's no content at the moment, and there's a "x close" button on the right. It doesn't work either. You need to write script for that!



But first things first - this is what your Lightbox looks like when visible. We're going to turn it invisible. Make the following change to the CSS.

            .screen_wrapper
            {
                position:fixed;
                z-index:900;
                background: rgba(0,0,0,0.8);   
                left:0px;
                top:0px;
                width:100%;
                height:100%;
                display:none;
            }

Now when you refresh your browser, your screen is back to its pristine clickable self!

Didn't we just do that two months ago?

Ah, you've been paying attention. Yes, we did pretty much the same thing for LKY's Memorial. So if you went through that one, the first part of this web tutorial should be easier than Britney Spears on crack.

The difference here is that we're going to populate different content here on the fly. And, of course, in here we define proper CSS classes.

The screen_wrapper class is the translucent black overlay on the screen. Look up LKY's Memorial for the explanation regarding this bit of code.

The content_wrapper class sits in the middle of the overlay and has the following properties.

- width:80%, height:80% fills up the screen with a little border around the edges, to show part of the screen beneath this layer.
- border:1px solid #777777; gives the content_wrapper a nice grey border.
- overflow:auto ensures that any content that goes outside this box will be available through the use of (very ugly but functional) scrollbars.
- margin-left:auto, margin-right:auto puts the box dab center of the overlay.

The btn_close class is for the clickable element that closes your Lightbox.
- width:100% makes sure the div occupies the entire width of content_wrapper.
- text-align:right because you want the text to be aligned right, duh.
- cursor:pointer to change the mouse cursor to a pointer when you roll over the area, indicating that this guy can be clicked on.

And the content_box class is for the div we'll be populating with content!
- width:100% makes sure the div occupies the entire width of content_wrapper.
- padding:20px makes sure your content doesn't stray too close to the borders, which would make for some really ugly effects.

Now for some data!

We need some JavaScript for this. Add this code to your head tag.
    <head>
        <title>Lightbox test</title>
        <style type="text/css">
            .content_wrapper
            {
                width:80%;
                height:80%;
                border:1px solid #777777;
                overflow:auto;
                margin-left:auto;
                margin-right:auto;
                margin-top:5%;
                background-color:#FFFFFF;
            }

            .screen_wrapper
            {
                position:fixed;
                z-index:900;
                background: rgba(0,0,0,0.8);   
                left:0px;
                top:0px;
                width:100%;
                height:100%;
                display:none;
            }

            .btn_close
            {
                width:100%;
                text-align:right;
                color:#999999;
                cursor:pointer;
            }

            .content_box
            {
                width:100%;
                padding:20px;
            }
        </style>

        <script>
            function open_lb(varid)
            {
                document.getElementById("wrapper").style.display="block";       
               
document.getElementById("lb_content").innerHTML=content[varid];  
            }

            function close_lbt()
            {           
                document.getElementById("wrapper").style.display="none";           
            }
        </script>

    </head>


The close_lb() function is straightforward - just set the wrapper div's display property to none, thus rendering it - and all content within it - to vanish. For that to happen, you need to add this code in the HTML, like so.

                <div class="btn_close" onclick="close_lb();">
                    x close&nbsp;
                </div>


The open_lb() function does a wee bit more - it sets the wrapper div's display property to block, thus rendering it - and all content within it - to appear. And then it uses the varid variable which was passed in as an argument, to populate the lb_content div.

So let's create the content array, and fill it with data  like so. The images are, of course, to be saved to the same folder as your HTML file.
    <script> 
        var content=[];
        content[0]="<img src='00.jpg' height='400' align='left'> <p style='text-align:justify'>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas ultricies viverra eros, et rhoncus nulla accumsan vitae. Praesent mauris lectus, mollis non feugiat ut, suscipit id arcu. Aliquam ac gravida ipsum, et pretium risus. Phasellus euismod venenatis pharetra. Sed at neque vitae ipsum facilisis elementum. Cras auctor nunc nisi, nec congue odio luctus vitae. Ut a nisl quis purus gravida faucibus. Etiam ut nunc sed dui convallis efficitur sit amet nec tortor. Pellentesque elit sem, aliquet id dui id, ultricies dictum eros. Suspendisse egestas, ante sit amet volutpat vestibulum, risus ex accumsan diam, quis varius leo diam et neque. Etiam in efficitur diam. </p><p style='text-align:justify'>Etiam eget massa lorem. Nulla congue maximus tincidunt. Vivamus at efficitur libero. Etiam a aliquet metus, sit amet fermentum neque. In id auctor erat. Praesent a lacus nibh. Donec gravida augue eu nisi varius, in lacinia justo feugiat. </p><p style='text-align:justify'>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus fringilla augue non mollis sagittis. Vestibulum ullamcorper odio sit amet fermentum cursus. Ut vestibulum libero at risus rutrum, in dictum nibh lobortis. Aliquam urna velit, posuere imperdiet hendrerit eget, accumsan in nulla. Aliquam quis fringilla ex. Nunc auctor sapien nisi, nec efficitur lorem sollicitudin vel. Quisque diam lacus, rutrum eu nunc in, sollicitudin auctor lacus.</p>";
        content[1]="<img src='01.jpg' height='400' align='left'><p style='text-align:justify'>Aliquam erat volutpat. Maecenas id tristique libero. Aenean iaculis mi nec nisl tempor, sit amet lobortis nisi condimentum. Nulla ut odio quis velit pulvinar fringilla sit amet et nisi. Pellentesque sit amet faucibus massa, vel sodales mauris. Duis fringilla ut lacus sed ultricies. Suspendisse id auctor ipsum. Vestibulum lacinia nisl urna, quis mattis nulla placerat at. Curabitur sagittis risus nec euismod maximus. Morbi facilisis bibendum purus ac mattis. Vestibulum tempus efficitur massa, a convallis mi dapibus vitae. In pharetra vitae nulla eu malesuada. Ut aliquet volutpat tristique. Fusce pellentesque porta finibus. Aliquam erat volutpat. Maecenas id tristique libero. Aenean iaculis mi nec nisl tempor, sit amet lobortis nisi condimentum. Nulla ut odio quis velit pulvinar fringilla sit amet et nisi. Pellentesque sit amet faucibus massa, vel sodales mauris. Duis fringilla ut lacus sed ultricies. Suspendisse id auctor ipsum. Vestibulum lacinia nisl urna, quis mattis nulla placerat at. Curabitur sagittis risus nec euismod maximus. Morbi facilisis bibendum purus ac mattis. Vestibulum tempus efficitur massa, a convallis mi dapibus vitae. In pharetra vitae nulla eu malesuada. Ut aliquet volutpat tristique. Fusce pellentesque porta finibus. </p><p style='text-align:justify'>Sed ultricies tincidunt turpis, in feugiat mauris malesuada id. Morbi sit amet semper eros. Donec vestibulum sem quis congue luctus. Suspendisse turpis nulla, ornare nec erat et, tincidunt aliquet odio. Aliquam cursus felis nec sem volutpat fermentum. Aenean lacinia sapien sapien, sit amet tincidunt ligula eleifend at. Integer sit amet mi ac purus gravida tempus quis ac ipsum. Nullam ultrices eleifend enim, at rutrum lacus mollis vel. Donec sapien urna, pretium a augue ut, gravida tempus mi. Sed sit amet ullamcorper ante. Aliquam sagittis, justo in dictum auctor, nunc erat pellentesque magna, id facilisis tortor nisi eget ligula. Donec suscipit mattis velit. </p>";
        content[2]="<img src='02.jpg' height='400' align='right'><p style='text-align:justify'>Maecenas eu risus aliquet libero maximus facilisis ornare ac sapien. Nam ac sapien eu nulla laoreet mollis ac id purus. Vivamus dapibus ex sit amet turpis faucibus, quis euismod mi semper. Fusce quis tristique turpis, in porttitor eros. Vivamus non velit laoreet, semper enim a, volutpat velit. In hac habitasse platea dictumst. In mollis purus ipsum, at ultrices eros aliquam nec. In vestibulum lorem id felis tempor semper. </p><p style='text-align:justify'>Aenean id leo ultrices, dignissim orci non, rhoncus augue. Etiam posuere bibendum magna, quis congue nibh dapibus eget. Praesent pharetra a nisl eu euismod. Pellentesque consequat fermentum magna ut pharetra. Proin nec scelerisque est, eget mattis tellus. Nullam rhoncus pretium dolor, in fringilla eros interdum eget. Nulla facilisi. </p><p style='text-align:justify'>Vestibulum tellus odio, efficitur quis convallis et, imperdiet sed odio. Etiam nec dui at justo gravida semper nec a ex. Nam tellus nisi, aliquet in ipsum hendrerit, vulputate finibus ligula. Aliquam vel quam est. Sed volutpat lectus tortor, a rutrum lorem cursus non. Vivamus vitae vestibulum nibh, vel maximus tortor. Aliquam nibh nulla, ornare eget posuere id, luctus non lacus. Sed felis nisl, pretium vel nisl sed, scelerisque iaculis tortor. Mauris ex mauris, sagittis at risus at, molestie feugiat metus. </p><p style='text-align:justify'>Praesent ac magna in quam accumsan interdum. Vivamus faucibus volutpat neque, id pellentesque massa finibus in. Aliquam dapibus sem vel semper mollis. Praesent nec turpis purus. Mauris a diam congue, maximus nibh ac, ultrices ante. Ut a turpis mollis, placerat lacus eget, auctor eros. Nulla justo metus, ullamcorper eu tincidunt ut, lacinia a eros. Sed quis lobortis tortor. Ut pharetra ornare libero sit amet feugiat. Curabitur mattis augue quis tellus pulvinar scelerisque. Quisque eros risus, consectetur in pulvinar at, sollicitudin id sem. Quisque accumsan varius tortor, a semper ex pharetra ac. Mauris tristique vitae ante nec sagittis. Morbi facilisis felis non vulputate porta. Mauris dignissim, tellus sed dictum laoreet, erat leo eleifend leo, ut mollis dui elit non diam. </p>";
        content[3]="<img src='03.jpg' height='400' align='right'><p style='text-align:justify'>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ornare libero eu varius commodo. Nulla et bibendum lectus, eget rutrum ante. Integer lobortis pulvinar quam eget malesuada. Cras interdum nulla at elit pharetra ultrices. Integer pellentesque, sem id tempus viverra, urna dui semper sapien, et facilisis sapien diam ac sem. Phasellus sagittis est vel euismod laoreet. Nullam semper non leo ut facilisis. Suspendisse eu ante turpis. Donec vel lorem nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Etiam lacinia ac massa eu sodales. Aliquam tempor nisl erat, a ullamcorper purus venenatis sit amet. Duis lobortis, dolor et elementum faucibus, metus enim faucibus mi, eu posuere massa augue sit amet nulla. In aliquam consectetur ex. Praesent id nisl odio. </p><p style='text-align:justify'>Suspendisse euismod lacinia ligula. Etiam bibendum condimentum odio eget vulputate. Cras ultrices odio vel lacus rutrum, et tempor arcu porttitor. Vestibulum suscipit ante mattis sapien pretium, ac facilisis quam iaculis. Proin sapien ligula, condimentum eget dui posuere, vestibulum interdum purus. Morbi euismod, ipsum ut rhoncus congue, lectus turpis interdum justo, sit amet dapibus ex neque nec lectus. Sed vel rhoncus orci, sed porttitor ipsum. Nunc arcu ligula, volutpat eu ante euismod, maximus convallis sapien. Maecenas dignissim vel massa in fermentum. Pellentesque varius sapien ac maximus laoreet. Fusce eu eros porta, rhoncus massa fringilla, cursus leo. Etiam tempus libero non augue laoreet ultrices. </p>";
        content[4]="<img src='04.jpg' height='400' align='left'><p style='text-align:justify'>Quisque vehicula eros sed sem imperdiet, id dignissim erat dapibus. Pellentesque nec varius justo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur fringilla sodales diam a dictum. Curabitur non lacus efficitur, rutrum nisi vitae, accumsan urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cras gravida mauris libero, a pretium mi rutrum eget. Aliquam velit eros, vulputate ut ultrices eu, auctor tincidunt massa. Praesent posuere cursus vulputate. Maecenas suscipit lorem nec justo iaculis congue. In volutpat sodales interdum. Aenean vel urna non ante dapibus elementum eget ut neque. </p><p style='text-align:justify'>Vestibulum at lectus id tortor sagittis blandit. Vivamus in sapien sit amet justo tincidunt finibus. Pellentesque iaculis, sapien eget consectetur consectetur, sapien leo pretium libero, nec ultricies libero purus quis quam. Duis pharetra sem eget leo cursus maximus. In suscipit, nisl nec tempus volutpat, eros justo cursus leo, malesuada ullamcorper neque ipsum vel augue. Morbi cursus dui vitae nulla viverra vulputate. Donec in hendrerit lorem. </p><p style='text-align:justify'>Morbi non neque vel lacus vehicula vulputate. Phasellus pulvinar, nibh at fringilla condimentum, nulla ipsum consequat arcu, et sollicitudin nibh ipsum quis justo. Quisque imperdiet ligula et est sagittis, vel ultrices eros mattis. Fusce orci elit, fermentum a accumsan eget, porta auctor augue. Nam risus dui, sodales at tristique aliquam, ultrices non elit. Mauris vitae pharetra dui. Cras sollicitudin dignissim justo, non blandit eros pharetra sed. Etiam tristique metus magna, et blandit lacus lacinia et. Integer ac mauris et est pulvinar ultricies sit amet ut purus. Aliquam varius velit sollicitudin, ornare dolor quis, scelerisque tortor. Curabitur sed dolor dapibus, semper risus non, convallis nibh. Morbi suscipit sapien est, quis pellentesque nibh blandit sed. Quisque efficitur fermentum mauris, eu ultrices dolor dictum eget. Vivamus et odio enim. Aliquam pharetra vehicula vestibulum. </p>";

         
        function open_lb(varid)           
        {               
            document.getElementById("wrapper").style.display="block";                       
            document.getElementById("lb_content").innerHTML=content[varid];              
        }
           
        function close_lb()           
        {                           
            document.getElementById("wrapper").style.display="none";                       
        }       
    </script>

Yep, I'm going to use this opportunity to plug pictures of my nephew Paul. Do I hear a collective groan from the audience? Well, fuck you. If you guys can post your bimbotic selfies and pics of your cats and your lunch all over Facebook and Instagram, I am damn well going to post pics of my baby nephew. Deal with it!

For the purposes of brevity, the actual HTML code for the content array is listed here.

Now adjust your HTML so that clicking on the labels "Photo 1" to "Photo 5" brings up the Lightbox.
        <div>
            <div><a href="#" onclick="open_lb(0);">Photo 1</a></div>
            <div><a href="#" onclick="open_lb(1);">Photo 2</a></div>
            <div><a href="#" onclick="open_lb(2);">Photo 3</a></div>
            <div><a href="#" onclick="open_lb(3);">Photo 4</a></div>
            <div><a href="#" onclick="open_lb(4);">Photo 5</a></div>
        </div>


Now refresh your browser. Click on the links. Do the individual photos pop up in the Lightbox? And can you close the Lightbox by clicking on "x close"? Well, congratulations then! You've just made your first Lightbox!

Next

It's a boring Lightbox, truth be told. Let's jazz it up a little with some good old CSS3!


Monday 11 May 2015

Film Review: Unfriended

Unfriended, known in some circles as Cybernatural, is a horror movie in found footage format with social media as the theme. And while I'm not a big fan of the found footage genre (they make me giddy, and then some) the computer-based theme of the trailer was enough to pique my interest.

Technically, it's more of a variant of the found footage format, in the sense that the main narrative isn't told from the point-of-view of a handheld camera. Instead, the entire story takes place on the computer screen of the main character, with interaction among the other characters in the story taking place via chat  and webcam windows.


But make no mistake - this film is as much about cyberbullying as it is about technology. And in this case, the two are interlinked.

The Premise

A girl has a humiliating video of herself posted online, and it goes viral. She takes suicide. A year later, on the anniversary of her death, a group of teenagers are in a group chat when they are suddenly joined by an unknown user. All manner of attempts to evict the user, who identifies herself as the girl who killed herself, fail and the teenagers start getting picked off one by one.

Warning: Definite spoilers ahead!

This is a horror movie. And half the scare is in the unknown. If you're planning to watch it, you may want to skip all the way to the end.

The Characters

Shelley Hennig as Blaire Lily. The range of emotions she portrayed was entertaining - from seductive/virginal to peacemaker, to hysterical, to mortified, and finally guilty.

Moses Jacob Storm as Mitch Roussel, Blaire's boyfriend. A horny teenager who's best friends with Adam, which is the source of many more twists down the road. His performance was blah, and only merits a mention because the character had the second-most screen time in the movie. The Chekov's Gun in the shape of a knife, was a nice touch.

Will Peltz as Adam Sewell, tall. dark and brooding. With anger-driven impulses. I found the character more compelling than Mitch. Overacted a little near the end, but I can live with that.

Jacob Wysocki plays Ken Smith, the fat stoner dude who also happens to be the group's tech whiz. I liked this guy, but the moment he started being the one to come up with solutions to evict the ghost, I knew he would be among the first to die.

The rest of the cast were... bland. Their characters were typical bratty self-centered teenagers with no inkling of the consequences of their casual cruelty.

The Mood

Started out light-hearted and  - dare I say - banal, but quickly upped the tension and the creep factor as things progressed.

What I liked

Foreshadowing. "I GOT HER" was a nice touch.

The study in human behavior online. You'll see this in things Blaire, the main character, chooses to say to the group, in private to others, and things she initially wants to say and then retracts. And if you have enough of an eye for detail to look around what's shown of her desktop, you'll get a stunning amount of insight on her character.

You'll also see this in the way the characters use their perceived anonymity online to participate in malicious attacks on each other. And the scary thing about this is - it's based on things people do, and do on a regular basis.

What I didn't

The humiliating video taken of the vengeful ghost did not seem enough to warrant her suicide. Sure, honey. You got filmed passed out and soiling yourself. So what? Then again, I've never been a teen girl brought up in today's viral cyberworld, so...

Which brings me to my next point - this film will hit you particularly hard if you are a teenager brought up in today's viral cyberworld. Even to people like me, who grew up without the internet but have adapted to this way of life, this hits us more or less where we live. And if not, this may just look like some overlong advertisement for Skype, Facebook, Google, Instagram and YouTube. Oh, not to forget iTunes.

Also, the fact that the ghost of Laura Banks forces people to kill themselves, came off as a little trite.

Conclusion

I was entertained. Unfriended is a work of art, and the first of its kind. Hopefully it's the only one of its kind, not because it's bad, but because its appeal lies in its originality. Any follow-up clones would serve only to lessen the impact of the original.

My Rating

8 / 10

I give this flick one huge and heartfelt Like.
T___T

Wednesday 6 May 2015

The Prime Minister's New Sudoku

Two days ago at about 6pm, Singapore's current Prime Minister Lee Hsien Loong (who, for the purpose of brevity, will in this blogpost be referred to as LHL) posted the following on Facebook.

The Sudoku
solver


It referenced a speech he made on 20th April this year, a speech which I admittedly made no effort to listen to because up till then, I hadn't the faintest clue that this dude might say anything I would find worth listening to.

But man, was I wrong.

In his speech, LHL declared his intent to promote Information Technology. He accepted - nay, embraced - the changes that this age has foisted upon us, and the positive differences it has made in our lives. There's too many things cool about his speech and I don't want to regurgitate it all here, so follow this link for the transcript.

And if that wasn't awesome enough, he topped it off by posting a Sudoku solver he had written in C++ some years ago. I'll admit it - I was legit impressed.

Was I all that surprised though? Not really. It's common knowledge that our PM is a bit of a math prodigy. And while it would be a fallacy to say that all good programmers are also great mathematicians or vice versa, the two disciplines are somewhat interlinked. Math is about logic. So is programming.

I've looked at C++ program. As far as I can tell, it's pretty much just basic constructs, arrays and loops. Solid but not spectacular. As for the logic, I'm not about to try and dissect that. Math's not my thing. Sudoku, for Christ's sake.

The reaction has ranged from derision... 
"A mathematician leading a country. No wonder everyone is treated like a digit, and the country lost its soul."

"Sorry, not high enough for my standard"


...to outright sycophantic.
"I think that u are the only prime minister on our planet who can code as a truly professional programmer"

"There you have it, a Prime Minister who can write codes! You need a problem solver in every chaotic situation, now I see why Singapore progresses."


We probably need to hold our horses here. While I agree that this little display puts the PM's IQ at above average, this has little or nothing to do with how he's run the country so far, or his ability to do so. I mean, math is math. Leadership is leadership.

But still! I knew our PM was good at numbers. Just didn't know he could program too.

It figures, eh?
T___T


Friday 1 May 2015

Whitelisting - a Paler Shade of Security

URL parameters are an easy and convenient way for web pages to pass data to other pages. And, where SEO is concerned, it's a plus because URLs can be cached. But sometimes it can be too convenient. People tend to forget that such methods are open to abuse and appropriate measures can (and should) be taken against said abuse.

Below are some instances of URL parameters, where products is the page name, and id and type are the parameters, and "34400" and "cars" are their respective values.

products.php?id=34400&type=cars
products/cars/34400

Obviously, some of the security risks are SQL Injection and XSS. I'm writing this with the assumption that you know what that is, and on the off-chance that you don't, check out an explanation of SQL Injection and XSS.

There are plenty of ways to deal with such threats, some at script level (depending on language), some at database level (depending on database). But these aren't under discussion today, because there is a simple and non platform-specific solution at the logical level: whitelisting.

What's Whitelisting?

Whitelisting is a technique that ensures that the values of the parameters conform to a specific range of values. At its simplest, here is a preliminary example. (All examples are in PHP)

URL: products.php?id=56700
<?php
$productid = $_GET["id"];
$productid = intval($productid);
?>

The above example ensures that the variable productid, when taken from the URL, is an integer, by converting the value of productid to its integer equivalent. With this, it's not possible to enter malicious code into the parameter, and the usability of the data is preserved. If I wanted to be pedantic about this, the above could be termed sanitization instead of whitelisting.

To take this further and to see a more comprehensive example of whitelisting, see the following.

URL: report.php?month=11&year=2011
<?php
$reportmonth = $_GET["month"];
$reportmonth = intval($reportmonth);

if ($reportmonth<1) $reportmonth=1;
if ($reportmonth>12) $reportmonth=12;

$reportyear = $_GET["year"];
$reportmonth = intval($reportmonth);

if ($reportyear<1969) $reportyear=1969;
if ($reportyear>year(date)) $reportyear=year(date);
?>
See what went on there? The variables reportmonth and reportyear were forced to conform to a range of values. reportmonth had to be a value from 1 to 12. reportyear had to be a value from 1969 to the current year. This makes it impossible for the values to do any damage if written as part of an SQL string.

What if input is a string? 

Well, in that case we can't convert the value to integer. But, we can still make input conform via an array. URL: products.php?type=cars
<?php
$producttype = $_GET["type"];

$wl_producttype = array();
$wl_producttype[] = "buses";
$wl_producttype[] = "cars";
$wl_producttype[] = "vans";
$wl_producttype[] = "lorries";

if (!in_array($producttype,$wl_producttype)) $error=true;
?>

With this, we ensure that the value of producttype is either "buses", "cars", "vans" or "lorries". All else produces an error.

What if there's no range to conform to? 

That can happen, yes. If, for example, the parameter is a search string and thus can theoretically be any value, then there's no conformity to speak of. Therein lies the limitation of whitelisting. Simple and elegant, but applicable only to very specific instances such as those outlined.

Why go to that trouble, then?

You'd be surprised, though, how many web developers don't bother with this, hoping that more advanced techniques will catch any monkey business. I think that's terribly short-sighted. It's good to secure your code at a logical level to weed out any possible exceptions before letting more advanced security techniques do their job.

messagetype=goodbye&article=whitelisting
T___T