Kudos to the men behind the suits - Alien and Predator series

Bolaji Badejo - The actor behind alien Source
On a school holiday many years ago, dad and I were watching Star Wars on tv on a late night.  Not long after the movie started, he'd dozed off on the couch while I was still lying on the floor, mesmerized by the scenes of Jedi fighting off Darth Vader's forces.  Watching movies have been part of life, be it action, horror, comedy but definitely not love ones.

forever alone achievement  unlocked!

Today, I came across these articles which I think it's interesting to share, especially when Alien prequel, Prometheus Bluray has just released.  The actor behind the Alien suit is not known by many as he's just briefly introduced in Alien Anthology Bluray set which contains a total of 6 hours extra videos.

TL;DR
...he was called Bolaji Badejo, born and raised in Nigeria, and that he had ended up in the  Alien film by chance. He had only been in London to take a course when a casting agent approached him in a pub and asked if he wanted to audition for a role in a science fiction movie...
- SIGGE EKLUND 19:31 JUNE 7, 2012 

One of the men who built the famous model of Nostromo told me a bad news: "Bolaji committed suicide shortly after he returned to Nigeria," he writes in an email.
- SIGGE EKLUND 19:31 JUNE 7, 2012

the producers put him in a different hotel than the rest of crews, some distance away from the shooting, that he would feel extra strange and scary when he showed up. And it worked. He was always very lonely on the recording. Sat in his swing.
- SIGGE EKLUND 19:31 JUNE 7, 2012

Only Bolaji and HR Giger were allowed to watch the rushes of the Alien footage with Ridley Scott, so they could work out problems together on how best to show the Alien and represent the movements and actions required. Most of the footage Bolaji filmed never made it into the movie, due to problems.
6:59 AM OCTOBER 18, 2012

HR Giger made the Alien suits worn by Bolaji and the stuntman out of latex, at a cost of more than $250,000. The suit consisted of some ten to fifteen separate pieces, worn over a one-piece black body suit, needed underneath to disguise the fact that the Alien fitted together in sections
6:59 AM OCTOBER 18, 2012

Bolaji regrets that no one can recognise him as the Alien in the film, but thinking back on Boris Karloff, Christopher Lee, or other successful actors who began their careers by playing grotesque monsters, he adds, "The fact that I played the part of the Alien, for me, that’s good enough. Legally, I’ll be given the opportunity of doing a follow-up, if there is one."
6:59 AM OCTOBER 18, 2012
As for the other famous series, the 7' 2" actor, Kevin Peter Hall played the first two movies' iconic monster from space - Predator.

During its developmental stages, the Predator was going to be played by Jean-Claude Van Damme, who played the Predator for the first few scenes but wasn't billed in the end credits. 
Wikipedia

Van Damme was cast to portray a “small, martial-arts creature”.  However, the cast was so full of big men (Schwarzenegger, Ventura, Landham, Weathers), so the producers changed their mind, and Van Damme himself was not satisfied, as being credited as a “special effect” in the ending of the film. So, the idea was dropped, and a new look for the predator was created, and could realistically physically dominate the film’s human characters.
bzfilm.com

Can be seen in Predator (1987) without costume. He is the helicopter pilot at the end of the film.
IMDB

He was in a major car accident in Los Angeles. During surgery for his critical wounds, he received a contaminated blood transfusion. He died shortly thereafter of AIDS.
IMDB

"When I first came to California it was fun and exciting to get any part in any movie and get paid for it. Because of my size and my background it seemed like I was right for just about anything. I did go through a period where I thought it was time to give up monster movies. But then the scripts and the effects started getting better. I was treated better and starting getting paid more. Doing creatures these days is more of a job for me than it was in the beginning. In the early days I was creating these creatures and basically getting lost in them. Now with creatures like Harry and the Predator it's more a matter of getting deeper into their characters and making sure they work."
IMDB - 1990 interview



I once had a crazy/naive thought of those temporary actors in action movies (during primary school time).  The special effect is so surreal that it made me wonder how the director find so many extras to be killed by the main actor.  My thoughts?!  They must be people who intends to commit suicide or criminals who were sentenced to death...




Related:

How to implement achievement system in CodeIgniter

In this post, I'm going to implement a reward system using PHP, similar to the current console generation's game achievements. Certain user interactions which satisfy the game's predefined set of requirements will trigger an event of showing the reward. E.g. Survive a fall from 400m will unlock the achievement of "Die Hard".

How to implement this feature in PHP? Since I've been working on CodeIgniter MVC, I shall introduce you a library, simply called as "CodeIgniter Events" by Eric Barnes and Dan Horrigan.

Steps

  1. Download the latest CodeIgniter here, version 2.1.3 as of writing 
  2. Download CodeIgniter Events library here
  3. Add the autoload line in config/autoload.php and put the events.php in application/libraries folder

Tasks

Whenever user types more than 5 characters into a text field and clicks 'Send' button, it will trigger the event class and show the achievement text.

Solution


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Comments</title>
<style type="text/css">
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head>
<body>
<div id="container">
<form id="jForm" name="jForm" method="POST">
<h3>Comments</h3>
<input type="text" id="comment" name="comment" maxlength="150" />
<input type="button" id="btnsubmit" name="btnsubmit" value="Send" />
</form>
</div>
</body>
</html>
<script type="text/javascript">
$(document).ready(function () {
$('#btnsubmit').click(function(){
$('#jForm').submit();
});
});
</script>
view raw exp.php hosted with ❤ by GitHub
public function __construct() {
parent::__construct();
// You can put the Badge class in application/libraries but I want to try out third_party feature of CI
// If you put it into application/third_party folder, please create 'config', 'controllers', 'helpers', 'language', 'libraries', 'models', 'views' folders
// under 'application/third_party/achievements' directory
$this->load->add_package_path(APPPATH.'third_party/achievements/');
$this->load->library('badge');
}
public function comment() {
if($_POST) {
$c = $this->input->post('comment');
echo Events::trigger('badges', $c, 'string'); //3rd: 'array', 'json', 'serialized', or 'string'
}
$this->load->view('exp');
}
view raw welcome.php hosted with ❤ by GitHub
class Badge {
public function __construct() {
// Define all the achievements
Events::register('badges', array($this, 'badgeCommentator'));
Events::register('badges', array($this, 'badgeContributor'));
}
public function badgeCommentator($comment = '') {
if (!empty($comment) && strlen($comment) > 5) {
return 'Achievement: Badass Commentator';
}
}
public function badgeContributor($param = '') {
//...
}
}
view raw badge.php hosted with ❤ by GitHub

My toilet's flushing system is hissing...

Bills do like to come around end of the month, don't they?  I got a shock the other day when my water bill arrived, it's $100 more than the average.  I checked the bill details and found out the sewage charge is way more than usage.

Let me guess, this could be due to
  • People in the house is peeing and shitting more often
  • The sewage meter is malfunctioned
  • Somewhere is leaking!!

I called a local plumber (which I found his contact from TrueLocal) and got the second shock.  They're going to charge $60 on arrival to the property (even though they're based in a neighbouring suburb), $20 for every 20 minutes.  It would take them at least 1 - 2 hours to carry out leak investigation and fixing.

Looking at my dry wallet, I decided to fix it on my own, the most suspicious thing would be the hissing sound coming out from the toilet's flushing system.  The hissing noise will stop if I twist the screw a bit tighter.  But when water refills the tank, the noise starts again.  Googling the issue leads me to exchange of a flapper in the outlet valve of the flushing system.

Steps to do to confirm a leak:
  1. When the water tank is filled, turn off the water supply where the minitap is normally situated below the flushing system.
  2. Come back after 15 - 30 minutes, check if the water level has dropped.

In my case, the water tank has gone empty.  Right, leaking issue half solved!  In order to let the professionals to identify the exact problem, I disassembled the outlet valve and brought it to Bunnings.  Have the wrong size of flapper substituted (it's still leaking!), I then drove to Caroma service centre and bought another flapper (price is < $2.00).  Once it's fitted into the outlet valve properly, all fixed!

TIL
  • water company charges any amount of water coming in and going out of the property 
  • not all flappers can fix a leaking valve, even though they look very similar.

Step-by-Step Guide

Turn off the water supply
Take out the middle (yellowish) outlet valve, the right  cylinder is the inlet valve
The outlet valve structure, flapper is shown as the black rubber plate at the end to prevent water from flowing into the toilet bowl
Replace it, the old one may look bigger as it has inflated along the years.  The new flapper as seen in the packaging is the wrong one that I've bought from Bunnings
Remember to slightly turn the platform that holds the flapper clockwise until they're firnly attached.  Install it back, mission accomplished!!

How to use POCO C++ library to receive emails and analyse contents

I've one task to do, and that is:
  • Get emails from accounts, account info (username, password, saveBody, saveAttachments) can be obtained from EmailInboundConfig object
  • Retrieve subject, each attachment's filename

After comparing 3 open source C++ email handling libraries, I've decided to give POCO library a go.  Remember to include the following in the header (*.h) files.

#include "Poco/Net/POP3ClientSession.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/NameValueCollection.h"
#include "Poco/Net/QuotedPrintableDecoder.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Exception.h"
#include "Poco/StreamCopier.h"
#include "Poco/Base64Decoder.h"
#include <iostream>
#include <fstream>


#ifndef MYMAILMESSAGE_H
#define MYMAILMESSAGE_H
#include "Poco/Net/POP3ClientSession.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/NameValueCollection.h"
#include "Poco/Net/QuotedPrintableDecoder.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Exception.h"
#include "Poco/StreamCopier.h"
#include "Poco/Base64Decoder.h"
#include "utils/String.h"
#include <iostream>
#include <fstream>
using namespace std;
using Poco::Net::POP3ClientSession;
using Poco::Net::MailMessage;
using Poco::Net::PartHandler;
using Poco::Net::MessageHeader;
using Poco::Net::NameValueCollection;
using Poco::Net::MultipartReader;
using Poco::StreamCopier;
using Poco::Exception;
class MyMailMessage: public MailMessage {
public:
const string GetCustomSender();
const string GetContentTypeProperty();
};
#endif
view raw MyMailMessage.h hosted with ❤ by GitHub
/**
* @name EmailInbound (Mail Message Handler for POCO)
* @description Receive and sort emails
*/
#include "MyMailMessage.h"
/**
* POCO::Net::MailMessage
*/
const string MyMailMessage::GetCustomSender()
{
//getSender() will return: John Smith <john.smith@xxx.com>
//This function will grab the email part only
string sender = getSender();
string senderEmail = "";
size_t leftQuotePos;
leftQuotePos = sender.find_last_of("<");
size_t rightQuotePos;
rightQuotePos = sender.find_last_of(">");
size_t emailLength;
emailLength = rightQuotePos - leftQuotePos - 1;
senderEmail = sender.substr(leftQuotePos + 1, emailLength);
return senderEmail;
}
const string MyMailMessage::GetContentTypeProperty()
{
//20120208: Expect the unexpected!! One email appears to have such content type: Content-Type: APPLICATION/PDF; name="8257049.PDF"
//Content Type:application/pdf; name="Invoice.pdf"
//This function to get the value of 'name' property, return Invoice.pdf as result
string ct = getContentType();
string cti = String::ToLower(ct); //for case insensitive find of keyword
string filename = "";
if(cti.find("application") != string::npos && cti.find("name") != string::npos) {
size_t startPos = ct.find("=");
size_t filenameLength = 0;
if(startPos != string::npos) {
if(ct[startPos + 1] == '"') {
filenameLength = ct.size() - (startPos + 2) - 1; //skip [="] (thus +2)
filename = ct.substr(startPos + 2, filenameLength);
} else {
filename = ct.substr(startPos + 1); //skip [=] (thus +1) and get from that index way to the end
}
}
}
return filename;
}
#ifndef MYPARTHANDLER_H
#define MYPARTHANDLER_H
#include "Poco/Net/POP3ClientSession.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/NameValueCollection.h"
#include "Poco/Net/QuotedPrintableDecoder.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Exception.h"
#include "Poco/StreamCopier.h"
#include "Poco/Base64Decoder.h"
#include "utils/Directory.h"
#include "utils/String.h"
#include <iostream>
#include <fstream>
using namespace std;
using Poco::Net::POP3ClientSession;
using Poco::Net::MailMessage;
using Poco::Net::PartHandler;
using Poco::Net::MessageHeader;
using Poco::Net::NameValueCollection;
using Poco::Net::MultipartReader;
using Poco::StreamCopier;
using Poco::Exception;
class MyPartHandler: public PartHandler
{
public:
void handlePart(const MessageHeader& header, std::istream& stream);
const string& GetBody();
const vector<string>& GetHeaders();
const vector<string>& GetFilenames();
const vector<string>& GetAttachments();
string DecodeString(string phrase);
void CleanUp();
private:
string _body;
string _myboundary;
vector<string> _headers;
vector<string> _filenames;
vector<string> _attachments;
};
#endif
view raw MyPartHandler.h hosted with ❤ by GitHub
/**
* @name EmailInbound (Mail Part Handler for POCO)
* @description Receive and sort emails
*/
#include "MyPartHandler.h"
/**
* POCO::Net::PartHandler
* Documentation: http://pocoproject.org/docs/
* Called for every part encountered during the processing of an email message
* For Multipart message, it has the following pattern:
* Content-Transfer-Encoding="quoted-printable"
* Content-Type="text/plain"; charset="us-ascii"
* ....
* Content-Transfer-Encoding="quoted-printable"
* Content-Type="text/html"; charset="us-ascii"
* <html>
* ....
* </html>
*/
void MyPartHandler::handlePart(const MessageHeader& messageHeader, std::istream& stream)
{
stringstream headerSS;
messageHeader.write(headerSS);
_headers.push_back(headerSS.str());
if(messageHeader.has("Content-Disposition")) {
//If there is any file attachment, append the filename and attachment to vectors
string disp;
string filename;
string attachment;
NameValueCollection params;
MessageHeader::splitParameters(messageHeader["Content-Disposition"], disp, params);
filename = params.get("filename", "nil");
if(filename != "nil") {
// Filename might be encoded in Base64 or QuotedPrintable
_filenames.push_back(DecodeString(filename));
StreamCopier::copyToString(stream, attachment);
_attachments.push_back(attachment);
}
}
string contentType = messageHeader.get("Content-Type", "nil");
if((String::ToLower(contentType)).find("multipart") == 0) {
MultipartReader multipartReader(stream);
while(multipartReader.hasNextPart()) {
MessageHeader subMessageHeader;
multipartReader.nextPart(subMessageHeader);
string subContentType = subMessageHeader.get("Content-Type", "nil");
// Convert to lower case for comparison only
string lc_subctype = String::ToLower(subContentType);
//Priority is text/plain format, else save text/html format
if(lc_subctype == "nil") {
continue;
} else if(lc_subctype.find("application") != string::npos && lc_subctype.find("name") != string::npos) {
// Save attachment(s) in sub-content part
string disp;
string filename;
string attachment;
NameValueCollection params;
MessageHeader::splitParameters(lc_subctype, disp, params);
filename = params.get("name", "nil");
if(filename != "nil") {
// Filename and Attachments might be encoded in Base64 or QuotedPrintable
_filenames.push_back(DecodeString(filename));
string encoder = String::ToLower(subMessageHeader.get("Content-Transfer-Encoding", "nil"));
if(encoder == "base64") {
Poco::Base64Decoder base64Decoder(multipartReader.stream());
StreamCopier::copyToString(base64Decoder, attachment);
} else if(encoder == "quoted-printable") {
Poco::Net::QuotedPrintableDecoder qpDecoder(multipartReader.stream());
StreamCopier::copyToString(qpDecoder, attachment);
} else {
StreamCopier::copyToString(multipartReader.stream(), attachment);
}
if (!attachment.empty()) {
_attachments.push_back(attachment);
}
}
} else if(lc_subctype.find("boundary") != string::npos) {
int bStart = 0;
if(_myboundary.empty()) {
bStart = subContentType.find('_');
_myboundary = String::FixField(subContentType, bStart, (subContentType.length() - (bStart + 1)));
}
} else if(lc_subctype.find("text/plain") == 0) {
string charset;
if(subContentType.find("charset") != string::npos) {
//Outlook: Content-Type text/plain charset="us-ascii"
//Yahoo: Content-Type text/plain charset=iso-8859-1
string subct_clean = String::RemoveChar(subContentType, '"');
int charpos = subct_clean.find("charset=") + 8; //+8 to bypass the word "charset="
charset = String::FixField(subct_clean, charpos, (subContentType.length() - charpos) );
}
//If body variable is not empty, it has the text/plain format of the email body.
string cte = subMessageHeader.get("Content-Transfer-Encoding", "nil");
//For some reasons, emails from outlook (content transfer encoding is specified as quoted-printable in header), it generates nil result in QuotedPrintableDecoder
if(charset.compare("us-ascii") != 0) {
if(cte == "base64") {
Poco::Base64Decoder base64Decoder(multipartReader.stream());
StreamCopier::copyToString(base64Decoder, _body);
} else if(cte == "quoted-printable") {
Poco::Net::QuotedPrintableDecoder qpDecoder(multipartReader.stream());
StreamCopier::copyToString(qpDecoder, _body);
} else {
StreamCopier::copyToString(multipartReader.stream(), _body);
}
} else {
StreamCopier::copyToString(multipartReader.stream(), _body);
}
if(!_myboundary.empty() && _myboundary.compare(multipartReader.boundary()) != 0) {
_body = String::Trim(String::FixField(_body, 0, (_body.find(_myboundary) - 2))); //-2 for the boundary heading, e.g. --_000_OD67Eexchau_
}
} else {
if(_body.empty() || _body.length() > 0) break;
// Will hit error "Malformed message: Field value too long/no CRLF found" under MesssageHeader.read() in MessageHeader.cpp
// if "continue" is used. "text/plain" part will always come before "text/html" part
//Keep this code for reference of retrieving text/html content, ignore text/html part at this moment
/*
else if(subContentType.find("text/html") == 0) {
string cte = subMessageHeader.get("Content-Transfer-Encoding", "nil");
if(cte == "base64") {
Poco::Base64Decoder base64Decoder(multipartReader.stream());
StreamCopier::copyToString(base64Decoder, _body);
} else if(cte == "quoted-printable") {
Poco::Net::QuotedPrintableDecoder qpDecoder(multipartReader.stream());
StreamCopier::copyToString(qpDecoder, _body);
} else
StreamCopier::copyToString(stream, _body);
*/
}
}
} else if((String::ToLower(contentType)).find("application") != string::npos && (String::ToLower(contentType)).find("name") != string::npos) {
// Some oddball emails doesn't have a Content-Disposition clause even though they've attachments.
// Decoding is not necessary at top level as POCO will do it automatically. weird...need more testing
string disp;
string filename;
string attachment;
NameValueCollection params;
MessageHeader::splitParameters(String::ToLower(contentType), disp, params);
filename = params.get("name", "nil");
if(filename != "nil") {
_filenames.push_back(DecodeString(filename));
/*
string encoder = String::ToLower(messageHeader.get("Content-Transfer-Encoding", "nil"));
if(encoder == "base64") {
Poco::Base64Decoder base64Decoder(stream);
StreamCopier::copyToString(base64Decoder, attachment);
} else if(encoder == "quoted-printable") {
Poco::Net::QuotedPrintableDecoder qpDecoder(stream);
StreamCopier::copyToString(qpDecoder, attachment);
} else
*/
StreamCopier::copyToString(stream, attachment);
if(!attachment.empty()) _attachments.push_back(attachment);
}
} else {
//Email body content
//Change request 20101007: Ignore text/html part
if(contentType.find("text/html") == string::npos && (_body.empty() || _body.length() > 0))
StreamCopier::copyToString(stream, _body);
}
}
const vector<string>& MyPartHandler::GetHeaders() {
return _headers;
}
const string& MyPartHandler::GetBody() {
return _body;
}
const vector<string>& MyPartHandler::GetFilenames() {
return _filenames;
}
const vector<string>& MyPartHandler::GetAttachments() {
return _attachments;
}
/**
* This function can decode mixed languages within one string (email subject, file attachment)
* For example (mixed of english and ukrainian):
* charset="windows-1251"
* =?windows-1251?Q?outlook:_testing_with_english_text....and_ukrainian_=EA?= =?windows-1251?B?7u3q8/DxIOTw4Oru7bPi8fzq6PUg9+7i7bPi?=
**/
string MyPartHandler::DecodeString(string phrase) {
//If the phrase is encoded in base64 or quoted printable text, it shows
//=?gb2312?B?ztLKc3re4==?=
//Which is enclosed in =??= quotes, B stands for 'base64' encoded, Q stands for 'quoted-printable' encoded.
if(String::Trim(phrase).length() == 0) {
return phrase;
}
if(String::IsBeginWith(phrase, "=?") && String::IsEndWith(phrase, "?=")) {
string utf8Phrase = "";
size_t leftQuotePos = phrase.find("=?");
size_t rightQuotePos = phrase.find("?=");
while(leftQuotePos != string::npos && rightQuotePos != string::npos) {
//+2 is for the ending ?=
string quotedString = phrase.substr(leftQuotePos, rightQuotePos - leftQuotePos + 2);
string decodedPhrase = "";
string textEncoding = String::TakeField(quotedString, 2, "?");
string encodedType = String::TakeField(quotedString, 3, "?");
string encodedString = String::TakeField(quotedString, 4, "?");
if(encodedType == "B") {
istringstream iss(encodedString);
Poco::Base64Decoder base64Decoder(iss);
StreamCopier::copyToString(base64Decoder, decodedPhrase);
} else if(encodedType == "Q") {
istringstream iss(encodedString);
Poco::Net::QuotedPrintableDecoder qpDecoder(iss);
StreamCopier::copyToString(qpDecoder, decodedPhrase);
//Quoted printable treated space as underscore, revert it
replace(decodedPhrase.begin(), decodedPhrase.end(), '_', ' ');
} else {
decodedPhrase = quotedString; //safety measure
}
if (String::ToLower(textEncoding) != "utf-8") {
string errorMessage = "";
string convertedPhrase = "";
//Microsoft Outlook 2007 cannot differentiate between simplified and traditional chinese for email subject.
//It will only list the content type as GB2312, thus we need to do a conversion.
if (String::ToLower(textEncoding) == "gb2312") {
String::ConvertTextEncoding("GBK", "UTF-8", decodedPhrase, convertedPhrase, errorMessage);
} else {
String::ConvertTextEncoding(textEncoding, "UTF-8", decodedPhrase, convertedPhrase, errorMessage);
}
if (errorMessage.length() > 0) {
return "";
} else {
utf8Phrase += convertedPhrase;
}
} else {
utf8Phrase += decodedPhrase;
}
leftQuotePos = phrase.find("=?", leftQuotePos + 1);
rightQuotePos = phrase.find("?=", rightQuotePos + 1);
}
return utf8Phrase;
} else {
return phrase;
}
}
void MyPartHandler::CleanUp() {
_body = "";
_myboundary = "";
_headers.clear();
_filenames.clear();
_attachments.clear();
}
#ifndef SERVICE_IMPL_H
#define SERVICE_IMPL_H
#include "Poco/Net/POP3ClientSession.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/NameValueCollection.h"
#include "Poco/Net/QuotedPrintableDecoder.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Exception.h"
#include "Poco/StreamCopier.h"
#include "Poco/Base64Decoder.h"
#include "utils/String.h"
#include "include/MyMailMessage.h"
#include "include/MyPartHandler.h"
#include <iostream>
#include <fstream>
using namespace std;
using Poco::Net::POP3ClientSession;
using Poco::Net::MailMessage;
using Poco::Net::PartHandler;
using Poco::Net::MessageHeader;
using Poco::Net::NameValueCollection;
using Poco::Net::MultipartReader;
using Poco::StreamCopier;
using Poco::Exception;
#define MAIL_SERVER "mail.yourcompanyserver.com"
/**
* Service Implementation
*/
class Service
{
public:
Service();
virtual ~Service();
void Init();
void Run();
void Stop();
private:
void ProcessEmail(EmailInboundConfig* emailInboundConfig, MyMailMessage& mailMessage, MyPartHandler& handler);
};
#endif
view raw Service.h hosted with ❤ by GitHub
/**
* @name EmailInbound
* @description Receive and Sort emails
*/
#include "Service.h"
/**
* Constructor
*/
Service::Service()
{
}
/**
* Destructor
*/
Service::~Service()
{
}
/**
* Initialises this, the service implemenation class
*/
void Service::Init()
{
}
/**
* Determines which mode the service is running in and then executes the appropriate 'Run' method
* (called automatically by the ServiceBase class)
*/
void Service::Run()
{
EmailInboundConfig *emailInboundConfig = GetEmailInboundConfig(localDatabase, serviceConfigID);
if (_IsError) {
if (_Verbose) {
VerboseLog(">>> EMAIL CLIENT CONFIG ERROR");
}
HandleSystemError();
delete emailInboundConfig;
continue;
}
//Connect to account and see if there is any new email
try {
POP3ClientSession ppcs(MAIL_SERVER);
MyPartHandler partHandler;
MyMailMessage mailMessage;
POP3ClientSession::MessageInfoVec messageInfoVec;
ppcs.login(emailInboundConfig->GetUsername(), emailInboundConfig->GetPassword());
ppcs.listMessages(messageInfoVec);
for (unsigned int i = 1; i <= messageInfoVec.size(); i++) {
ppcs.retrieveMessage(i, mailMessage, partHandler);
//Gather details of the email received and log them
stringstream headersSS;
mailMessage.write(headersSS);
vector<string> partHeaders = partHandler.GetHeaders();
for (unsigned int j=0; j < partHeaders.size(); j++) {
headersSS << partHeaders[j];
}
if (mailMessage.isMultipart()) {
InsertEmailInboundLog(localDatabase, serviceConfigID, headersSS.str(), partHandler.GetBody());
} else {
// Save body content only if [name] property doesn't exist in ContentType
string ct_filename = mailMessage.GetContentTypeProperty();
if (ct_filename.size() == 0) {
InsertEmailInboundLog(localDatabase, serviceConfigID, headersSS.str(), mailMessage.getContent());
}
}
// Process the email
ProcessEmail(emailInboundConfig, mailMessage, partHandler);
if (_IsError) {
HandleSystemError();
}
mailMessage.clear();
ppcs.deleteMessage(i);
}
ppcs.close();
} catch(Exception& e) {
RaiseSystemError("Exception raised by POCO while processing. " + e.displayText());
HandleSystemError();
delete emailInboundConfig;
continue;
}
delete emailInboundConfig;
}
/**
* Performs any additional steps required to stop
* (called automatically ServiceBase class Stop method)
*/
void Service::Stop()
{
}
/**
* Processes the email, as required
*
* @param emailInboundConfig EmailInbound Config
* @param mailMessage Email to process
*/
void Service::ProcessEmail(EmailInboundConfig* emailInboundConfig, MyMailMessage& mailMessage, MyPartHandler& partHandler)
{
string creatorFilePath;
string outputBodyPath = _PhoenixSettings->GetBaseTempPath() + "body.txt";
string bodyFilename = File::ExtractFilename(outputBodyPath);
if (_Verbose) {
VerboseLog("Body file path= " + outputBodyPath + "; bodyFilename = " + bodyFilename);
}
//Step 1: Check whether to save body content
if (emailInboundConfig->GetSaveBody() == "Yes") {
File* contentFile = new File(outputBodyPath, File::MODE_WRITE);
string content;
try {
if(mailMessage.isMultipart()) {
content.append(partHandler.GetBody());
} else {
// Skip saving body content if ContentType header has [name] property
string ct_filename = mailMessage.GetContentTypeProperty();
if (ct_filename.size() == 0) {
content = mailMessage.getContent();
}
}
} catch(Exception& e) {
RaiseSystemError("POCO error:" + e.displayText());
return;
}
if(content.length() > 0) {
contentFile->Write(content);
contentFile->Close();
delete contentFile;
stringstream tempFilePath;
tempFilePath << _PhoenixSettings->GetBaseGlobalPath() << "creator/in/" << DateTime::NowString("%Y%m%d%H%M%S","GMT") << "_" << _ServiceInstance->GetID();
File *creatorFile = new File(tempFilePath.str(), File::MODE_CREATEUNIQUE);
if (creatorFile->IsError()) {
RaiseSystemError("Unable to create unique file for creator - " + creatorFile->GetErrorMessage());
delete creatorFile;
return;
}
creatorFilePath = creatorFile->GetFilename();
delete creatorFile;
if (!File::Copy(outputBodyPath,creatorFilePath)) {
RaiseSystemError("Unable to copy file attachment \"" + outputBodyPath + "\" to creator in \"" + creatorFilePath + "\"");
return;
}
// Do some file processing here
// ...
if(!File::Delete(outputBodyPath)) {
RaiseSystemError("Unable to remove body file after put into creator - " + outputBodyPath);
}
}
}
//Step 2: Check whether to save file attachments
if (emailInboundConfig->GetSaveAttachments() == "Yes") {
vector<string> filenames;
vector<string> attachments;
// Check if message is multipart
if (mailMessage.isMultipart()) {
//Retrieve filenames & attachments
filenames = partHandler.GetFilenames();
attachments = partHandler.GetAttachments();
} else {
// For some oddball reason, a mail, which has attachment as the body might have no MIME boundary defined
// Example Message Header with no boundary and body content defined (blank) but attachment is located in body content:
// Content-Description: PDF Conversion
// Content-Disposition: attachment; filename="Invoice.pdf"
// Content-Transfer-Encoding: base64
// Content-Type: application/pdf; name="Invoice.pdf" <-- Poco library can only retrieve this field without going through MessageHeader
// Step 1: Check if "Content-Type" clause exists in header. if so, extract filename.
// Check list of MIME types
string ct_filename = mailMessage.GetContentTypeProperty();
if(ct_filename.size() > 0) {
filenames.push_back(ct_filename);
// Step 2: Retrieve the body content (attachment)
attachments.push_back(mailMessage.getContent());
}
}
}
//Step 3: Clean up
partHandler.CleanUp();
}
view raw Service.cpp hosted with ❤ by GitHub
#ifndef String_H
#define String_H
#include <string>
#include <sstream>
#include <errno.h>
#include <iconv.h>
#include <vector>
using namespace std;
namespace custom
{
namespace utils
{
#define TEXTENC_BUFFER 10000 //buffer size for iconv text encoding conversion - currently limited to 10KB which should be plenty for individual string or line processing
/**
* A collection of useful static string utility methods
*/
class String
{
public:
static string TakeField(const string &source, int fieldNumber, char delimiter);
static string TakeField(const string &source, int fieldNumber, string delimiter);
static string FixField(const string &source, int start, int length);
static string Trim (const string &source);
static bool ConvertTextEncoding(string fromEncoding, string toEncoding, const string &inputStr, string &outputStr, string &errMsg);
static void Split(const string &s, char delim, vector<string> &elems);
static bool IsBeginWith(const string &source, string prefix);
static bool IsEndWith(const string &source, string suffix);
static bool IsNumeric(const string &number, string ignoreChars = "");
static string RemoveChar(const string &source, char remove);
static string RemoveChars(const string &source, const string &remove);
//template function which takes any basic type and converts it to a string using the stringstream which has already overloaded the << operator for basic types
template <class T>
static string ToString(T a){stringstream s; s << a; return s.str();}
private:
};
}
}
#endif
view raw String.h hosted with ❤ by GitHub
#include "String.h"
using namespace custom::utils;
/**
* Search for the field at the specified field number and returns its data.
*
* @param source The source string to take the field data from
* @param fieldNumber The number (from 1-n) of the field to take data from
* @param delimiter The character which delimits the fields in the source
* @return The data found in the field
*/
string String::TakeField(const string &source, int fieldNumber, char delimiter) {
int length = 0;
int start = 0;
int fieldNum = 1;
for(unsigned int i = 0; i < source.length(); i++, length++) {
if(source.at(i) == delimiter || (i == (source.length() - 1)) ) { //Find delimiter
if(i == (source.length() - 1) && source.at(i) != delimiter) {
length++;
}
if(fieldNum == fieldNumber) { //Found field
return source.substr(start, length);
}
fieldNum++;
start = i + 1;
length = -1;
}
}
return "";
}
/**
* Search for the field at the specified field number and returns its data.
*
* @param source The source string to take the field data from
* @param fieldNumber The number (from 1-n) of the field you wish to take data from
* @param delimiter The string (1-n characters) which delimits the fields in the source
* @return The data found in the field
*/
string String::TakeField(const string &source, int fieldNumber, string delimiter) {
if(delimiter.length() == 1) //if the delimiter is a char use other TakeField - more efficient
return TakeField(source, fieldNumber, delimiter[0]);
int length = 0;
int start = 0;
int fieldNum = 1;
unsigned int i = 0;
string src_partial = "";
while (i < source.length()) {
src_partial = source.substr(i, delimiter.length());
if(strcmp(src_partial.c_str(), delimiter.c_str()) == 0) { //Find delimiter
if(fieldNum == fieldNumber) { //Found field
if(length == 0)
return "";
else
return source.substr(start, length);
}
fieldNum++;
start = i + delimiter.length();
length = 0;
i = i + delimiter.length();
} else {
i++;
length++;
}
}
if(start != 0 && fieldNumber == fieldNum)
return source.substr(start);
else
return ""; //Couldn't find field
}
/**
* A string substr function which is compatible with utf8 character encoding.
*
* @param source The source string to take the sub-string from
* @param start The start position (0-n) to take the sub-string from
* @param length The number of character to take from the start position
* @return Sub-string or empty string if the range is outside the size of the string
*/
string String::FixField(const string &source, int start, int length) {
string result = "";
if (utf8::unchecked::distance(source.begin(), source.end()) < start) {
return result;
}
int pos = 0;
int len = 0;
for (string::const_iterator it = source.begin(); it != source.end(); pos++) {
if (pos >= start) {
string r;
utf8::unchecked::append(utf8::unchecked::next(it), back_inserter(r));
result.append(r);
len++;
if (len == length) {
break;
}
} else {
utf8::unchecked::next(it);
}
}
return result;
}
/**
* Trims all white space from the start and end of a string.
*
* @param source The input string to be trimmed.
* @return Output string containing the trimmed string.
*/
string String::Trim (const string &source) {
if (source.length() == 0) {
return "";
}
string res = "";
int start_idx, end_idx;
start_idx = 0;
end_idx = 0;
unsigned int i;
// Search for starting idx
for (i = 0; i < source.length(); i++) {
if(source[i] != ' ' && source[i] != '\t' && source[i] != '\r' && source[i] != '\n') {
start_idx = i;
break;
}
}
// Search for ending idx
for(i = source.length()-1; i > 0; i--) {
if(source[i] != ' ' && source[i] != '\t' && source[i] != '\r' && source[i] != '\n') {
end_idx = i;
break;
}
}
if (start_idx <= end_idx && source[start_idx] != ' ') {
res = source.substr(start_idx, (end_idx-start_idx+1));
}
return res;
}
/**
* Uses the iconv library to perform conversion between text encodings.
*
* Example usage:
* string input = "text to convert, possibly with encoding specific characters";
* string newLine = "";
* string errMsg = "";
*
* if (false == convertTextEncoding("ISO-8859-1","UTF-8",line,newLine,errMsg)) {
* cout << "ERROR: " << errMsg << endl;
* } else {
* cout << newLine << endl;
* }
*
* @param fromEncoding The name of the character encoding you want to convert from
* @param toEncoding The name of the character encoding you want to convert to
* @param inputStr The string to convert
* @param outputStr The string which will be populated with the converted output
* @param errMsg The variable which will be populated with the error message data if the conversion fails
* @return True if the convresion was successful, otherwise false
*/
bool String::ConvertTextEncoding(string fromEncoding, string toEncoding, const string &inputStr, string &outputStr, string &errMsg) {
outputStr = "";
//setup the conversion descriptor
errno = 0;
iconv_t icDescriptor = iconv_open(toEncoding.c_str(),fromEncoding.c_str());
if ((iconv_t)(-1) < icDescriptor) {
errMsg = "iconv_open failed with ";
if (errno == EMFILE)
errMsg.append("EMFILE: max file descriptors open in calling process");
else if (errno == ENFILE)
errMsg.append("ENFILE: too many files are currently open in the system");
else if (errno == ENOMEM)
errMsg.append("ENOMEM: insufficent memory available");
else if (errno == EINVAL)
errMsg.append("EINVAL: encoding specified for conversion is not supported");
else
errMsg.append("UNKNOWN ERROR: most likely invalid text encoding specified");
return false;
}
char in[TEXTENC_BUFFER];
char out[TEXTENC_BUFFER*2]; //allows all input characters to be converted to 2-byte characters
memset(in,'\0',TEXTENC_BUFFER);
memset(out,'\0',TEXTENC_BUFFER*2);
strcpy(in, inputStr.c_str());
char* inptr = in;
char* outptr = out;
size_t inSize = strlen(inptr);
size_t outSize = sizeof(out);
errno = 0;
if ((size_t)(-1) == iconv(icDescriptor,&inptr,&inSize,&outptr,&outSize)) {
errMsg = "iconv failed with ";
if (errno == E2BIG)
errMsg.append("E2BIG: insufficent space in output buffer");
else if (errno == EILSEQ)
errMsg.append("EILSEQ: input byte does not belong to specified encoding");
else if (errno == EINVAL)
errMsg.append("EINVAL: incomplete character at end of input buffer");
else
errMsg.append("UNKNOWN ERROR: most likely invalid text encoding specified");
return false;
}
outputStr.append(out);
iconv_close(icDescriptor);
errMsg = "";
return true;
}
/**
* Split a string depending on the delimiter
* ref: http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
*
* @param s The source of string to be split
* @param delim The string delimiter
* @param elems A pre-defined string vector, split result is pushed to this vector
* @return void
**/
void String::Split(const string &s, char delim, vector<string> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim)) {
item = String::Trim(item);
if(item.size() > 0) {
elems.push_back(String::Trim(item));
}
}
}
/**
* Checks if a string begins with another string.
*
* @param source The input string to be checked.
* @param prefix The string to look for at the start of the source string.
* @return True if source starts with prefix, false otherwise.
*/
bool String::IsBeginWith(const string &source, string prefix) {
if (source.length() < prefix.length())
return false;
if (source.substr(0, prefix.length()) == prefix) {
return true;
} else {
return false;
}
}
/**
* Checks if a string ends with another string.
*
* @param source The input string to be checked.
* @param suffix The string to look for at the end of the source string.
* @return True if source ends with suffix, false otherwise.
*/
bool String::IsEndWith(const string &source, string suffix) {
if (source.length() < suffix.length())
return false;
if (source.substr((source.length() - suffix.length())) == suffix) {
return true;
} else {
return false;
}
}
/**
* Checks if a string contains only numeric characters.
* Allows for certin characters to be ignored by listing them in the second paramter.
*
* @param number String to check
* @param ignoreChars String containing one or more characters to ignore when performing check
*/
bool String::IsNumeric(const string &number, string ignoreChars) {
unsigned int numericCharCount = 0;
unsigned int len = number.length();
if(len == 0)
return false;
for (unsigned int i = 0; i < len; i++) {
if (number[i] < '0' || number[i] > '9') {
bool is_ignore = false;
for (unsigned int j = 0; j < ignoreChars.length() && !is_ignore; j++) {
if (ignoreChars[j] == number[i]) {
is_ignore = true;
}
}
if(!is_ignore) return false;
} else {
numericCharCount++;
}
}
if(numericCharCount == 0)
return false;
return true;
}
/**
* Removes all occurrences of the specified character from string.
*
* @param source The source string to remove the character from
* @param remove The character to remove from the source string
* @return The string after the remove has been performed
*/
string String::RemoveChar(const string &source, char remove) {
string res = "";
if (remove == 0) {
res = source;
return res;
}
int len = source.length();
for (int i=0; i<len; i++) {
if (source[i] != remove)
res.push_back(source[i]);
}
return res;
}
/**
* Removes all occurrences of the specified characters from string.
*
* @param source The source string to remove the character from
* @param remove The characters to remove from the source string
* @return The string after the remove has been performed
*/
string String::RemoveChars(const string &source, const string &remove) {
string res = "";
if (remove.length() == 0) {
res = source;
return res;
}
int slen = source.length();
for (int i = 0; i < slen; i++) {
bool isMatch = false;
int rlen = remove.length();
for (int j = 0; j < rlen; j++) {
if (source[i] == remove[j]) {
isMatch = true;
break;
}
}
if (!isMatch) {
res.push_back(source[i]);
}
}
return res;
}
view raw String.cpp hosted with ❤ by GitHub

How to convert hard disk format from NTFS to Fat32

Another weekend, another task to do to make life easier. This time I will work on upgrading my 2008 phat Playstation3's 40GB hard disk to a massive 320GB. Since I play games a lot and games nowadays require larger space of game data for faster processing, I find myself having to remove previous games' install data just to accommodate enough space for the new ones. This is definitely a daunting task, in malay, we simply call it "potong stim".
‘Potong Stim’ literally means cutting steam. It is a term used for someone who kills the enthusiasm of others.
TL;DR Ruin the good mood!!

Tools required:
  • Screwdriver with cross heads aka Phillips-head
  • 2 portable USB powered hard disk: One for backing up the PS3 (> 80GB) and another one for PS3 firmware (~ 200MB)
  • 1 new 2.5 inch portable hard disk: Western Digital Scorpio Black 320GB 7200rpm 16MB SATA2 (Model No.WD3200BEKT) $71.50
There're plenty of online step-by-step guide on how to backup data, switch hard disk and restore data from backup, you can refer to "Related" section below. What I would like to write about is the 2 problems that I encountered which are not covered by those articles.


Q: How to format the new hard disk from NTFS (default) to FAT32?

Believe me, I've spent hours and gone through all the hard part for you. Below is the pseudocode:

IF (you're using Windows 95/NT/98/Me/2000/XP) {
    CompuApps SwissKnife V3 is the best option. 
    Download it here. 4.35MB 
} ELSE IF (you're using Windows 2000/XP/Vista/7) {
    SwissKnife won't work at all in Win7. Try Tokiwa's FAT32Formatter.  
    Download it here. 184KB
} ELSE IF (your thumbdrive capacity < 32GB && Use Diskpart feature in command prompt) {
    [01] Plug in your USB Flash Drive 
    [02] Open a command prompt as administrator (Right click on Start > All Programs > Accessories > Command Prompt and select run as administrator) 
    [03] diskpart 
    [04] list disk 
    [05] select disk 2 //Assume 2 is your USB drive 
    [06] clean 
    [07] create partition primary 
    [08] select partition 1 
    [09] active 
    [10] format fs=fat32 //Append "quick" option for quick format 
    [11] Assign 
    [12] Exit 
    reference
} ELSE {
    Give it one last try, 
    [01] Right click on drive in "My Computer" 
    [02] Choose "Format" 
    [03] Choose "FAT32" //NOTE: exFAT is different from FAT32 
    [04] Check "Quick Format" option 
    [05] Click "Start" button

    God Bless You 
}

I use Tokiwa's FAT32Formatter, this incredibly lightweight software did its job in less than 10 seconds for converting an empty 150GB drive from NTFS to FAT32. Impressed? Hell YES!


Q: Why PS3 can't find the .PUB (firmware) in the thumb drive?

I downloaded PS3 firmware (4.25 as of today) from AU Playstation site and transferred the xxx.PUB to another portable thumbdrive. But pressing 'Start' and 'Select' buttons simultaneously (as said in the on-screen instruction for restoring data) cannot detect the firmware update file in the drive.
SOLUTION: You need to create this directory path in the thumbdrive: PS3/UPDATE/xxx.PUB

Other

  • Time spent to backup a 38GB data is approximately 2 hours, same applies to restore the data to the new drive.
  • DLCs are included in backup as well. But it needs to be "activated" again somehow. E.g. Borderlands cannot detect any of the installed DLCs until I downloaded and reinstalled one of the DLCs from PSN.
  • Windows do have the limit of formatting drive (>32GB) to FAT32 no matter what version of the Windows OS. 

Related:

Job Interviews

Not going to lie, I've been going to interviews lately to see how things have changed along the years and of course, look for better opportunities.  It's either phone interviews with a job agents or face-to-face interviews in potential employers' offices.

2004
- Preferred languages: VB.Net

2008
- Preferred language: Cobol

2012
- Preferred language: HTML5, Ruby on Rails, Mobile (J2EE, Android)
- Requirement: Agile

Below is my checklist before going for interviews:
☑ Resume is modified to focus more on tasks and achievements
☑ Iron your shirt and trousers, wear a business tie and clean shoes, have a clean face
☑ Do research on the company or interviewer by checking out the official website or social networking sites, e.g. Linkedln, Twitter, blog
☑ Do revision on behavioural and technical questions that will be asked
☑ Be cool or at least look comfortable
☑ Have a good breakfast

Is there anything else I've missed out? If not, how the hell do I fail so much, I've been wondering. This article does point out something crucial.
Most interviewers fall prey to unconscious biases and focus too heavily on experience rather than competence.

As a mid-level programmer who works on various programming languages (Java, Ruby on Rails, PHP) along these years, I strongly feel that I can contribute more as my skills are not fully utilised yet. But the flawed filtering process by most employers categorized me as low end programmer. On the contrary, all my ex-employers are happy to have me around in their department during my employment. My proactiveness and strong adaptability at work cannot be seen in the 20 minutes or so interview. 

Ridiculously, I just can't score high in technical questions which aim to stress you up because most solutions can be found online. Of course one can code everything from scratch if you're a super coder, but what's the benefit of having a might-be buggy solution compare to modifying an existing code snippet from StackOverflow.

One thing that annoyed me the most would be asking "Do you have any experience in Agile development?". Let's have a read on its definition on Wiki,
Agile software development is a group of software development methods based on iterative and incremental development, where requirements and solutions evolve through collaboration between self-organizing, cross-functional teams. It promotes adaptive planning, evolutionary development and delivery, a time-boxed iterative approach, and encourages rapid and flexible response to change. It is a conceptual framework that promotes foreseen interactions throughout the development cycle.

May I know how hard it is to adapt to a new methodology in software development? Is it harder than paying the ever increasing utility bills or getting a payrise from a tight-ass stingy company?

In conclusion, I know that I'm definitely
NOT suitable if a company is looking for:
- a gun programmer who eats, lives, breaths and shits around programming
- a scholar who memorises all the programming jargon

TOTALLY suitable if a company is looking for:
- a proactive, organized programmer/analyst who requires minimum supervision
- get things done in a clean and efficient way, will work ass off to meet deadline (normally don't happen though)
- produce documented codes and communicates well in a team
- propose multiple solutions and welcome discussions to pick the best

Just curious, is there anyone out there who has similar situation as me? Maybe I should just switch my profession, get the hell away from programming. Heck, I don't know, mind blown!


Related:

Home made weed killer

Spring is here and it's time to get rid of the pesky weed.  In my opnion, those weed killer sprays that are sold in big retail stores are simply overpriced.  Well, basically aussies do pay more for everything. Sad? I know!

I've been looking for cheap solutions online and this would be the easiest to make.
1L vinegar
1 cup salt (seems like a lot, so you can maybe go 3/4)
Few drops dishwashing liquid (this makes the mix stick to whatever you spray)

According to the post, it takes 1 - 7 days to kill weed and grass once you've sprayed on them.  It's best NOT to spray on rainy or windy condition.

If you find measuring is cumbersome, this is what I do:
3 bottles of rice vinegar that you can buy from asian grocery store ($1.30 x 3 = $3.90)
1 small cup of Selley's sugar soup liquid concentrate ($3.83 x 10% = $0.40)
1 small cup of salt ($1.00)
All you need to do is pour everything into a bucket, mix it up and spray away~~  I've tried this 6 months ago and it works pretty well, but I've no idea how long more it can keep the weed away.

Source: Homemade weed killer

Transfer region locked Borderlands save file on PS3

PIC1.PNG from save file

While most people are playing Borderlands 2 which released last week, I'm still stucked with the first game.  Ming and I were having a gaming marathon last weekend, finally killed the last boss at Level 34 soldier class, sweeeeet!! Next thing to do is to finish the DLCs, another 10 hours to spend?!

Case:

- Own an Asia version of Borderlands GOTY game
- Wish to play in Australia server
- Create a new PSN ID using Australia address and sign in
- Copy Borderlands save file from Asia's PSN profile to Australia's PSN profile
- Load save file in Australia's PSN profile, able to see the save file (when you choose "Existing Character") but fail to load

Solution:

Step Description
01 Remove Borderlands game save file (NOT the profile data) under Australia's PSN profile.
02 Copy the original save file under Asia's PSN profile and transfer it to computer. You will notice this folder structure: "PS3 > SAVEDATA > BLExxx-SAVE-SAVE0001", you will find 5 files, which consists of:
  • SAVE00001.SAV
  • ICON0.PNG
  • PIC1.PNG
  • PARAM.PFD
  • PARAM.SFO
Remove save file from thumbdrive and pop it back to PS3.
03 Run Borderlands game on Australia's PSN profile, start a new game and level up once. Then, press "Start", choose "Exit". This will create a new save game file, copy it to the thumbdrive.
04 Here's the important part!! Copy ONLY the "SAVE00001.SAV" in step 02 (Asia profile) and overwrite the one in thumbdrive (Australia profile).
05 Remove the new save file under Australia PSN profile. Then, copy the modified save file from thumbdrive to PS3.
06 Run the game again, choose "Existing character" to load the modified save file. You may notice the game character info is not updated (Level 2 in this case) but it's totally fine. Once it's loaded, your game character is carried forward from previous account. Hit "Exit" to save necessary bits to this profile. Enjoy!

As the filenames indicate, PARAM.* files are storing values for validation and summary purpose while SAVExxx.SAV contains the main saved game data.

Myth: Blowing into game cartridges can fix glitching

I was once a proud owner of the NES Family Computer which was bought by dad during primary school days.  Game cartridges are definitely not cheap, RM60.00 (equivalent to RM120 nowadays), but games in those days had high replayability and challenging.

Source 
On weekends, brother and I would ask parents' permission to play games ONLY after we finished schoolwork.  If everything went well, we would then take out the console from a birthday cake box, set it all up and had some quality co-op action time.  Those were the days, we spent hours and hours playing Mario, Contra, Ice Climbers, Soccer, Double Dragon etc.  I still have the box and console back in hometown, will definitely take a photo next time.

Not the exact Fajar Supermarket, but close
After a few months of constant slotting the cartridge to the console pins, you might encounter cartridge fail reading or graphic glitch.  According to the sales assistant at a local game shop in Fajar Supermarket, "Oh, it's because dust collected on the cartridge's pins" he said confidently.  He then blew and shaked it a few times, put it back to the console slot *voila* it worked like a charm.  And so it all began, whenever the console can't read the cartridge properly, we would follow these steps:

Step 01: Take out the cartridge
Step 02: Inhale air into your mouth
Step 03: Blow it straight to the cartridge's pins
Step 04: Give it a few weak shakes to make sure dirt drops out
Step 05: Slot it back to console
Step 06: Still not working?? Back to Step 01.

It's working so well that I didn't give it a second thought...until I read this article.

TL;DR

Nintendo designed its NES connector using nickel pins bent into a position so that they’d give slightly when a cartridge was inserted, then spring back after it was removed. These pins became less springy after repeated use, which make it hard for them to firmly grasp the game cartridge’s connectors.

Myth busted and mind blown...

Ewww....  Source


Related:

4 things that you should never put in the database

Read this article by Frank Wiles,

TL;DR version

  • Images, files and binary data.  Solution: Use file system.
  • Ephemeral data: Usage statistics, metrics, GPS location, session data or anything that is only useful for a short period of time.  Solution: Use redis, statsdgraphite, Riak
  • Logs. Solution: Use Splunk, Loggly
  • Plain text passwords. Solution: Encryption

Last but not least,
But wait, you're a unique snowflake and your problem is SO different that it's ok for you to do one of these three. No you aren't and no it really isn't. Trust me. - Frank Wiles

Serviio - DLNA media server

#UPDATE 20130114
Recommend to update to version 1.1 for better stability and major bug fixes.

This week, I'm going to fix just one thing. A web service which I can use to share my videos, images either on Playstation3, Xbox360 or Samsung TV. I noticed the Samsung 3D plasma TV has DLNA feature equipped but I never bother to find out what it is.

After a quick google search, I instantly knew that I've missed out a lot on such technology. It's time to bring my problem solving skill to good use. After spending some time digging, I came across a free media server which ticks all my requirements:
  • Stream media files directly from PC to TV or game consoles, eliminating the use of media player
  • Easy to setup server
  • Simple user interface, easy to browse files
  • Lightweight software

What is Serviio?


According to the official website, it's developed by Petr Nejedly.
Serviio is a free media server. It allows you to stream your media files (music, video or images) to renderer devices (e.g. a TV set, Bluray player, games console or mobile phone) on your connected home network.

Serviio works with many devices from your connected home (TV, Playstation 3, XBox 360, smart phones, tablets, etc.). It supports profiles for particular devices so that it can be tuned to maximise the device's potential and/or minimize lack of media format playback support (via transcoding).

Serviio is based on Java technology and therefore runs on most platforms, including Windows, Mac and Linux (incl. embedded systems, e.g. NAS).

Steps to Setup

Operating System: Windows 7
Modem/Router: Netcomm NB6Plus4W
Display device: Samsung 3D Plasma TV (PN50C8000)

[01] Go to this page to download the latest version  (v1.01)
[02] Click on .exe file and install it to Windows
[03] Open serviio console, click on "Library" tab.
[04] Under "Shared Folders", choose the folders that you want to share within the network.  On the right side, click on the type of files you want to share.
[05] Turn on the TV, click on 'Source', you should see "Serviio DLNA device".
[06] Choose "Videos"/"Pictures" depending on what you've shared in step 04.

Troubleshooting

[01] If your device can't see Serviio
This could be caused by you having multiple IP addresses on the machine and Serviio binding to the wrong one. Insert the IP address of the machine running Serviio into 'Bound IP address' field in Network Settings section in the console or pass the system variable serviio.boundAddr including the IP address when starting the server.

- Make sure that TCP port 8895 and UDP 1900 are open in your firewall.
- If you are on a Linux based OS, make sure you set up multicast routes properly.
- If on Windows, you can push the Serviio service down in starting order.

[02] Networking error after reboot
This could be another serviio starts before the network adaptor has start so serviio sees the wrong adaptor.
- In window services manager, select the serviioservices.exe
- Go into its properties and select "Delayed Start" and that should fix your issue.

[03] How to setup Live stream folders
http://wiki.serviio.org/doku.php?id=live_stream_folders

[04] Linux workaround for supporting chinese characters
http://forum.serviio.org/viewtopic.php?f=14&t=692&p=5572&hilit=hebrew#p5832

[05] Other user interface is available for web and mobile
http://www.serviio.org/component/content/article?id=21#q7

[06] How to switch to other audio track
http://forum.serviio.org/viewtopic.php?f=7&t=8481#p62564

Related:

How to retrieve "Key" and "Value" pairs from GET method?

Title speaks it all.  This method can deal with empty value as well.



Related:

What on earth is Parallax effect p(*o* )?!

On Wiki, Parallax is a displacement or difference in the apparent position of an object viewed along two different lines of sight, and is measured by the angle or semi-angle of inclination between those two lines. You don't quite get it, do you? Yea, neither do I. Let's have a look at some examples instead.

Name Description File Size
Parallax-JS Developed by razorfish
A simple vertical page scroller, <section></section> tag is parsed for parallax effect. Side navigation bullet list is automatically generated if side-nav.js is included. One thing that I'm picky of is scrolling between pages doesn't really snap the page to the browser viewable pane. Sample doesn't fully demonstrate the controls offered by the javascript.
19.1 KB
Demo
Superscrollorama Developed by johnpolacek
The webpage has good demonstration of what the script can do, jam packed with scroll animation. It's most suitable for working with font effects.
171.44 KB
Demo
Plax Developed by cameronmcefee
I first saw the parallax effect on github 404 page, and yeap, it's done by him. Lightweight, and does the job well. It's very easy to have parallax effect on elements based on mouse position. Best for moving objects on mouse's movements.
9.23 KB
Demo

I decided to give Plax a quick run on fonts.  Below is the source, remember to put plax.js on the same file path as the html.


<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Moving Fonts</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="plax.js"></script>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
body {
position: relative;
}
div#shell {
display: block;
position: relative;
margin: 100px auto;
z-index: 1;
font-weight: bold;
font-size: 35px;
overflow: auto;
width: 500px;
height: 500px;
}
div.char {
float:left;
text-shadow: 3px 3px 3px #aaa;
}
div#char-j {
position: absolute;
top: 60px;
left: 80px;
}
div#char-u {
position: absolute;
top:55px;
left: 100px;
}
div#char-s {
position: absolute;
top: 60px;
left: 120px;
}
div#char-t {
position: absolute;
top: 56px;
left: 140px;
}
div#char-i {
position: absolute;
top: 65px;
left: 160px;
}
div#char-n {
position: absolute;
top: 57px;
left: 174px;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$.plax.enable();
$('#char-j').plaxify({xRange:20, yRange:20});
$('#char-u').plaxify({xRange:25, yRange:25, invert:true});
$('#char-s').plaxify({xRange:10, yRange:15});
$('#char-t').plaxify({xRange:18, yRange:18, invert:true});
$('#char-i').plaxify({xRange:20, yRange:20});
$('#char-n').plaxify({xRange:18, yRange:20, invert:true});
});
</script>
</head>
Related:

"If you leave this page, data you have entered may not be saved"

After receiving a request ticket today for the intranet system which my team has been developing, I'm set to look for a solution.

Stay or Leave

Criteria

Implement a "navigate away from browser" protection to prevent users from accidentally closing tabs or windows in Edit mode.  If user chose to stay on page, no changes should be made.

Solution

var isDataChanged = true;
window.onbeforeunload = (function() {
if(isDataChanged) {
//For IE only, Firefox and Chrome browsers have their own message to display
return 'If you leave now, data you have entered may not be saved.';
}
});
view raw general.js hosted with ❤ by GitHub
In the above example, a global variable, 'isDataChanged', is used to check whether any data is changed when the page is loaded.

Just remember to reset the variable whenever possible, you don't want to piss off users with the confirmation dialog box.  If you're not fancy of global variables, you may want to consider checking whether 
- The main edit pop-up dialog is not hidden
- Form element which stores the current mode is not equals to 'view'


var processDialog = new YAHOO.widget.Dialog('procDialog', {
width: '400px',
height: '350px',
underlay: 'shadow',
visible: false,
modal: true,
});
window.onbeforeunload = (function() {
if ( processDialog.cfg.getProperty('visible') &&
YAHOO.util.Dom.inDocument('actionMode') &&
YAHOO.util.Dom.get('processForm').elements['actionMode'].value != 'view' )
{
return 'If you leave now, data you have entered may not be saved.';
}
});
view raw form-control.js hosted with ❤ by GitHub


This method is tested on the following browsers:
  • Firefox 15.0
  • Chrome 21.0
  • Internet Explorer 9.0

Lots of interest but lack of direction in life

Have you ever wondered that what's the point of working if the main purpose of earning money is to pay off the mountainous bills which are piling at the corner of your desk?  And you notice that things that you enjoy doing just doesn't generate revenue to reward or motivate yourself to move further.  

Occassionally, you have the gut feelings that you can definitely contribute more to work or society so that you've a better quality of life in return.  But in fact, things are just not going the way you want it to be, FML moments.

Life Span
Here's one quote from Quora

Resident Evil 6

Resident Evil/Biohazard series has come a long way since it first introduced in 1996 as Playstation game.  It makes me aware of the Japanese company who developed these survival horror/action titles - Capcom.  When RE1 was released on Playstation, I have trouble playing it after I watched the infamous zombie head-turning cutscene in the mansion (yea, that's 15 minutes into the game).  In the end, my brother got hold of the controller, gunning down zombies while I helped him to solve puzzles.

Are you alrig...ARGH!!

Fast forward to present, Shinji Mikami, the creator of the series, left Capcom in 2007 after the critically acclaimed 4th instalment.  5th and 6th games have different directors to inject new elements to the horror franchise.  Despite the upcoming logo looks like a giraffe getting happy sack (judge for yourself from the image below) and Capcom's evil on-disc DLC strategy, it won't hinder long-time fans from purchasing the game on day one.

What's been seen cannot be unseen

Thanks to the earlier purchase of Dragon's Dogma,  I'm able to redeem a code for Resident Evil 6 demo.  I finished the 3 short single-player campaigns within an hour.  Below is my review solely based on the demo, final copy might have addressed some of the issues.

First Impression

Leon S. Kennedy & Helena Harper
Classic Resident Evil vibe, dark indoor environment with strong light source from the windows

Jake Muller & Sherry Birkin
Escape from boss and fight him afterwards in a confined place

Chris Redfield & Piers Nivans
Located in an asian city, just shoot everything that moves!

Improvement

+ Characters can finally strafe and aim simultaneously, no more stand-still-to-shoot
+ Using an modified version of the MT framework engine, lighting and graphic quality has improved
+ Thanks to Uncharted series, character's animation seems to be more human-like.  This can be noticed in Leon's campaign where he would hold on to the side of the door when he walked out a room
+ Shortcut control for accessing inventory
+ Interesting design of monsters, bigger action sequence

Issues

- Bad lip-synching
- Weird camera angles interfering gameplay, make me nauseous at times
- Big chunk of space is allocated for UI, displaying user's health, quick item slots etc
- Linear corridors shootout, the marked path in Leon's campaign spoilts the exploration even more

Day 1 Purchase?

If you've the patience, wait a year for the inevitable Gold or Platinum edition.  For me, it's just too hard resisting the urge to play the campaigns after the game releases on 4th October.  I will definitely skip the upcoming movie, Resident Evil: Retribution (released on 14th September), I just couldn't bring myself to watch another sucky RE's movie adaptation by Paul W.S. Anderson.  However, I love the CGI movies, Resident Evil: Degeneration (2008) and Resident Evil: Damnation (2012), it's like watching game HD cutscenes all the way.

Trivia:

Q: Who voiced "Resident Evil" at the game's title screen?
A: Joe Whyte (Chris Redfield) source

Are you the guy who says, "RESIDENT EVIL!" at the title screen in that demonic voice?
[laughter] Yeah. Yeah, that's me. At the end of all the sessions, they asked me to do some little extra lines. There were just some little extras - some little pick-ups that weren't actually Chris Redfield; they were just sort of in the game. I also did some of the vo for Richard in the game. The scene where Richard gives the radio to Jill and Chris is my voice. Pretty funny to hear my voice coming from two characters.

Q: Is there a variety of ink ribbons in the series?
A: Yes, I'm surprised to know that.  source

  • In Resident Evil, if played on original, the ink is white, if played on Training, the ink is Green. In REmake this is changed slightly. On all difficulties the ink is white unless the player is playing on "Once Again..." Mode, in which case it is green on Easy mode, white on Normal mode and red on Hard mode. On Real Survival Mode, the ink is blue, and on the special "Invisible Enemy" mode, it is Orange.
  • In Resident Evil 2 is played on Easy mode the ink is white for both characters, while in Normal the ink is red for Claire and blue for Leon. In Extreme Battle, the ink is green for everyone.
  • In Resident Evil 3: Nemesis is played on Easy mode, you can get an unlimited amount, and the ink is blue while in Hard mode the ink is white.
  • In Resident Evil Code: Veronica, there is always an ink ribbon right of the first typewriter and three ink ribbons per saving point (typewriter).
  • Resident Evil Outbreak and Resident Evil Outbreak File 2 as well as Resident Evil 4 did not include any ink ribbons but still used a typewriter as the save point.
  • Resident Evil 5 ditched the typewriter altogether, and replaced it with a more "modernized" automatic checkpoint save system. When asked in an interview for Official Xbox Magazine, the game's producer commented that "They simply couldn't find a way to fit them into the game.".


UPDATE on 21 October 2012

Progress:
✔ Finish 5 chapters of Leon Kennedy & Helena Harper story
✔ Finish 5 chapters of Chris Redfield & Piers Nivans story
✔ Finish 5 chapters of Sherry Birkin & Jack Muller story
✔ Chapter 1 of  Ada Wong story
✘ Agent Mode
✘ Mercenary Mode

Impressions:
☻ The most ambitious game settings in RE universe
☻ The updated MT Framework provides excellent lighting to the environment and slight update to graphics, I don't have any too-dark-to-see issue as seen in message boards
☻ Characters' animations are smooth
☻ Save point system is good, fast revive after death cut scene
☻ Partner's AI is improved compared to RE5 but they can be annoying sometimes.  E.g. outside of the cathedral which was overrun with zombies, I've trouble getting Helena to open the door
☻ Story is cleverly bound together among the 3 pairs of characters

Gameplay:
☻ Points obtained can be spend on skills which is similar to the perk system in Cod: Modern Warfare series
☻ Melee combat is enhanced and it's tied to stamina
☻ Player can shoot while strafing, awesome
☻ Innovative, apart from the familar Mercenary mode, they added Agent Hunt mode which lets other players to join the game as monsters and take down the main human characters, can't wait to try this mode
☹ Melee and shooting controls are standard. But mixing herbs and dodging require a combination of buttons
☹ In some sequences which require the player's attention, camera angle is fixed, making the player hard to navigate, E.g. running /sliding through obstacles while escaping from the claws of the gigantic B.O.W in Chris's story is pain in the arse
☹ Expect to have good coordination of eyes + hands and fast fingers as there're a lot of QTE (Quick Time Events)


Things to improve:
  • Die hard big boss: I know they're meant not to be killed easily but it's ridiculously for a player to kill it again and again and again in a single story.  What worse is they died cheaply in the end.
  • Player's UI occupies a large chunk of screen space: I don't mind characters have unique on-screen UI (User Interface) but it's taking too much space.  What I would do is removing the life bar indication, different level of health can be shown on character's animation.  E.g. Character will be limping on low health
  • Optimise controls: Holding L analog stick (L3 button) for more than 3 seconds will initiate run animation instead of pressing [L3] + [x] button. Clicking on L3 will run in the direction that the player is facing.  [x] button + [L3] can then be used as dodging instead of pressing [L1] + [L3] + [x]
  • Remove the idea of destroying crates to find ammunition:  I understand crate is served as placeholder to make the environment less empty and it's easy for players to identify where to get ammo supply.  But in a linear gameplay, it should somehow encourage the player to explore these fantastic game environments by checking out drawers, cars, boxes or even plants.

No doubt that Resident Evil franchise, particularly in game industry, is getting bigger by every release.  I wouldn't say it's still heading in the action horror direction, at least the people in Capcom are taking the risk to bring in various changes.  Looking at their first foray into open world game *Dragon Dogma*, I would very much hope that Resident Evil 7 will be a major overhaul to the PS2's Outbreak series which could be played in single or multiplayer mode in a semi-open world.  Fingers crossed.



Related:
- Resident Evil theme park in Japan's Universal Studios
- Resident Evil wikia
- Resident Evil Wikipedia
- Angry Joe plays Resident Evil 6 demo

Now everyone is a cryptographer of CAPTCHAs


Ahhhh...CAPTCHA - a tool which is designed to fence off spam and trolls (bad guys) is unfortunately, punishing potential customers, users (good guys) as well.  In fact, it's so common to come across one in websites nowadays, you would think it's a norm even though you made several wrong guesses, trying to figure out what're the characters.


captcha-impossible
Superscript, subscript, newline?
and the best goes to,
captcha-knows-best
As you wish, my lord

Below is some creative CAPTCHA methods I've found:

Name Tech Notes
MotionCAPTCHA HTML5, jQuery Simply my favourite, match drawing of a pattern
Qaptcha jQuery Similar to iProduct's screen unlock slider. Please note that the demo doesn't work properly, would recommend you to download the files and try it out.
Ajax Fancy CAPTCHA jQuery This is a fancy looking one but it's not hard for the bot to figure out which element is draggable.



More readings:

CSS3 Gradient Background


The days of creating a (1pixel * height/width) of image for a gradient background is over. Modern browsers are supporting CSS3 to an extent that you can create nice-looking backgrounds for button or wallpaper entirely from stylesheet.

Webkit
Syntax -webkit-gradient(, [, ]?, [, ]? [, ]*)
Example background: -webkit-gradient(linear, 0 0, 0 100%, from(red), to(blue));
Params - Gradient Type: linear / radial
- X and Y axis coordinates of where to begin: (0 0 – or left-top corner)
- X and Y axis coordinates of where to conclude: (0 100% – or left-bottom corner)
- Color to begin with: (from(red)) Color to end with: (to(blue))
Mozilla
Syntax -moz-linear-gradient( [ || ,]? , [, ]* )
Example background: -moz-linear-gradient(top, red, blue);
Params - Type of gradient "linear" is specified within the vendor extension
- Where to begin? (top – we could also pass in degrees, as in -45deg)
- Color to start with? (red)
- Color to end with? (blue)


.button {
display: inline-block;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: 14px/100% Arial, Helvetica, sans-serif;
padding: .5em 2em .55em; /* Change values for different sizes */
text-shadow: 0 1px 1px rgba(0,0,0,.3);
-webkit-border-radius: .5em;
-moz-border-radius: .5em;
border-radius: .5em;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
box-shadow: 0 1px 2px rgba(0,0,0,.2);
}
.button:hover {
text-decoration: none;
}
/* Button being pushed down effect */
.button:active {
position: relative;
top: 1px;
}
.orange {
color: #fef4e9;
border: solid 1px #da7c0c;
background: #f78d1d; /* fallback for non CSS3 browsers */
background: -webkit-gradient(linear, left top, left bottom, from(#faa51a), to(#f47a20));
background: -moz-linear-gradient(top, #faa51a, #f47a20);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#faa51a', endColorstr='#f47a20');
}
.orange:hover {
background: #f47c20;
background: -webkit-gradient(linear, left top, left bottom, from(#f88e11), to(#f06015));
background: -moz-linear-gradient(top, #f88e11, #f06015);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f88e11', endColorstr='#f06015');
}
.orange:active {
color: #fcd3a5;
background: -webkit-gradient(linear, left top, left bottom, from(#f47a20), to(#faa51a));
background: -moz-linear-gradient(top, #f47a20, #faa51a);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f47a20', endColorstr='#faa51a');
}
.small {
font-size: 11px;
padding: .2em 1em .275em;
}
.medium {
font-size: 12px;
padding: .4em 1.5em .42em;
}

As for HTML,
<button class="orange" id="test" name="test">Press me</button>

Click here for demo 


For more information: 


HTML code is escaped using htmlescape.net

Hide/Show DIV when input element is focused

Yesterday, I was browsing Play-Asia for a game (Resident Evil Chronicles HD by the way), the website is packed with so many text and images that they've found out a way to display the search box's extra options elegantly, as shown below:

Before

After: User clicks on search textbox

Tasks:
  • Textfield with placeholder
  • When user clicks on the textfield, an outer DIV will display with more search options and a submit button/image
  • If user clicks anywhere outside of the search dialog box or the 'X' button, the outer DIV will be hidden.
  • Avoid user from spam-clicking on the textfield that may cause unexpected behaviour of the toggle show/hide feature.
  • Able to put the textfield anywhere within a webpage and have the same effect
Eager to find out how they code such effect, I have successfully used jQuery to replicate it and improve on the element positioning.

HTML part
<form id="sForm" name="sForm" method="POST">
<!-- DIV containing textfield, always display -->
<div id="inside" name="inside" class="inside">
<input type="text" id="searchText" name="searchText" maxlength="25" placeholder="search for games" autocomplete="off" tabindex="1" style="z-index:500" />
</div>
<!-- DIV of wrapping block -->
<div id="outside" name="outside" class="outside hidden">
<div class="hd">
<div id="closeBtn" name="closeBtn" class="right btnClose">X</div>
Search
</div>
<div class="bd">
<div class="right btnSearch">
<input type="submit" value="" title="Search" alt="Search" name="submit_searchbox" id="submit_searchbox" tabindex="3" />
</div>
<br>
<div style="padding:30px 0 5px 5px;">
<label>Category</label>
<select id="category">
<option value="all">All</option>
<option value="ps3">PlayStation 3</option>
<option value="xbox360">Xbox 360</option>
<option value="wii">Wii</option>
</select>
</div>
</div>
<div class="ft"></div>
</div>
</form>


Javascript part
$(document).ready(function() {
$(document).click(function(e) {
// Checks if the element you clicked has #outside div as parent
if ($(e.target).closest('#outside').size() == 0) {
if ((e.target.id) == 'searchText') {
$('#outside').fadeIn(200);
} else {
$('#outside').fadeOut(200);
}
} else {
// If target element has #outside as parent, keep it visible at all times
$('#outside').fadeIn(200);
}
});
$('#closeBtn').click(function(e) {
// To halt the click queue
e.stopPropagation();
$('#outside').fadeOut(200);
});
});


Explanation:

  • The hidden outer DIV will have absolute positioning while its parent will have relative positioning so that their positions will be adjusted accordingly.  Click here for more information about css positioning.
  • event.stopPropagation() is used to stop the click queue.  If this is omitted, clicking on the "X" button will trigger the fadeOut() effect initially, then it will proceed to trigger the parent's fadeIn() effect (in 'else' statement).

Click here to download the files (ZIP).