<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hacked Existence</title>
	<atom:link href="http://blog.hackedexistence.com/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.hackedexistence.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Wed, 07 Dec 2011 12:04:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Book Review: Ghost in the Wires</title>
		<link>http://blog.hackedexistence.com/book-review-ghost-in-the-wires</link>
		<comments>http://blog.hackedexistence.com/book-review-ghost-in-the-wires#comments</comments>
		<pubDate>Wed, 07 Dec 2011 12:01:15 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Book Review]]></category>
		<category><![CDATA[Ghost in the Wires]]></category>
		<category><![CDATA[Kevin Mitnick]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=215</guid>
		<description><![CDATA[When I was in high school, I wouldn&#8217;t say I was an avid reader, but I definitely tackled some novels. When I got to college (back in 2003), reading books (that weren&#8217;t textbooks) kind of faded away, which is ironic, &#8230; <a href="http://blog.hackedexistence.com/book-review-ghost-in-the-wires">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When I was in high school, I wouldn&#8217;t say I was an avid reader, but I definitely tackled some novels.  When I got to college (back in 2003), reading books (that weren&#8217;t textbooks) kind of faded away, which is ironic, you would think college would have the opposite effect &#8230;</p>
<p>Recently, I gave the kindle a try, to see if I could really get back into reading books.  Even though I&#8217;m a huge supporter and overzealous user of technology, I was wary of the kindle at first.  I didn&#8217;t like the thought of not being able to flip pages, not being able to dog-ear pages and write notes in the book.  It really bothered me that when I finished dedicating all that time to a novel, I wouldn&#8217;t have a paper back trophy to add to the collection.  Then I actually gave it a try &#8230;</p>
<p><a href="http://blog.hackedexistence.com/wp-content/uploads/2011/12/ghost-wires.jpg"><img class="aligncenter size-full wp-image-224" title="ghost-in-the-wires" src="http://blog.hackedexistence.com/wp-content/uploads/2011/12/ghost-wires.jpg" alt="" width="324" height="500" /></a></p>
<p>Kevin Mitnick&#8217;s autobiography, &#8220;<a href="http://www.amazon.com/Ghost-Wires-Adventures-Worlds-Wanted/dp/0316037702/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1323259049&amp;sr=1-1" target="_blank">Ghost in the Wires: My Adventures as the World&#8217;s Most Wanted Hacker</a>&#8220;, instantly interested me as I had read &#8220;<a href="http://www.amazon.com/Takedown-Pursuit-Americas-Computer-Outlaw/dp/0786889136" target="_blank">Takedown: The Pursuit and Capture of Kevin Mitnick, America&#8217;s Most Wanted Computer Outlaw-By the Man Who Did It</a>&#8221; by Tsutomu Shimomura and John Markoff in highschool.</p>
<p>In this spare-no-details first hand account, Mitnick takes us through his rise to become the FBI&#8217;s most wanted target, detailing his steps in creating new identities to allude the law enforcement manhunt while (quite successfully) staging a counter snooping operation that kept him one step ahead of his pursuers for years.</p>
<p>Many of Mitnick&#8217;s exploits are based on an attack vector known as Social Engineering.  He outlines the three steps to successful social engineering as:<br />
1) Assume a position of authority<br />
2) Convince the victim that you are supposed to be doing what you are asking them to do<br />
3) Convince the victim that you are unable to do it yourself, and you need their help<br />
These three steps, if performed properly, almost always result in the victim doing something for you that you shouldn&#8217;t be able to do yourself.  Mitnick, by simply talking to people on the phone, was incredibly skilled in getting people to grant him access to restricted information and change systems that he didn&#8217;t have the permission to change himself.</p>
<p>Overall, this book assumes you have some background understanding of how  a Telco operates, and is not for the technically challenged, although  it rarely goes into great technical detail.</p>
<p>What I found most interesting was Mitnick&#8217;s thoughts on solitary confinement, a topic he became quite familiar with through first hand experience.  Spending 8 months in solitary confinement for non-violent crimes seems a little harsh, and Mitnick constantly describes the damaging psychological impact that it can have on a human being.</p>
<p>At one point, Mitnick describes being diagnosed as having an &#8220;addiction to hacking&#8221; in the same sense as an addiction to smoking or drinking.  This is easily justified given his lack of &#8220;for profit&#8221; exploits in lieu of a constantly exploiting Telcos on the quest for knowledge.</p>
<p>The truly shocking thing about this book is not Mitnick&#8217;s exploits, but the vulnerabilities in the Telco&#8217;s themselves, something I have been conscious of for years.  Most of his code based exploits were piggybacked on Social Engineering attacks against the Telcos.  The biggest vulnerability in the phone companies are the Operators, Service Technicians and general staff who are willing to break security protocol (or even completely disregard it) for someone who speaks their rare and unique, highly technical language.  This is a terrifying reality considering the power one can wield by simply convincing people over the phone to do something.</p>
<p>I highly recommend this book to other tech junkies looking for a good read, and am looking forward to reading some of his other books.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/book-review-ghost-in-the-wires/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building Awesome Facebook tabs with a Horribly Documented API</title>
		<link>http://blog.hackedexistence.com/building-awesome-facebook-tabs-with-a-horribly-documented-api</link>
		<comments>http://blog.hackedexistence.com/building-awesome-facebook-tabs-with-a-horribly-documented-api#comments</comments>
		<pubDate>Wed, 21 Sep 2011 17:34:48 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Facebook API]]></category>
		<category><![CDATA[Facebook Tabs]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=186</guid>
		<description><![CDATA[I built this Facebook tab in 2 days.  The entire template file is 111 lines of code.  2 days is way too long for 111 lines &#8230; You can check out the tab here. I&#8217;ve been playing with the Facebook &#8230; <a href="http://blog.hackedexistence.com/building-awesome-facebook-tabs-with-a-horribly-documented-api">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I built this Facebook tab in 2 days.  The entire template file is 111 lines of code.  2 days is way too long for 111 lines &#8230;</p>
<p>You can check out the tab <a href="https://www.facebook.com/#!/pages/Nation-Wide-Bar-Crawl/196540083699474" target="_blank">here</a>.</p>
<p>I&#8217;ve been playing with the Facebook API for a while, and I&#8217;ve never really been satisfied with the final product.  Something about it always seemed incomplete.  There were all kinds of restrictions and all kinds of hacks to break restrictions.  For example, I had a photo gallery inside a Facebook tab that leveraged a Dialog window to display a full size image, thanks to the old Javascript API.  Way cool effect for a photo gallery, but hacked out and not really supported which eventually caused it to break.</p>
<p>I&#8217;ve been working on a website for a few months, and I wanted to build something that would extend its reach to Facebook.  I wanted to create something that would really allow people to interact with each other, on Facebook, the way they used to with Apps like SuperPoke.</p>
<p>1) Pick a gift.<br />
2) Pick a friend.<br />
3) DIRECT INTERACTION that all your friends see.</p>
<p>The popularity of App provoked direct interaction between two people on Facebook is something that has really faded, probably due to horrible API documentation, and been replaced by a more pure, unaided post based interaction.  Our solution was to build an App that provided quality content worthy of sharing on Facebook while making it a very simple to share the content with a friend.</p>
<p>Facebook has built in facilities for sharing content with friends.  They used to provide access to some of those facilities in older versions of the API, but have since stripped out access to those facilities and replaced it with a lower level access to Facebook data, effectively moving third party developers closer to the database.  This is very beneficial to developers if they can figure out how to interface with the API, as it not only allows, but forces the developer to build out the full flow of interaction, but unfortunately, often becomes a task of blindly reverse engineering return values and function calls.</p>
<p>Alright, enough bitching about Facebook, lets take a look at the product &#8230; and I&#8217;ll bitch some more later.</p>
<p><img src="http://blog.hackedexistence.com/wp-content/themes/twentyten/images/beerwall.jpg" alt="Select a Beer" /></p>
<p>Our wall is composed of a huge list of beers that you can scroll through.  Step 1 is simply to pick a beer.  When you click on the beer, you are asked to authorize the app, giving access to your basic information (friends list).  After Authorizing the App (you only have to authorize it the first time you use it, it will be stored in your preferences), you will be shown a list of your friends in alphabetical order.  &#8216;In alphabetical order&#8217; doesn&#8217;t seem that impressive, but it&#8217;s not built in.  The Graph API uses lazy sorting when it returns the friends list, so it had to be sorted in Javascript by the browser.</p>
<p><img src="http://blog.hackedexistence.com/wp-content/themes/twentyten/images/select_friend.jpg" alt="Select a Friend" /></p>
<p>Step 2 is just as simple, click on one of your friends.</p>
<p><img src="http://blog.hackedexistence.com/wp-content/themes/twentyten/images/post_to_wall.jpg" alt="Post to Facebook Wall" /></p>
<p>Step 3: Facebook dialog asking if you want to post the chosen beer to the chosen friends wall.  Type in a description, and click share.  Thats it.  3 clicks and you can share any of the almost 200 beers with any of your 342,000 friends.  Simple enough, right?  Now lets look at the code &#8230;</p>
<pre>&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
// Put some style info for your div ids and classes here
&lt;/style&gt;
&lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/head&gt;
</pre>
<p>In the first block of code we setup a basic HTML layout and load the jquery script from Google&#8217;s Servers (Props to Google for hosting a lot of good frameworks for the masses).  The Jquery framework is going to help us with a few things, hiding and showing divs, getting and setting variable values, etc.</p>
<pre>&lt;body&gt;
&lt;div id="fb-root"&gt;&lt;/div&gt;
&lt;script&gt;
window.fbAsyncInit = function() {
FB.init({
appId  : 'YOUR_APP_ID_HERE', //FILL IN YOUR APP ID
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml  : true, // parse XFBML
oauth  : true // enable OAuth 2.0
});
//  FB.Event.subscribe('auth.statusChange', onFacebookStatusChange);
};
(function() {
var e = document.createElement('script');
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
</pre>
<p>The above code sets up the body element and uses javascript to load the Facebook Javascript API asynchronously.  Be sure to fill in your App ID or this will fail to load the API and all calls to the API will fail.</p>
<pre>function onFacebookInitialLoginStatus(response) {
if (response.status != "connected" || response.authResponse == null) {
facebookLogin();
}
FB.api('/me/friends', function(response) {
var friends1 = response.data;
var friends = friends1.sort(sortByName);
var l = friends.length;
for (var i=0;i&lt;l;i++) {
$('#friends ul').append("&lt;li onclick=\"personSelected(" + friends[i].id + ");\"&gt;&lt;img src=\"https://graph.facebook.com/" + friends[i].id + "/picture/\"&gt;&lt;p&gt;" + friends[i].name + "&lt;/p&gt;&lt;/li&gt;");
}
$('.beers_image_list').hide();
$('#beers_page_header').hide();
$('#footer').hide();
$('#friends_header').show();
$('.friends_image_list').show();
});
}
</pre>
<p>The above function is responsible for checking the LoginStatus of the requesting user.  I had to reverse engineer the response object as there is no proper documentation outlining what actually gets returned.  What comes back is a list of friends stored in response.data, but the Graph API uses a lazy sorting method and returns the list without any useful sort performed.  We must therefore implement a method in Javascript to sort the returned list.  This all takes place in the browser instead of on the server.</p>
<pre>function sortByName(a, b) {
var x = a.name.toLowerCase();
var y = b.name.toLowerCase();
return((x &lt; y) ? -1 : ((x &gt; y) ? 1 : 0));
}
</pre>
<p>The above function had to be implemented into the code (and was taken from HERE) to sort the list of friends.</p>
<pre>function facebookLogin() {
FB.login(onFacebookInitialLoginStatus);
}
</pre>
<p>The facebookLogin() function does some stuff FILL IN EXPLAINATION</p>
<pre>function shareBeer(selected_beer_img, selected_beer_link, selected_beer_name, selected_beer_brewery, selected_beer_type, selected_beer_locality) {
$('#selected_beer_image').html(selected_beer_img);
$('#selected_beer_link').html(selected_beer_link);
$('#selected_beer_name').html(selected_beer_name);
$('#selected_beer_brewery').html(selected_beer_brewery);
$('#selected_beer_type').html(selected_beer_type);
$('#selected_beer_locality').html(selected_beer_locality);
FB.getLoginStatus(onFacebookInitialLoginStatus);
}
</pre>
<p>The shareBeer() function is really the heart of what makes our product unique and easy to use.  By utilizing the Jquery framework, we are able to create a simple and easy to use user interface that allows users to perform step 1, Choose a Beer.  The function is fired by an onclick event attached to the &lt;li&gt; object that we will look at a little later in the HTML.  shareBeer() takes a few arguments, all of which are information that will get passed to the final dialog and describe the Beer that someone is going to share.  Because I am not overly familiar with Javascript, and it made debugging extremely easy, I chose to pass the variables from step 1 to step 2 inside of hidden div elements in the HTML.  The divs were hidden with CSS (display:hidden;).</p>
<pre>function personSelected(person) {
FB.ui({
method: 'feed',
to: person,
name: $('#selected_beer_name').html(),
link: 'http://nationwidebarcrawl.com/link/',
picture: $('#selected_beer_image').html(),
caption: 'Free. As in Beer.',
description: '&lt;center&gt;Brewery: ' + $('#selected_beer_brewery').html() + '&lt;/center&gt;&lt;center&gt;Type: ' + $('#selected_beer_type').html() + '&lt;/center&gt;&lt;center&gt;Locality: ' + $('#selected_beer_locality').html() + '&lt;/center&gt;'
}, function(response) {
if (response &amp;&amp; response.post_id) {
alert('post published');
} else {
alert('post failed');
}
});
}
&lt;/script&gt;
</pre>
<p>This function is responsible for popping the &#8216;post to wall&#8217; dialog which is popped by calling the &#8216;feed&#8217; method of the FB.ui() Graph API function.  We again utilize Jquery to pull the values from the Beer object variables that we set inside of hidden divs.  This function is triggered by an onclick event on the &lt;li&gt; that we will look at later in the HTML.  The onlick event passes the Facebook id of the friend who occupies the clicked &lt;li&gt;.  The FB.ui call utilizes this argument as the &#8216;to&#8217; value for the call.  If you leave the &#8216;to&#8217; value blank, the dialog will default to posting to the requesting users feed.  Without this &#8216;to&#8217; argument, our Facebook App loses its ability to provoke social interaction, and thus, its value to the Facebook community.</p>
<p>The description utilizes the &lt;center&gt; tag to get line breaks in our post.  Currently, Facebook does not allow you to put line breaks in your post description, but wrapping each line inside of a &lt;center&gt;&lt;/center&gt; tag will display the content on separate lines.</p>
<pre>&lt;div id="friends"&gt;
&lt;div id="friends_header"&gt;&lt;/div&gt;
&lt;ul&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;div id="beers_page_header"&gt;&lt;a href="http://nationwidebarcrawl.com/beers/" target="_blank"&gt;&lt;img src="/media/images/facebook/beers_button.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;ul&gt;
{% for beer in beers %}&lt;li&gt;&lt;a href="#" onclick="shareBeer('{{ beer.mainphoto.get_singlebeer_url }}', 'http://nationwidebarcrawl.com/beers/{{ beer.slug }}', '{{ beer }}', '{{ beer.brewery }}', '{{ beer.type }}', '{{ beer.get_locality_display }}');"&gt;&lt;img src="{{ beer.mainphoto.get_singlebeer_url }}" /&gt;&lt;p&gt;{{ beer }}&lt;/p&gt;&lt;/a&gt;&lt;/li&gt;{% if forloop.counter|divisibleby:"4" and not forloop.last %}&lt;/ul&gt;&lt;ul&gt;{% endif %}{% endfor %}
&lt;/ul&gt;
&lt;div id="footer"&gt;&lt;a href="http://cloudcreativegroup.com/" target="_blank"&gt;&lt;img src="/media/images/facebook/footer_logo.png"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div id="selected_beer_image"&gt;&lt;/div&gt;
&lt;div id="selected_beer_link"&gt;&lt;/div&gt;
&lt;div id="selected_beer_name"&gt;&lt;/div&gt;
&lt;div id="selected_beer_brewery"&gt;&lt;/div&gt;
&lt;div id="selected_beer_type"&gt;&lt;/div&gt;
&lt;div id="selected_beer_locality"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The above HTML generates the entire 3 step process in a single page, embedded inside of a Facebook fan page, utilizing Jquery to require only the initial page load to facilitate the entire 3 step process of sharing a gift with a friend.</p>
<p>AN OPEN CALL TO FACEBOOK</p>
<p>Facebook, love the website.  In fact, it eats up a large amount of my daily time, but we have to have a talk about your API.  You guys have moved at an extremely fast pace over the last couple years, starting out as a College based social network and eventually expanding to encompass the whole world.  During this time, many developers have felt as though you haven&#8217;t put enough emphasis on keeping your API documentation up to date (and working for that matter).  I like how you guys have spent a lot of time trying to explain the concepts behind a lot of the inner workings of your API, but honestly, none of the documentation really helped me understand what was going on.</p>
<p>The one thing I think you guys could really improve, and quite easily, would be a full API reference.  If you&#8217;re not sure what one of those looks like, take a look at Google Maps API Version 3 reference here: <a href="http://code.google.com/apis/maps/documentation/javascript/reference.html" target="_blank">http://code.google.com/apis/maps/documentation/javascript/reference.html</a></p>
<p>With a fully documented API reference, you will see a lot more quality apps being developed for your platform.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/building-awesome-facebook-tabs-with-a-horribly-documented-api/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MediaTemple CentOS 5.5 (VE) Server Build &#8211; Django 1.3, Python 2.7, MySQL 5.5, PHP 5.3</title>
		<link>http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3</link>
		<comments>http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3#comments</comments>
		<pubDate>Thu, 04 Aug 2011 06:37:56 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Media Temple]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[MediaTemple]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Server Build]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=175</guid>
		<description><![CDATA[This is an updated version of an older blog post outlining a full (VE) build for django.  I had to update my server due to incompatibilities between the latest version of WordPress and the versions of PHP/MySQL found in the &#8230; <a href="http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.hackedexistence.com/wp-content/themes/twentyten/images/VEServer.JPG" alt="VE Server" width="1122" height="265" /></p>
<p>This is an updated version of an older blog post outlining a full (VE) build for django.  I had to update my server due to incompatibilities between the latest version of WordPress and the versions of PHP/MySQL found in the standard CentOS repos.</p>
<p><span style="color: #ff0000;">// SHOUTOUTS</span></p>
<p>Malcolm Frazier &#8211; (still) holding it down with the Linux knowledge.</p>
<p><span style="color: #ff0000;">// USER ACCOUNTS</span></p>
<p>The first step is to create a user account so you don&#8217;t have to use root</p>
<pre># useradd &lt;username&gt;
# passwd &lt;username&gt;</pre>
<p>Add a user group so we can setup the sudoers file and add our new account to the group</p>
<pre># /usr/sbin/groupadd &lt;new_group_name&gt;
# /usr/sbin/usermod -a -G &lt;new_group_name&gt; &lt;username&gt;</pre>
<p>I like to use the locate command a lot, so lets build the index of the file system that locate uses to search</p>
<pre># updatedb</pre>
<p>Setup the sudoers config file</p>
<pre># vim /etc/sudoers</pre>
<p>Add the following lines to the bottom of the file:</p>
<pre># Customizations
%&lt;new_group_name&gt;     ALL=(ALL)     ALL</pre>
<p>*** The above modification more or less gives all users in &lt;new_group_name&gt; the ability to do anything root can do, without the root password.  This is fine for building the server, but after the server is built, you should restrict the permission levels a little bit more.</p>
<p>At this point you should be able to exit ssh and log back in as your new user account.  You can use sudo &lt;command&gt; to execute commands as root, or use sudo -s as a replacement for su.</p>
<p><span style="color: #ff0000;">// UPGRADE PACKAGES SYSTEM WIDE</span></p>
<pre># yum upgrade</pre>
<p><span style="color: #ff0000;">// INSTALLING PYTHON 2.7</span></p>
<p>I&#8217;ve chosen to use Python 2.7 as my version of python for django.  CentOS 5.5 comes with Python 2.4 already installed.  I had some down time on a past project because I asked the techs at RackSpace to upgrade the version of Python on the server and they started by uninstalling Python 2.4.  The problem is that the yum package management system that CentOS uses is built on top of Python.  If you uninstall Python 2.4, you will not be able to use yum to install Python 2.7, or any other package at that point.  The solution is to install Python 2.7 in parallel to 2.4, have Django and all your other apps use the 2.7 install, and leave 2.4 to be used by yum and the underlying OS.</p>
<p>Before we start compiling, lets install the GCC compiler:</p>
<pre># yum install gcc</pre>
<p>This will prevent the following error from occurring if you try to compile python without gcc:</p>
<pre>configure: error: in `/root/Source/Python-2.7':
configure: error: no acceptable C compiler found in $PATH</pre>
<p>Additionally, you&#8217;ll want to install a few extra optional dependencies for Python</p>
<pre># yum install readline-devel gdbm-devel sqlite-devel
# yum install openssl-devel ncurses-devel bzip2-devel</pre>
<p>Theres a great tutorial on installing Python 2.7 on CentOS 5 <a href="http://toey.tc20.net/2010/08/04/install-python-2-7-gevent-on-centos-5-x86_64/" target="_blank">here</a>.</p>
<p>Instead of using /usr/src/ for all the source code, I created /root/Source/ to hold the source from all the packages.  Inside of Source, download and extract Python 2.7:</p>
<pre># wget http://www.python.org/ftp/python/2.7/Python-2.7.tar.bz2
# tar -xvjf Python-2.7.tar.bz2
# cd Python-2.7
# ./configure --help</pre>
<p>Read through the configure help and see if there are any options you want to enable or customize.  Then run the configuration script:</p>
<pre># ./configure --prefix=/usr/local/python2.7 --enable-shared</pre>
<p>&#8211;prefix tells python to install to a directory other than the default.  This is necessary if we want to run both 2.7 and 2.4 side by side.</p>
<p>&#8211;enable-shared will prevent an error later on when trying to build mod_wsgi.  If you get the following error when building mod_wsgi, recompile and reinstall python with &#8211;enable-shared:</p>
<pre>/usr/local/python2.7/lib/libpython2.7.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
apxs:Error: Command failed with rc=65536
make: *** [mod_wsgi.la] Error 1</pre>
<p>Now its time to build and install Python:</p>
<pre># make
# make install</pre>
<p><span style="color: #ff0000;">// SETUP ENVIRONMENT VARIABLES</span></p>
<pre>$ vim ~/.bashrc</pre>
<p>Add the following to the bottom of .bashrc:</p>
<pre># User specific aliases and functions
alias python='/usr/local/python2.7/bin/python'</pre>
<p>Log out, Log back in, and you should be able to execute the new Python 2.7</p>
<pre>$ python
Python 2.7
&gt;&gt;&gt;</pre>
<p><span style="color: #ff0000;">// INSTALLING PIL (PYTHON IMAGING LIBRARY)</span></p>
<p>At this point, if you install PIL without first satisfying the optional dependencies, PIL will be built without libjpeg and zlib (png support).  The output of python setup.py install would be:</p>
<pre>*** TKINTER support not available
*** JPEG support not available
*** ZLIB (PNG/ZIP) support not available
*** FREETYPE2 support not available
*** LITTLECMS support not available</pre>
<p>Unfortunately, PIL doesn&#8217;t complain very loudly and will still install a working version that will not be able to handle .jpg or .png files.  If you install PIL without the header libraries for the dependencies present, you will receive the following error in django&#8217;s admin when trying to upload an image file:</p>
<pre>Upload a valid image. The file you uploaded was either not an image or a corrupted image.</pre>
<p>You can further verify if the proper support is compiled in from the shell:</p>
<pre>$ python
&gt;&gt;&gt; from PIL import Image
&gt;&gt;&gt; i = Image.open("/path/to/some/image.jpg")
&gt;&gt;&gt; i.verify()
&gt;&gt;&gt; i.load()
Traceback (most recent call last):
File "&lt;console&gt;", line 1, in &lt;module&gt;
File "/usr/local/python2.7/lib/python2.7/site-packages/PIL/ImageFile.py", line 189, in load
d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
File "/usr/local/python2.7/lib/python2.7/site-packages/PIL/Image.py", line 385, in _getdecoder
raise IOError("decoder %s not available" % decoder_name)
IOError: decoder jpeg not available</pre>
<p>You can see from the above error that the jpeg decoder is not available.  If you&#8217;ve already installed PIL, uninstall it.  If you havn&#8217;t installed PIL yet, this will save you a lot of time (:</p>
<pre># yum install zlib zlib-devel
# yum install libjpeg libjpeg-devel
# yum install freetype freetype-devel</pre>
<p>Django relies heavily on the PIL.  Again in our /root/Source directory, install PIL:</p>
<pre># wget http://effbot.org/downloads/Imaging-1.1.7.tar.gz
# tar xvfz Imaging-1.1.7.tar.gz
# cd Imaging-1.1.7
# python setup.py build_ext -i</pre>
<p>Check to make sure that libjpeg and zlib were found:</p>
<pre>*** TKINTER support not available
--- JPEG support available
--- ZLIB (PNG/ZIP) support available
--- FREETYPE2 support available
*** LITTLECMS support not available</pre>
<p>Run a test to make sure that everything works:</p>
<pre># python selftest.py
--------------------------------------------------------------------
PIL 1.1.7 TEST SUMMARY
--------------------------------------------------------------------
Python modules loaded from ./PIL
Binary modules loaded from ./PIL
--------------------------------------------------------------------
--- PIL CORE support ok
*** TKINTER support not installed
--- JPEG support ok
--- ZLIB (PNG/ZIP) support ok
--- FREETYPE2 support ok
*** LITTLECMS support not installed
--------------------------------------------------------------------
Running selftest:
--- 57 tests passed.</pre>
<p>And finally, install PIL:</p>
<pre># python setup.py install</pre>
<p>You should now be able to import PIL inside of python:</p>
<pre>$ python
&gt;&gt;&gt;import PIL
&gt;&gt;&gt;</pre>
<p><span style="color: #ff0000;">// INSTALLING MYSQL</span></p>
<p>Enable the Remi Repository to install MySQL 5.5 and PHP 5.3.  More information about the Remi Repository can be found <a href="http://rpms.famillecollet.com/" target="_blank">here</a>.</p>
<pre># wget http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
# rpm -Uvh epel-release-5-4.noarch.rpm
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
# yum --enablerepo=remi list mysql mysql-server
# yum --enablerepo=remi install mysql.x86_64 mysql-server.x86_64</pre>
<p>Start the MySQL Server:</p>
<pre># /etc/init.d/mysqld start</pre>
<p>In order to set the initial root password, and get rid of the built in tables/user accounts for testing, run:</p>
<pre># /usr/bin/mysql_secure_installation</pre>
<p>Follow the instructions, pick your customizations &#8230; then make sure MySQL is installed and working:</p>
<pre># mysql -u root -p
Enter password:
mysql&gt; SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.5.14    |
+-----------+
1 row in set (0.00 sec)</pre>
<p>Add MySQL to the proper run level:</p>
<pre># /sbin/chkconfig mysqld on</pre>
<p><span style="color: #ff0000;">// MYSQL-PYTHON GAP</span></p>
<p>Next, you need to install MySQL-python, the python interface to MySQL.  If you do not install MySQL-python, later on when you try to do a &#8216;python manage.py syncdb&#8217; django will not be able to communicate with MySQL and will throw the following error:</p>
<pre>django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb</pre>
<p>Setuptools is a required dependency of MySQL-python.  Download it from <a href="http://pypi.python.org/pypi/setuptools" target="_blank">here</a> and install it, setting the prefix to our freshly installed python2.7</p>
<pre># sh setuptools*.egg --prefix=/usr/local/python2.7</pre>
<p>Now install the MySQL headers from the Remi repo, then install MySQL-python:</p>
<pre># yum --enablerepo=remi install mysql-devel.x86_64
# wget http://sourceforge.net/projects/mysql-python/files/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz/download
# tar -zxvf MySQL-python-1.2.3.tar.gz
# cd MySQL-python-1.2.3
# python setup.py build
# python seutp.py install</pre>
<p>At this point django should be able to talk to MySQL using MySQL-python.</p>
<p><span style="color: #ff0000;">// INSTALLING APACHE</span></p>
<p>Next we have to install our web server, Apache.  There&#8217;s a pretty straight forward tutorial on this <a href="http://www.cyberciti.biz/faq/linux-install-and-start-apache-httpd/" target="_blank">here</a>.</p>
<pre># yum install httpd
# /sbin/chkconfig httpd on
# /etc/init.d/httpd start
Starting httpd:                                            [  OK  ]</pre>
<p>At this point, you should spend some quality time with /etc/httpd/conf/httpd.conf to really squeeze some power out of apache.</p>
<p><span style="color: #ff0000;">// INSTALLING DJANGO</span></p>
<p>The django install docs can be found <a href="https://docs.djangoproject.com/en/1.3/topics/install/" target="_blank">here</a>.</p>
<pre># wget http://www.djangoproject.com/download/1.3/tarball/
# tar xzvf Django-1.3.tar.gz
# cd Django-1.3
# python setup.py install
$ python
&gt;&gt;&gt; import django
&gt;&gt;&gt;</pre>
<p><span style="color: #ff0000;">// INSTALLING PHPMYADMIN</span></p>
<p>PhpMyAdmin is a web interface for controlling your MySQL database.</p>
<pre># yum install phpmyadmin</pre>
<p>This will install PHP as a dependency, but you will still need to setup PHP.  Setup the PHP Cookie:</p>
<pre># vim /usr/share/phpmyadmin/config.inc.php</pre>
<p>Add the Python Shared Libraries</p>
<pre># vim /etc/ld.so.conf.d/python2.7.conf</pre>
<p>add the following line:</p>
<pre>/usr/local/python2.7/lib</pre>
<p>Create necessary links and cache the new libraries:</p>
<pre># ldconfig</pre>
<p><span style="color: #ff0000;">// INSTALLING MOD_WSGI</span></p>
<p>mod_wsgi is the link between apache and django.  It is responsible for taking the web request from apache and getting it to your django app for handling.  The mod_wsgi installation docs are a great resource, they can be found <a href="http://code.google.com/p/modwsgi/wiki/InstallationInstructions" target="_blank">here</a>.</p>
<p>First, we need to install the source code for apache, as mod_wsgi needs it to build.  Install the httpd-devel package, which will install the headers for apache.</p>
<pre># yum install httpd-devel</pre>
<p>Get and install mod_wsgi</p>
<pre># wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
# tar -zxvf mod_wsgi-3.3.tar.gz
# cd mod_wsgi-3.3
# ./configure --help
# ./configure --with-python=/usr/local/python2.7/bin/python
# make
# make_install</pre>
<p><span style="color: #ff0000;">// POINT APACHE AT DJANGO USING MOD_WSGI</span></p>
<p>First, you need to tell apache which version of python to use so it doesn&#8217;t use the default 2.4:</p>
<pre># vim /etc/httpd/conf/httpd.conf</pre>
<p>Add the following to the bottom of the file:</p>
<pre># Python Versioning Control for mod_wsgi
WSGIPythonHome /usr/local/python2.7</pre>
<p>Make sure you load mod_wsgi in httpd.conf at the end of the LoadModule section</p>
<pre>LoadModule wsgi_module modules/mod_wsgi.so</pre>
<p>Then restart apache</p>
<pre># /etc/init.d/httpd restart</pre>
<p>Now you can configure your virtual hosts in apache to point to a &#8216;django.wsgi&#8217; file thats specific to each django project you create.  Add the WSGIScriptAlias to your Virtual Host configuration file:</p>
<pre>WSGIScriptAlias / /path/to/your/django/project/django_project_name/apache/django.wsgi</pre>
<p>Add the &#8216;apache&#8217; directory to your django project, and create the django.wsgi file inside the apache directory:</p>
<pre>$ cd /path/to/your/django/project/django_project_name/
$ mkdir apache
$ cd apache
$ vim django.wsgi</pre>
<p>Copy the following into the django.wsgi file:</p>
<pre>import os
import os.path
import sys

sys.path.append('/path/to/project/root')

os.environ['PYTHON_EGG_CACHE'] = '/path/to/a/directory/for/egg_cache'
os.environ['DJANGO_SETTINGS_MODULE'] = 'your_django_project_name.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()</pre>
<p>If you&#8217;ve made it this far, you should have a working django install.</p>
<pre>(:</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Look at Facebook Five Years Later</title>
		<link>http://blog.hackedexistence.com/a-look-at-facebook-five-years-later</link>
		<comments>http://blog.hackedexistence.com/a-look-at-facebook-five-years-later#comments</comments>
		<pubDate>Tue, 17 May 2011 22:51:03 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=173</guid>
		<description><![CDATA[Check out our latest paper: A Look at Facebook Five Years Later]]></description>
			<content:encoded><![CDATA[<p>Check out our latest paper:</p>
<p><a href="http://www.hackedexistence.com/project-facebook.html">A Look at Facebook Five Years Later</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/a-look-at-facebook-five-years-later/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Locking down SFTP user without SSH on CentOS 5</title>
		<link>http://blog.hackedexistence.com/locking-down-sftp-user-without-ssh-on-centos-5</link>
		<comments>http://blog.hackedexistence.com/locking-down-sftp-user-without-ssh-on-centos-5#comments</comments>
		<pubDate>Tue, 03 May 2011 03:13:46 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Media Temple]]></category>
		<category><![CDATA[CentOS 5]]></category>
		<category><![CDATA[MediaTemple]]></category>
		<category><![CDATA[SFTP]]></category>
		<category><![CDATA[SSH]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=167</guid>
		<description><![CDATA[&#8221;&#8217; Problem Context &#8221;&#8217; We have multiple sites hosted on a single server and needed to give individual FTP accounts to each person, but can not give them permission to see the other sites on the server or any of &#8230; <a href="http://blog.hackedexistence.com/locking-down-sftp-user-without-ssh-on-centos-5">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><span style="color: #3366ff;">&#8221;&#8217; Problem Context &#8221;&#8217;</span><br />
We have multiple sites hosted on a single server and needed to give individual FTP accounts to each person, but can not give them permission to see the other sites on the server or any of the configuration files.</p>
<p><span style="color: #3366ff;">&#8221;&#8217; Solution &#8221;&#8217;</span><br />
For security reasons, FTP is disallowed on our server forcing everyone to use SFTP.  As such, we were not able to simply disallow SSH as it is required for SFTP to function properly.  After messing around with Linux file permissions for a while, we figured out a few modifications that need to be made to block our new users from SSH while maintaining their ability to SFTP to a specific directory and be able to modify all files under that directory.</p>
<p>The first step is to create a group for the new user to apply to their specific folder so we can set permissions on their files at the group level.  Then we create a new user account and add them to the new group.  For this post we will use the user NewUser and the group NewGroup.</p>
<pre># /usr/sbin/groupadd NewGroup
# /usr/sbin/useradd -g NewGroup NewUser
# /usr/bin/passwd NewUser
</pre>
<p>Now lets setup the directory the new user will drop into, and block their ability to do anything useful with SSH.  Inside of /etc/passwd, find the line that looks something like this:</p>
<pre># vim /etc/passwd
NewUser:x:501:502::/home/NewUser/:/bin/bash
</pre>
<p>Now lets say the root directory for the site we want to the user to modify is /var/www/website.com/ so we change the home directory in /etc/passwd to point to this directory.  When the user SFTPs into the website.com, they will be dropped in this directory.  Additionally, we want to set their shell to the location of sftp-server, which can be found by running   #which sftp-server</p>
<pre>NewUser:x:501:502::/var/www/website.com/:/usr/libexec/openssh/sftp-server
</pre>
<p>Now we can change the group permissions on /var/www/website.com/ with</p>
<pre># cd /var/www/website.com/
# chgrp -R NewGroup *
</pre>
<p>This will let you control permissions for NewUser at the group level.  The last thing to do is disallow the user read on the directory above website.com/ which will stop them from going up the directory tree, effectively locking them into website.com/</p>
<pre># cd /var
# chmod 771 www
</pre>
<p>At this point, NewUser will be able to SFTP to website.com which will drop them into /var/www/website.com/ but they will be unable to move up a directory and SSH will respond with a shell that isn&#8217;t interactive.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/locking-down-sftp-user-without-ssh-on-centos-5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webcam Surveillance System</title>
		<link>http://blog.hackedexistence.com/webcam-surveillance-system</link>
		<comments>http://blog.hackedexistence.com/webcam-surveillance-system#comments</comments>
		<pubDate>Tue, 12 Apr 2011 21:57:51 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Astak Mole Camera]]></category>
		<category><![CDATA[Evo 4g]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac Mini Server]]></category>
		<category><![CDATA[Webcam Surveillance System]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=157</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/webcam-surveillance-system/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Power of Django: 9 websites, 1 database</title>
		<link>http://blog.hackedexistence.com/the-power-of-django-9-websites-1-database</link>
		<comments>http://blog.hackedexistence.com/the-power-of-django-9-websites-1-database#comments</comments>
		<pubDate>Fri, 01 Apr 2011 12:46:12 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=140</guid>
		<description><![CDATA[# Shoutouts Most of this information came from Franchising: Running Multiple Sites from one Django Codebase by Huy Nguyen.  Really great article. # Problem Context For this project, we had to build 9 splash pages for a QR Code campaign. &#8230; <a href="http://blog.hackedexistence.com/the-power-of-django-9-websites-1-database">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/themes/twentyten/images/django-logo.png" alt="Django Logo" width="600" height="209" /></p>
<p><strong><span style="color: #3366ff;"># Shoutouts</span></strong><br />
Most of this information came from <a href="http://www.huyng.com/archives/franchising-running-multiple-sites-from-one-django-codebase-2/394/">Franchising: Running  Multiple Sites from one Django Codebase</a> by Huy Nguyen.  Really great article.<a href="http://www.huyng.com/archives/franchising-running-multiple-sites-from-one-django-codebase-2/394/"><br />
</a></p>
<p><strong><span style="color: #3366ff;"># Problem Context</span></strong><br />
For this project, we had to build 9 splash pages for a QR Code campaign.  Each website had to have its own branding, and we were afforded the luxury of having a separate domain name for each page.  By leveraging Django, we were able to provide a single page CMS to manage all of the splash pages while each splash page exists on its own domain.</p>
<p><strong><span style="color: #3366ff;"># Solution</span></strong><br />
At some point from the initial request to the served template we had to distinguish which domain the request was generated from.  This was accomplished at the apache level, using the django.wsgi script to add an environment variable equal to the domain the request originated from.  The different django.wsgi scripts (1 for each domain) were then called by each virtual host individually.</p>
<p>At this point you should have a django project already created.  There will be a single project that all of the individual sites are served from.  Create the main project as you would at the beginning of any normal project.</p>
<p><strong><span style="color: #3366ff;"># Setup Apache to call individual wsgi files</span></strong><br />
In your virtual host configuration file, you want to declare an alias that points to a common directory that will be used to hold the media for all the different domains, then point each domain at its own django.wsgi script:</p>
<pre>Alias /media/ /directory/to/SharedDomainForAllSites.com/htdocs/media/
WSGIScriptAlias / /path/to/django_project/apache/IndividualSiteName/django.wsgi
</pre>
<p>Now in /path/to/django_project/apache/ create a directory for each domain that will call your project.  We will put the django.wsgi file from above into this directory.</p>
<pre>$ cd /path/to/django_project/
$ mkdir apache
$ cd apache
$ mkdir IndividualSiteName
$ cd IndividualSiteName
$ vim django.wsgi
</pre>
<p>Inside each django.wsgi file, set the OVERLOAD_SITE variable to a name that identifies each domain uniquely.  We will use this variable to tell django which CSS file to load, which template to use, which domain to search for media files, etc.</p>
<pre>import os
import os.path
import sys

sys.path.append('/path/to/django/django_project')

os.environ['DJANGO_SETTINGS_MODULE'] = 'django_project.settings'
os.environ['OVERLOAD_SITE'] = 'IndividualSiteName'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>Back up in your main project directory, were going to modify the settings.py file to overload the MEDIA_ROOT and MEDIA_URL variables based on the request from each domain.  At the bottom of settings.py, add the function that will overload the variables:</p>
<pre>#
# IMPORT CUSTOM SETTINGS BASED ON DOMAIN MAKING THE CALL
#
import os
OVERLOAD_SITE = os.environ.get('OVERLOAD_SITE')
if OVERLOAD_SITE:
        OVERLOAD_SITE_MODULE ="site_overloads" + "." + OVERLOAD_SITE
        exec "from %s.settings import *" % (OVERLOAD_SITE_MODULE)
        # Overload the MEDIA_ROOT with site specific path
        try:
                MEDIA_ROOT = OVERLOAD_MEDIA_ROOT
        except:
                pass
        # Overload the MEDIA_URL with site specific URL
        try:
                MEDIA_URL = OVERLOAD_MEDIA_URL
        except:
                pass
</pre>
<p>For the MEDIA_ROOT and MEDIA_URL configuration at the top of the settings.py file, set a directory that will be a common directory used to host the media for all domains.  If you override the MEDIA_URL for every domain, these settings will be ignored, so their values arn&#8217;t that important.</p>
<p>To set the override values, create the site_overloads directory that is referenced in the function we just added to settings.py.  It should be in the project root.  Inside site_overloads, create a directory for each individual domain that has the same name as the OVERLOAD_SITE variable from the django.wsgi file.  Inside of site overloads, you must add a blank __init__.py file, or django will not be able to pull files from the directory:</p>
<pre>$ cd /path/to/django_project/
$ mkdir site_overloads
$ cd site_overloads
$ touch __init__.py
$ mkdir IndividualSiteName
$ cd IndividualSiteName
$ touch __init__.py
</pre>
<p>Now we will add a settings.py and urls.py file to each folder that will provide the overloads for each specific domain:</p>
<pre># settings.py
# Overload Default MEDIA_ROOT
# Use this if you want to serve up separate media for each domain
#OVERLOAD_MEDIA_ROOT = '/c2g/sites/auburnparkave.com/htdocs/media/'

# Overload Default MEDIA_URL
OVERLOAD_MEDIA_URL = 'http://IndividualSiteName.com/media/'
</pre>
<p>In your Apache Virtualhost config, recall that we set an Alias to /media/.  This Alias will allow you to put any domain in OVERLOAD_MEDIA_URL and have the single media directory exist at http://EachDomainName.com/media/.</p>
<p>New lets look at the urls.py.  For our project, each domain was hosting a single splash page, so we were able to serve all requests by providing the context straight from the url, letting us completely skip making any views.</p>
<pre># urls.py
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from pages.models import Page

urlpatterns = patterns('',
(r'^$', direct_to_template, {'template': 'SingleTemplate.html',
'extra_context': {'page': Page.objects.get(name__exact='IndividualSiteName'),
'sliderImages': Page.objects.get(name__exact='IndividualSiteName').slider.photos.all()}}),
)
</pre>
<p>The above assumes  you have a Page class in your models.py with a name field and a slider field.  You can modify the code to request anything you want from your models, or call a view for more indepth interaction.</p>
<p>Well, that should get you separate domains all hooked up to a single django app, capable of having a shared or individual media directories as well as individual domain names, all with a single page CMS for managing all your sites.</p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/the-power-of-django-9-websites-1-database/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MediaTemple CentOS 5.5 (VE) Server Build &#8211; Django 1.3, Python 2.7</title>
		<link>http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build</link>
		<comments>http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build#comments</comments>
		<pubDate>Mon, 28 Mar 2011 13:51:24 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Media Temple]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=107</guid>
		<description><![CDATA[THIS IS OUTDATED DOCUMENTATION. NEW VERSION AVAILABLE HERE: http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3 Media Temple is End-Of-Life-ing their Grid Server Django Containers.  As such, I had to migrate all my django sites off the grid onto a new (VE) server.  This is a guide &#8230; <a href="http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff0000;">THIS IS OUTDATED DOCUMENTATION.  NEW VERSION AVAILABLE HERE:</span></p>
<p><a href="http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3">http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build-django-1-3-python-2-7-mysql-5-5-php-5-3</a></p>
<p><img src="http://blog.hackedexistence.com/wp-content/themes/twentyten/images/VEServer.JPG" alt="VE Server" width="1122" height="265" /></p>
<p>Media Temple is End-Of-Life-ing their Grid Server Django Containers.  As such, I had to migrate all my django sites off the grid onto a new (VE) server.  This is a guide for building a stock CentOS 5.5 server with django and python 2.7.</p>
<p><span style="color: #ff0000;">// SHOUT OUTS</span></p>
<p>Malcolm Frazier &#8211; Holding it down with all the linux knowledge.</p>
<p><span style="color: #ff0000;">// USER ACCOUNTS</span></p>
<p>The first step is to create a user account so you don&#8217;t have to use root</p>
<pre># useradd &lt;username&gt;
# passwd &lt;username&gt;
</pre>
<p>Add a user group so we can setup the sudoers file and add our new user account to the group</p>
<pre># /usr/sbin/groupadd &lt;new_group_name&gt;
# /usr/sbin/usermod -a -G &lt;new_group_name&gt; &lt;new_user_name&gt;
</pre>
<p>I like to use the locate command a lot, so lets build the index of file names to search from</p>
<pre># updatedb
</pre>
<p>Setup the sudoers config file</p>
<pre># vim /etc/sudoers
</pre>
<p>Add the following lines to the bottom of the file:</p>
<pre># Customizations
%&lt;new_group_name&gt;    ALL=(ALL)       ALL
</pre>
<p>At this point you should be able to exit ssh and log back in as your new user account.  You can use sudo &lt;command&gt; to execute commands as root, or use sudo -s as a replacement for su.</p>
<p><span style="color: #ff0000;">// UPGRADE PACKAGES SYSTEM WIDE</span></p>
<pre># yum upgrade
</pre>
<p><span style="color: #ff0000;">// INSTALLING PYTHON 2.7</span></p>
<p>I&#8217;ve chosen to use Python 2.7 as my version of python for django.  CentOS comes with Python 2.4 already installed.  I had some down time on a project because I asked the techs at RackSpace to upgrade the version of python on the server and they started by trying to uninstall Python 2.4.  The problem is that the yum package management system that CentOS uses is built on top of python.  If you uninstall python 2.4, you will not be able to use yum to install python 2.7, or any package at that point.  The solution is to install Python 2.7 in parallel to 2.4, have Django and all your other apps use the 2.7 install, and leave 2.4 to be used by yum.</p>
<p>Theres a great tutorial on installing Python 2.7 on CentOS 5 <a href="http://toey.tc20.net/2010/08/04/install-python-2-7-gevent-on-centos-5-x86_64/">here</a>.</p>
<p>Instead of using /usr/src/ for all the source code, I created /root/Source/ to hold the source from all the packages.  Inside of Source, download and extract Python 2.7:</p>
<pre># wget http://www.python.org/ftp/python/2.7/Python-2.7.tar.bz2
# tar -xvjf Python-2.7.tar.bz2
# cd Python-2.7
# ./configure --help
</pre>
<p>Read through the configure help and see if there are any options you want to enable or customize.  Then ./configure</p>
<pre># ./configure --prefix=/usr/local/python2.7
</pre>
<p>&#8211;prefix tells the configure script to install python into /usr/local/python2.7/ to create a completely separate parallel installation next to python 2.4.</p>
<p>Because of a mod_wsgi error that you will run into later, you should install the following dependencies before installing python:</p>
<pre># yum install readline-devel
# yum install gdbm-devel
# yum install sqlite-devel
</pre>
<p>After installing the dependencies, you can run ./configure again after you do a # make clean.  This will get rid of the old config file and generate a new one.</p>
<pre># make clean
# ./configure --prefix=/usr/local/python2.7
</pre>
<p>Assuming everything went well, build and install python 2.7</p>
<pre># make
# make install
</pre>
<p><span style="color: #ff0000;">// SETUP ENVIRONMENT VARIABLES</span></p>
<pre>$ vim ~/.bashrc
</pre>
<p>Add the following to the bottom of .bashrc:</p>
<pre># User specific aliases and functions
alias python='/usr/local/python27/bin/python'
</pre>
<p>Log out, Log back in, and you should be able to execute the new Python 2.7</p>
<pre>$ python
Python 2.7 (r27:82500, Mar 22 2011, 13:20:42)
</pre>
<p><span style="color: #ff0000;">// INSTALLING PIL (PYTHON IMAGING LIBRARY)</span></p>
<p>At this point, if you install PIL without first satisfying dependencies, PIL will be built without libjpeg and zlib (png support).  The output of python setup.py install would be:</p>
<pre>*** TKINTER support not available
*** JPEG support not available
*** ZLIB (PNG/ZIP) support not available
*** FREETYPE2 support not available
*** LITTLECMS support not available
</pre>
<p>Unfortunately, PIL doesn&#8217;t complain very loudly and will still install a working version that will not be able to handle .jpg or .png files.  If you install PIL without the header libraries for the dependencies present, you will receive the following error in django&#8217;s admin when trying to upload a file:</p>
<pre>Upload a valid image. The file you uploaded was either not an image or a corrupted image.
</pre>
<p>You can further verify if the proper support is compiled in from the shell:</p>
<pre>$ python
&gt;&gt;&gt; from PIL import Image
&gt;&gt;&gt; i = Image.open("/path/to/some/image.jpg")
&gt;&gt;&gt; i.verify()
&gt;&gt;&gt; i.load()
Traceback (most recent call last):
File "&lt;console&gt;", line 1, in &lt;module&gt;
File "/usr/local/python2.7/lib/python2.7/site-packages/PIL/ImageFile.py", line 189, in load
d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
File "/usr/local/python2.7/lib/python2.7/site-packages/PIL/Image.py", line 385, in _getdecoder
raise IOError("decoder %s not available" % decoder_name)
IOError: decoder jpeg not available
</pre>
<p>You can see from the above error that the jpeg decoder is not available.  If you&#8217;ve already installed PIL, uninstall it.  If you havn&#8217;t installed PIL yet, this will save you a lot of time (:</p>
<pre># yum install zlib zlib-devel
# yum install libjpeg libjpeg-devel
# yum install freetype freetype-devel
</pre>
<p>Django relies heavily on the Python Imaging Library PIL.  Again in our /root/Source/ directory, install PIL</p>
<pre># wget http://effbot.org/downloads/Imaging-1.1.7.tar.gz
# tar xvfz Imaging-1.1.7.tar.gz
# cd Imaging-1.1.7
# python setup.py build_ext -i
</pre>
<p>Check to make sure that libjpeg and zlib were found:</p>
<pre>*** TKINTER support not available
--- JPEG support available
--- ZLIB (PNG/ZIP) support available
--- FREETYPE2 support available
*** LITTLECMS support not available
</pre>
<p>Run a test to make sure that everything works:</p>
<pre># python selftest.py
--------------------------------------------------------------------
PIL 1.1.7 TEST SUMMARY
--------------------------------------------------------------------
Python modules loaded from ./PIL
Binary modules loaded from ./PIL
--------------------------------------------------------------------
--- PIL CORE support ok
*** TKINTER support not installed
--- JPEG support ok
--- ZLIB (PNG/ZIP) support ok
--- FREETYPE2 support ok
*** LITTLECMS support not installed
--------------------------------------------------------------------
Running selftest:
--- 57 tests passed.
</pre>
<p>And finally, install PIL</p>
<pre># python setup.py install
</pre>
<p>You should now be able to import PIL inside of python:</p>
<pre>$ python
&gt;&gt;&gt;import PIL
&gt;&gt;&gt;
</pre>
<p><span style="color: #ff0000;">// INSTALLING APACHE</span></p>
<p>Next we have to install our web server, Apache.  Theres a pretty straight forward tutorial on this <a href="http://www.cyberciti.biz/faq/linux-install-and-start-apache-httpd/">here</a>.</p>
<pre># yum install httpd
# /sbin/chkconfig httpd on
# /etc/init.d/httpd start
Starting httpd:                                            [  OK  ]
</pre>
<p>At this point, you should spend some quality time with /etc/httpd/conf/httpd.conf to really squeeze some power out of apache.</p>
<p><span style="color: #ff0000;">// INSTALLING MOD_WSGI</span></p>
<p>mod_wsgi is the link between apache and django.  It is responsible for taking the web request from apache, and getting it to your django app for handling.  The mod_wsgi installation docs are a great resource, they can be found <a href="http://code.google.com/p/modwsgi/wiki/InstallationInstructions">here</a>.</p>
<p>First, we need to install the source code for apache, as mod_wsgi needs it to build.  Install the httpd-devel package, which will install the headers for apache.</p>
<pre># yum install httpd-devel
</pre>
<p>Get and install mod_wsgi, again from /root/Source/</p>
<pre># wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
# tar -zxvf mod_wsgi-3.3.tar.gz
# cd mod_wsgi-3.3
# ./configure --help
# ./configure --with-python=/usr/local/python27/bin/python
# make
# make_install
</pre>
<p><span style="color: #ff0000;">// INSTALLING PHPMYADMIN</span></p>
<p>PhpMyAdmin is a web interface for controlling your MySQL database.  The RPM for PhpMyAdmin is in the rpmforge repo, so we will add that repo to yum.  Again from /root/Source/:</p>
<pre># wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
# rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
# rpm -K rpmforge-release-0.5.2-2.el5.rf.*.rpm
# rpm -i rpmforge-release-0.5.2-2.el5.rf.*.rpm
# yum search phpmyadmin
# yum install phpmyadmin
</pre>
<p>Setup the PHP Cookie</p>
<pre># vim /usr/share/phpmyadmin/config.inc.php
</pre>
<p>Add the Python Shared Libraries</p>
<pre># vim /etc/ld.so.conf.d/python2.7.conf
</pre>
<p>add the following line:</p>
<pre>/usr/local/python2.7/lib
</pre>
<p><span style="color: #ff0000;">// INSTALLING DJANGO</span></p>
<p>The django install docs can be found <a href="http://docs.djangoproject.com/en/1.3/topics/install/">here</a>.</p>
<pre># wget http://www.djangoproject.com/download/1.3/tarball/
# tar xzvf Django-1.3.tar.gz
# cd Django-1.3
# python setup.py install
$ python
&gt;&gt;&gt; import django
&gt;&gt;&gt;
</pre>
<p><span style="color: #ff0000;">// POINT APACHE AT DJANGO USING MOD_WSGI</span><br />
First, you need to tell apache which version of python to use so it doesn&#8217;t use the built in 2.4</p>
<pre># vim /etc/httpd/conf/httpd.conf
</pre>
<p>Add the following to the bottom of the file</p>
<pre>#Python Versioning Control for mod_wsgi
WSGIPythonHome /usr/local/python2.7
</pre>
<p>Then restart apache</p>
<pre># /etc/init.d/httpd restart
</pre>
<p>Now you can configure your virtual hosts in apache to point to a &#8216;django.wsgi&#8217; file thats specific to your django project.  Add the WSGIScriptAlias to your Virtual Host</p>
<pre>WSGIScriptAlias / /path/to/your/django/project/django_project_name/apache/django.wsgi
</pre>
<p>Add the &#8216;apache&#8217; directory to your django project, and copy the following into django.wsgi inside of the apache folder</p>
<pre>import os
import os.path
import sys

sys.path.append('/path/to/project/root')

os.environ['PYTHON_EGG_CACHE'] = '/path/to/a/directory/for/egg_cache'
os.environ['DJANGO_SETTINGS_MODULE'] = 'your_django_project_name.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>If you&#8217;ve made it this far, you should have a working django install.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/mediatemple-centos-5-5-ve-server-build/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Django &#8220;Through&#8221; relationship part 1: The Intermediary Model</title>
		<link>http://blog.hackedexistence.com/django-through-relationship-part-1-the-intermediary-model</link>
		<comments>http://blog.hackedexistence.com/django-through-relationship-part-1-the-intermediary-model#comments</comments>
		<pubDate>Thu, 24 Feb 2011 16:14:53 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Through Relationship]]></category>
		<category><![CDATA[Intermediary Model]]></category>
		<category><![CDATA[Through relationship]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=84</guid>
		<description><![CDATA[The Django Through relationship is, in my opinion, one of the most powerful things you can do with Django.  It allows you to define extra information about a database level relationship.  In this blog post, we will look at building &#8230; <a href="http://blog.hackedexistence.com/django-through-relationship-part-1-the-intermediary-model">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Django Through relationship is, in my opinion, one of the most powerful things you can do with Django.  It allows you to define extra information about a database level relationship.  In this blog post, we will look at building the Models for a &#8220;Through&#8221; relationship.</p>
<p>Example Context: Lets say you have a Person class and an Event class.  Now you want to have people be able to RSVP to Events.  In this case, the RSVP will be the Intermediary Model that links a Person to an Event and stores extra information about the link.  Here is what the classes would look like:</p>
<pre><span style="color: #ff7700; font-weight: bold;">class</span> Person<span style="color: black;">(</span>models.<span style="color: black;">Model</span><span style="color: black;">)</span>:
    name        = models.<span style="color: black;">CharField</span><span style="color: black;">(</span>max_length=<span style="color: #ff4500;">200</span><span style="color: black;">)</span>
    image       = models.<span style="color: black;">ImageField</span><span style="color: black;">(</span>upload_to=<span style="color: #483d8b;">"person_images"</span>, blank=<span style="color: #008000;">True</span><span style="color: black;">)</span>
    RSVPList    = models.<span style="color: black;">ManyToManyField</span><span style="color: black;">(</span>Event, through=<span style="color: #483d8b;">'RSVP'</span><span style="color: black;">)</span>

    <span style="color: #ff7700; font-weight: bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">(</span><span style="color: #008000;">self</span><span style="color: black;">)</span>:
        <span style="color: #ff7700; font-weight: bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">name</span>

<span style="color: #ff7700; font-weight: bold;">class</span> Event<span style="color: black;">(</span>models.<span style="color: black;">Model</span><span style="color: black;">)</span>:
    name        = models.<span style="color: black;">CharField</span><span style="color: black;">(</span>max_length=<span style="color: #ff4500;">200</span><span style="color: black;">)</span>
    date        = models.<span style="color: black;">DateTimeField</span><span style="color: black;">(</span><span style="color: black;">)</span>

    <span style="color: #ff7700; font-weight: bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">(</span><span style="color: #008000;">self</span><span style="color: black;">)</span>:
        <span style="color: #ff7700; font-weight: bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">name</span>

<span style="color: #ff7700; font-weight: bold;">class</span> RSVP<span style="color: black;">(</span>models.<span style="color: black;">Model</span><span style="color: black;">)</span>:
    person      = models.<span style="color: black;">ForeignKey</span><span style="color: black;">(</span>Person<span style="color: black;">)</span>
    event       = models.<span style="color: black;">ForeignKey</span><span style="color: black;">(</span>Event<span style="color: black;">)</span>
    attending   = models.<span style="color: black;">CharField</span><span style="color: black;">(</span>max_length=<span style="color: #ff4500;">20</span>, default=<span style="color: #483d8b;">'maybe'</span><span style="color: black;">)</span>

    <span style="color: #ff7700; font-weight: bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">(</span><span style="color: #008000;">self</span><span style="color: black;">)</span>:
        <span style="color: #ff7700; font-weight: bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">attending</span>
</pre>
<p>The Event class is autonomous, it doesn&#8217;t have a relationship to anything, and exists solely to hold information that defines events.</p>
<p>The Person class has a ManyToMany relationship to Event.  This allows a single Person to RSVP to multiple Events.  RSVPList will provide a list of all the Events a single Person object has RSVP&#8217;d to.  The magic starts with <span style="background-color: #c0c0c0;">through=&#8217;RSVP&#8217;</span>.  This tells django that the RSVP class will define extra information about the relationship between a single Person and a single Event.</p>
<p>The RSVP class has a single ForeignKey to a Person object and an Event object, defining a specific relationship between the two objects while enforcing that a single Person can only have one RSVP to any single Event.  In the example, we have added the &#8216;attending&#8217; attribute that will store extra information about the related Person and Event objects.  You can add as many extra attributes as you like that define extra information about the individual Person and Event.</p>
<p>The model defines a DB table that functions kind of like this:</p>

<a href="http://blog.hackedexistence.com/wp-content/gallery/django/img_0518.jpg" title="" class="shutterset_singlepic8" >
	<img class="ngg-singlepic" src="http://blog.hackedexistence.com/wp-content/gallery/cache/8__320x240_img_0518.jpg" alt="img_0518" title="img_0518" />
</a>

<p>Stay tuned, in Part 2 I will go over the view code that shows how to instantiate the RSVP object and attach it to a Person and Event.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/django-through-relationship-part-1-the-intermediary-model/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One Line &#8220;Tweet This&#8221; button for Twitter</title>
		<link>http://blog.hackedexistence.com/one-line-tweet-this-button-for-twitter</link>
		<comments>http://blog.hackedexistence.com/one-line-tweet-this-button-for-twitter#comments</comments>
		<pubDate>Wed, 09 Feb 2011 14:19:37 +0000</pubDate>
		<dc:creator>r3dfish</dc:creator>
				<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://blog.hackedexistence.com/?p=76</guid>
		<description><![CDATA[Since viewers of a page already had the ability to post that page to Facebook, I wanted to give them the ability to Tweet about it as well. Solution: Twitter provides http://twitter.com/share for you to call directly. By using the &#8230; <a href="http://blog.hackedexistence.com/one-line-tweet-this-button-for-twitter">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[
<a href="http://blog.hackedexistence.com/wp-content/gallery/twitter/tweet.png" title="" class="shutterset_singlepic7" >
	<img class="ngg-singlepic" src="http://blog.hackedexistence.com/wp-content/gallery/cache/7__320x240_tweet.png" alt="tweet" title="tweet" />
</a>

<p>Since viewers of a page already had the ability to post that page to Facebook, I wanted to give them the ability to Tweet about it as well.</p>
<p>Solution: Twitter provides http://twitter.com/share for you to call directly.  By using the share function, we can allow users to post to their twitter feed without anything more than a single line of code.  Twitter will handle authentication in the popup themselves.  I put this in a popup window using <span style="background-color: #c0c0c0;">window.open()</span> so that my website will stay open in the background.</p>
<pre><span style="color: #009900;">&lt;<a style="color: #000060;" href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">onclick</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">"window.open('http://twitter.com/share?text=Check%20out%20this%20Super%20Cool%20Website&amp;amp;url=http://cloudcreativegroup.com/{{ page.slug }}','C2G','menubar=no,width=550,height=450,toolbar=no'); return false;"</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">"#"</span>&gt;</span>Tweet this page<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a style="color: #000060;" href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span>
</pre>
<p>The <span style="background-color: #c0c0c0;">{{ page.slug }}</span> variable is a django variable that puts a link directly to the current page.  It can be removed to point to a static page, or generated with PHP if your site is written in PHP.  One of the cool things about the share function is that it automatically uses a URL shortener for you, so all you have to do is provide the full URL.</p>
<p>As always, you can replace the &#8220;Tweet this page&#8221; text with a cool Twitter image.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hackedexistence.com/one-line-tweet-this-button-for-twitter/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

