Development Posts

May 10, 2013

Understanding and Implementing Coding Standards

By in Development, SoftLayer, Tips and Tricks

Coding standards provide a consistent framework for development within a project and across projects in an organization. A dozen programmers can complete a simple project in a dozen different ways by using unique coding methodologies and styles, so I like to think of coding standards as the “rules of the road” for developers.

When you’re driving in a car, traffic is controlled by “standards” such as lanes, stoplights, yield signs and laws that set expectations around how you should drive. When you take a road trip to a different state, the stoplights might be hung horizontally instead of vertically or you’ll see subtle variations in signage, but because you’re familiar with the rules of the road, you’re comfortable with the mechanics of driving in this new place. Coding standards help control development traffic and provide the consistency programmers need to work comfortably with a team across projects. The problem with allowing developers to apply their own unique coding styles to a project is the same as allowing drivers to drive as they wish … Confusion about lane usage, safe passage through intersections and speed would result in collisions and bottlenecks.

Coding standards often seem restrictive or laborious when a development team starts considering their adoption, but they don’t have to be … They can be implemented methodically to improve the team’s efficiency and consistency over time, and they can be as simple as establishing that all instantiations of an object must be referenced with a variable name that begins with a capital letter:

$User = new User();

While that example may seem overly simplistic, it actually makes life a lot easier for all of the developers on a given project. Regardless of who created that variable, every other developer can see the difference between a variable that holds data and one that are instantiates an object. Think about the shapes of signs you encounter while driving … You know what a stop sign looks like without reading the word “STOP” on it, so when you see a red octagon (in the United States, at least), you know what to do when you approach it in your car. Seeing a capitalized variable name would tell us about its function.

The example I gave of capitalizing instantiated objects is just an example. When it comes to coding standards, the most effective rules your team can incorporate are the ones that make the most sense to you. While there are a few best practices in terms of formatting and commenting in code, the most important characteristics of coding standards for a given team is consistency and clarity.

So how do you go about creating a coding standard? Most developers dislike doing unnecessary work, so the easiest way to create a coding standard is to use an already-existing one. Take a look at any libraries or frameworks you are using in your current project. Do they use any coding standards? Are those coding standards something you can live with or use as a starting point? You are free to make any changes to it you wish in order to best facilitate your team’s needs, and you can even set how strict specific coding standards must be adhered to. Take for example left-hand comparisons:

if ( $a == 12 ) {} // right-hand comparison
if ( 12 == $a ) {} // left-hand comparison

Both of these statements are valid but one may be preferred over the other. Consider the following statements:

if ( $a = 12 ) {} // supposed to be a right-hand comparison but is now an assignment
if ( 12 = $a ) {} // supposed to be a left-hand comparison but is now an assignment

The first statement will now evaluate to true due to $a being assigned the value of 12 which will then cause the code within the if-statement to execute (which is not the desired result). The second statement will cause an error, therefore making it obvious a mistake in the code has occurred. Because our team couldn’t come to a consensus, we decided to allow both of these standards … Either of these two formats are acceptable and they’ll both pass code review, but they are the only two acceptable variants. Code that deviates from those two formats would fail code review and would not be allowed in the code base.

Coding standards play an important role in efficient development of a project when you have several programmers working on the same code. By adopting coding standards and following them, you’ll avoid a free-for-all in your code base, and you’ll be able to look at every line of code and know more about what that line is telling you than what the literal code is telling you … just like seeing a red octagon posted on the side of the road at an intersection.

-@SoftLayerDevs

April 29, 2013

Web Development – Installing mod_security with OWASP

By in Development, Tips and Tricks

You want to secure your web application, but you don’t know where to start. A number of open-source resources and modules exist, but that variety is more intimidating than it is liberating. If you’re going to take the time to implement application security, you don’t want to put your eggs in the wrong basket, so you wind up suffering from analysis paralysis as you compare all of the options. You want a powerful, flexible security solution that isn’t overly complex, so to save you the headache of making the decision, I’ll make it for you: Start with mod_security and OWASP.

ModSecurity (mod_security) is an open-source Apache module that acts as a web application firewall. It is used to help protect your server (and websites) from several methods of attack, most common being brute force. You can think of mod_security as an invisible layer that separates users and the content on your server, quietly monitoring HTTP traffic and other interactions. It’s easy to understand and simple to implement.

The challenge is that without some advanced configuration, mod_security isn’t very functional, and that advanced configuration can get complex pretty quickly. You need to determine and set additional rules so that mod_security knows how to respond when approached with a potential threat. That’s where Open Web Application Security Project (OWASP) comes in. You can think of the OWASP as an enhanced core ruleset that the mod_security module will follow to prevent attacks on your server.

The process of getting started with mod_security and OWASP might seem like a lot of work, but it’s actually quite simple. Let’s look at the installation and configuration process in a CentOS environment. First, we want to install the dependencies that mod_security needs:

## Install the GCC compiler and mod_security dependencies ##
$ sudo yum install gcc make
$ sudo yum install libxml2 libxml2-devel httpd-devel pcre-devel curl-devel

Now that we have the dependencies in place, let’s install mod_security. Unfortunately, there is no yum for mod_security because it is not a maintained package, so you’ll have to install it directly from the source:

## Get mod_security from its source ##
$ cd /usr/src
$ git clone https://github.com/SpiderLabs/ModSecurity.git

Now that we have mod_security on our server, we’ll install it:

## Install mod_security ##
$ cd ModSecurity
$ ./configure
$ make install

And we’ll copy over the default mod_security configuration file into the necessary Apache directory:

## Copy configuration file ##
$ cp modsecurity.conf-recommended /etc/httpd/conf.d/modsecurity.conf

We’ve got mod_security installed now, so we need to tell Apache about it … It’s no use having mod_security installed if our server doesn’t know it’s supposed to be using it:

## Apache configuration for mod_security ##
$ vi /etc/httpd/conf/httpd.conf

We’ll need to load our Apache config file to include our dependencies (BEFORE the mod_security module) and the mod_security file module itself:

## Load dependencies ##
LoadFile /usr/lib/libxml2.so
LoadFile /usr/lib/liblua5.1.so
## Load mod_security ##
LoadModule security2_module modules/mod_security2.so

We’ll save our configuration changes and restart Apache:

## Restart Apache! ##
$ sudo /etc/init.d/httpd restart

As I mentioned at the top of this post, our installation of mod_security is good, but we want to enhance our ruleset with the help of OWASP. If you’ve made it this far, you won’t have a problem following a similar process to install OWASP:

## OWASP ##
$ cd /etc/httpd/
$ git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git
$ mv owasp-modsecurity-crs modsecurity-crs

Just like with mod_security, we’ll set up our configuration file:

## OWASP configuration file ##
$ cd modsecurity-crs
$ cp modsecurity_crs_10_setup.conf.example modsecurity_crs10_config.conf

Now we have mod_security and the OWASP core ruleset ready to go! The last step we need to take is to update the Apache config file to set up our basic ruleset:

## Apache configuration ##
$ vi /etc/httpd/conf/httpd.conf

We’ll add an IfModule and point it to our new OWASP rule set at the end of the file:

<IfModule security2_module>
    Include modsecurity-crs/modsecurity_crs_10_config.conf
    Include modsecurity-crs/base_rules/*.conf
</IfModule>

And to complete the installation, we save the config file and restart Apache:

## Restart Apache! ##
$ sudo /etc/init.d/httpd restart

And we’ve got mod_security installed with the OWASP core ruleset! With this default installation, we’re leveraging the rules the OWASP open source community has come up with, and we have the flexibility to tweak and enhance those rules as our needs dictate. If you have any questions about this installation or you have any other technical blog topics you’d like to hear from us about, please let us know!

-Cassandra

April 16, 2013

iptables Tips and Tricks – Track Bandwidth with iptables

By in Development, Tips and Tricks

As I mentioned in my last post about CSF configuration in iptables, I’m working on a follow-up post about integrating CSF into cPanel, but I thought I’d inject a simple iptables use-case for bandwidth tracking. You probably think about iptables in terms of firewalls and security, but it also includes a great diagnostic tool for counting bandwidth for individual rules or set of rules. If you can block it, you can track it!

The best part about using iptables to track bandwidth is that the tracking is enabled by default. To see this feature in action, add the “-v” into the command:

[root@server ~]$ iptables -vnL
Chain INPUT (policy ACCEPT 2495 packets, 104K bytes)

The output includes counters for both the policies and the rules. To track the rules, you can create a new chain for tracking bandwidth:

[root@server ~]$ iptables -N tracking
[root@server ~]$ iptables -vnL
...
Chain tracking (0 references)
 pkts bytes target 	prot opt in 	out 	source           	destination

Then you need to set up new rules to match the traffic that you wish to track. In this scenario, let’s look at inbound http traffic on port 80:

[root@server ~]$ iptables -I INPUT -p tcp --dport 80 -j tracking
[root@server ~]$ iptables -vnL
Chain INPUT (policy ACCEPT 35111 packets, 1490K bytes)
 pkts bytes target 	prot opt in 	out 	source           	destination
    0 	  0 tracking    tcp  --  *  	*   	0.0.0.0/0        	0.0.0.0/0       	tcp dpt:80

Now let’s generate some traffic and check it again:

[root@server ~]$ iptables -vnL
Chain INPUT (policy ACCEPT 35216 packets, 1500K bytes)
 pkts bytes target 	prot opt in 	out 	source           	destination
  101  9013 tracking    tcp  --  *  	*   	0.0.0.0/0        	0.0.0.0/0       	tcp dpt:80

You can see the packet and byte transfer amounts to track the INPUT — traffic to a destination port on your server. If you want track the amount of data that the server is generating, you’d look for OUTPUT from the source port on your server:

See the OUTPUT Command and Learn More about Tracking Bandwidth with iptables »

April 12, 2013

Catalyst at SXSW 2013: Mentorship and Meaningfulness

By in Development, SoftLayer, Startup Series

In the Community Development group, our mission is simple: Create the industry’s most substantially helpful startup program that assists participants in a MEANINGFUL way. Meaningfulness is a subjective goal, but when it comes to fueling new businesses, numbers and statistics can’t tell the whole story. Sure, we could run Catalyst like some of the other startup programs in the infrastructure world and gauge our success off of the number of partners using the hosting credits we provide, but if we only focused on hosting credits, we’d be leaving a significant opportunity on the table.

SoftLayer is able to offer the entrepreneurial community so much more than cloud computing instances and powerful servers. As a startup ourselves not so long ago, our team knows all about the difficulties of being an entrepreneur, and now that we’re able to give back to the startup community, we want to share battle stories and lessons learned. Mentorship is one of the most valuable commodities for entrepreneurs and business founders, and SoftLayer’s mentors are in a unique position to provide feedback about everything from infrastructure planning to hiring your first employees to engaging with your board of advisors to negotiating better terms on a round of funding.

The Catalyst team engages in these kinds discussions with our clients every day, and we’ve had some pretty remarkable success. When we better understand a client’s business, we can provide better feedback and insight into the infrastructure that will help that business succeed. In other words, we build meaningful relationships with our Catalyst clients, and as a result, those clients are able to more efficiently leverage the hosting credits we provide them.

The distinction between Catalyst and other startup programs in the hosting industry has never been so apparent than after South by Southwest (SXSW) in Austin this year. I had the opportunity to meet with entrepreneurs, investors, and industry experts who have been thirsting for a program like Catalyst for years, and when they hear about what we’re doing, they know they’ve found their oasis. I had a chance to sit down with Paul Ford in the Catalyst Startup Lounge at SXSW to talk about the program and some of the insights and feedback we’d gotten at the show:

Paul was quick to point out that being a leader in the startup community has more impact when you provide the best technology and pair that with a team that can deliver for startups what they need: meaningful support.

Later, I had an impromptu coffee with one of the world’s largest, most prestigious Silicon Valley-based venture capital firms — probably THE most respected venture capital firm in the world, actually. As we chatted about the firm’s seed-funding practices, the investment partner told me, “There is no better insurance policy for an infrastructure company than what SoftLayer is doing to ensure success for its startup clients.” And I thought that was a pretty telling insight.

That simple sentence drove home the point that success in a program like Catalyst is not guaranteed by a particular technology, no matter how innovative or industry-leading that technology may be. Success comes from creating value BEYOND that technology, and when I sat down with George Karidis, he shared a few insights how the Catalyst vision came to be along with how the program has evolved to what it is today:

Catalyst is special. The relationships we build with entrepreneurs are meaningful. We’ve made commitments to have the talented brainpower within our own walls to be accessible to the community already. After SXSW, I knew I didn’t have to compare what we were doing from what other programs are doing because that would be like comparing apples and some other fruit that doesn’t do nearly as much for you as apples do.

I was told once on the campaign trail for President Clinton in ’96 that so long as you have a rock-solid strategy, you cannot be beaten if you continue to execute on that strategy. Execute, Execute, Execute. If you waiver and react to the competition, you’re dead in the water. With that in mind, we’re going to keep executing on our strategy of being available to our Catalyst clients and actively helping them solve their problems. The only question that remains is this:

How can we help you?

-@JoshuaKrammes

April 1, 2013

SoftLayer Mobile: Now a Universal iOS Application

By in Development, SoftLayer

Last month, we put SoftLayer Mobile HD out to pasture. That iPad-specific application performed amazingly, and we got a lot of great feedback from our customers, so we doubled-down on our efforts to support iPad users by merging SoftLayer Mobile HD functionality with our standard SoftLayer Mobile app to provide a singular, universal application for all iOS devices.

By merging our two iOS applications into a single, universal app, we can provide better feature parity, maintain coherent architecture and increase code reuse and maintainability because we’re only working with a single feature-rich binary app that provides a consistent user experience on the iPhone and the iPad at the same. Obviously, this meant we had to retool much of the legacy iPhone-specific SoftLayer Mobile app in order to provide the same device-specific functionality we had for the iPad in SoftLayer Mobile HD, but I was surprised at how straightforward that process ended up being. I thought I’d share a few of the resources iOS includes that simplify the process of creating a universal iOS application.

iOS supports development of universal applications via device-specific resource loading and device-specific runtime checks, and we leveraged those tools based on particular situations in our code base.

Device-specific resource loading allows iOS to choose the appropriate resource for the device being used. For example, if we have two different versions of an image called SoftLayerOnBlack.png to fit either an iPhone or an iPad, we simply call one SoftLayerOnBlack~iphone.png and call the other one SoftLayerOnBlack~ipad.png. With those two images in our application bundle, we let the system choose which image to use with a simple line of code:

UIImage* image = [UIImage imageNamed: @"SoftLayerOnBlack.png"];

In addition to device-specific resource loading, iOS also included device-specific runtime checks. With these runtime checks, we’re able to create conditional code paths depending on the underlying device type:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    // The device is an iPad running iOS 3.2 or later.
} else {
    // The device is an iPhone or iPod touch.
}

These building blocks allow for a great deal of flexibility when it comes to creating a universal iOS application. Both techniques enable simple support based on what device is running the application, but they’re used in subtly different ways. With those device-specific tools, developers are able to approach their universal applications in a couple of distinct ways:

Device-Dependent View Controller:
If we want users on the iPhone and iPad applications to have the same functionality but have the presentation tailored to their specific devices, we would create separate iPhone and iPad view controllers. For example, let’s look at how our Object Storage browser appears on the iPhone and the iPad in SoftLayer Mobile:

Object Storage - iPhoneObject Storage - iPad

We want to take advantage of the additional real estate the iPad provides, so at runtime, the appropriate view controller is be selected based on the devices’ UI context. The technique would look a little like this:

@implementation SLMenuController
...
 
- (void) navigateToStorageModule: (id) sender {
	UIViewController<SLApplicationModule> *storageModule = nil;
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        storageModule = [SLStorageModule_iPad storageModule];
    } else {
        storageModule = [SLStorageModule storageModule];
    }
    [self navigateToModule: storageModule];
}	
...
@end

“Universal” View Controller
In other situations, we didn’t need for the viewing experience to differ between the iPhone and the iPad, so we used a single view controller for all devices. We don’t compromise the user experience or presentation of data because the view controller either re-scales or reconfigures the layout at runtime based on screen size. Take a look at the “About” module on the iPhone and iPad:

About Module - iPhoneAbout Module - iPad

The code for the universal view controller of the “About” module looks something like this:

@implementation SLAboutModuleNavigationViewController
…
 
- (id) init {
    self = [super init];
    if (self) {
      _navigationHidden = YES;
		_navigationWidth = [[UIScreen mainScreen] bounds].size.width * 0.5;
    }
    return self;
}@end

There are plenty of other iOS features and tricks in the universal SoftLayer Mobile app. If you’ve got a SoftLayer account and an iOS devices, download the app to try it out and let us know what you think. If you were a SoftLayer Mobile HD user, do you notice any significant changes in the new app from the legacy app?

-Pawel

P.S. If you’re not on iOS but you still want some SoftLayer love on your mobile device, check out the other SoftLayer Mobile Apps on Android and Windows Phone.

March 22, 2013

Social Media for Brands: Monitor Twitter Search via Email

By in Development, Social Media, SoftLayer, Tips and Tricks

If you’re responsible for monitoring Twitter for conversations about your brand, you’re faced with a challenge: You need to know what people are saying about your brand at all times AND you don’t want to live your entire life in front of Twitter Search.

Over the years, a number of social media applications have been released specifically for brand managers and social media teams, but most of those applications (especially the free/inexpensive ones) differentiate themselves only by the quality of their analytics and how real-time their data is reported. If that’s what you need, you have plenty of fantastic options. Those differentiators don’t really help you if you want to take a more passive role in monitoring Twitter search … You still have to log into the application to see your fancy dashboards with all of the information. Why can’t the data come to you?

About three weeks ago, Hazzy stopped by my desk and asked if I’d help build a tool that uses the Twitter Search API to collect brand keywords mentions and send an email alert with those mentions in digest form every 30 minutes. The social media team had been using Twilert for these types of alerts since February 2012, but over the last few months, messages have been delayed due to issues connecting to Twitter search … It seems that the service is so popular that it hits Twitter’s limits on API calls. An email digest scheduled to be sent every thirty minutes ends up going out ten hours late, and ten hours is an eternity in social media time. We needed something a little more timely and reliable, so I got to work on a simple “Twitter Monitor” script to find all mentions of our keyword(s) on Twitter, email those results in a simple digest format, and repeat the process every 30 minutes when new mentions are found.

With Bear’s Python-Twitter library on GitHub, connecting to the Twitter API is a breeze. Why did we use Bear’s library in particular? Just look at his profile picture. Yeah … ’nuff said. So with that Python wrapper to the Twitter API in place, I just had to figure out how to use the tools Twitter provided to get the job done. For the most part, the process was very clear, and Twitter actually made querying the search service much easier than we expected. The Search API finds all mentions of whatever string of characters you designate, so instead of creating an elaborate Boolean search for “SoftLayer OR #SoftLayer OR @SoftLayer …” or any number of combinations of arbitrary strings, we could simply search for “SoftLayer” and have all of those results included. If you want to see only @ replies or hashtags, you can limit your search to those alone, but because “SoftLayer” isn’t a word that gets thrown around much without referencing us, we wanted to see every instance. This is the code we ended up working with for the search functionality:

def status_by_search(search):
    statuses = api.GetSearch(term=search)
    results = filter(lambda x: x.id > get_log_value(), statuses)
    returns = []
    if len(results) > 0:
        for result in results:
            returns.append(format_status(result))
 
        new_tweets(results)
        return returns, len(returns)
    else:
        exit()

If you walk through the script, you’ll notice that we want to return only unseen Tweets to our email recipients. Shortly after got the Twitter Monitor up and running, we noticed how easy it would be to get spammed with the same messages every time the script ran, so we had to filter our results accordingly. Twitter’s API allows you to request tweets with a Tweet ID greater than one that you specify, however when I tried designating that “oldest” Tweet ID, we had mixed results … Whether due to my ignorance or a fault in the implementation, we were getting fewer results than we should. Tweet IDs are unique and numerically sequential, so they can be relied upon as much as datetime (and far easier to boot), so I decided to use the highest Tweet ID from each batch of processed messages to filter the next set of results. The script stores that Tweet ID and uses a little bit of logic to determine which Tweets are newer than the last Tweet reported.

def new_tweets(results):
    if get_log_value() < max(result.id for result in results):
        set_log_value(max(result.id for result in results))
        return True
 
 
def get_log_value():
    with open('tweet.id', 'r') as f:
        return int(f.read())
 
 
def set_log_value(messageId):
    with open('tweet.id', 'w+') as f:
        f.write(str(messageId))

Once we culled out our new Tweets, we needed our script to email those results to our social media team. Luckily, we didn’t have to reinvent the wheel here, and we added a few lines that enabled us to send an HTML-formatted email over any SMTP server. One of the downsides of the script is that login credentials for your SMTP server are stored in plaintext, so if you can come up with another alternative that adds a layer of security to those credentials (or lets you send with different kinds of credentials) we’d love for you to share it.

From that point, we could run the script manually from the server (or a laptop for that matter), and an email digest would be sent with new Tweets. Because we wanted to automate that process, I added a cron job that would run the script at the desired interval. As a bonus, if the script doesn’t find any new Tweets since the last time it was run, it doesn’t send an email, so you won’t get spammed by “0 Results” messages overnight.

The script has been in action for a couple of weeks now, and it has gotten our social media team’s seal of approval. We’ve added a few features here and there (like adding the number of Tweets in an email to the email’s subject line), and I’ve enlisted the help of Kevin Landreth to clean up the code a little. Now, we’re ready to share the SoftLayer Twitter Monitor script with the world via GitHub!

SoftLayer Twitter Monitor on GitHub

The script should work well right out of the box in any Python environment with the required libraries after a few simple configuration changes:

  • Get your Twitter Customer Secret, Access Token and Access Secret from https://dev.twitter.com/
  • Copy/paste that information where noted in the script.
  • Update your search term(s).
  • Enter your mailserver address and port.
  • Enter your email account credentials if you aren’t working with an open relay.
  • Set the self.from_ and self.to values to your preference.
  • Ensure all of the Python requirements are met.
  • Configure a cron job to run the script your desired interval. For example, if you want to send emails every 10 minutes: */10 * * * * <path to python> <path to script> 2>&1 /dev/null

As soon as you add your information, you should be in business. You’ll have an in-house Twitter Monitor that delivers a simple email digest of your new Twitter mentions at whatever interval you specify!

Like any good open source project, we want the community’s feedback on how it can be improved or other features we could incorporate. This script uses the Search API, but we’re also starting to play around with the Stream API and SoftLayer Message Queue to make some even cooler tools to automate brand monitoring on Twitter.

If you end up using the script and liking it, send SoftLayer a shout-out via Twitter and share it with your friends!

-@SoftLayerDevs

March 19, 2013

iptables Tips and Tricks: CSF Configuration

By in Development, Tips and Tricks

In our last “iptables Tips and Tricks” installment, we talked about Advanced Policy Firewall (APF) configuration, so it should come as no surprise that in this installment, we’re turning our attention to ConfigServer Security & Firewall (CSF). Before we get started, you should probably run through the list of warnings I include at the top of the APF blog post and make sure you have your Band-Aid ready in case you need it.

To get the ball rolling, we need to download CSF and install it on our server. In this post, we’re working with a CentOS 6.0 32-bit server, so our (root) terminal commands would look like this to download and install CSF:

$ wget http://www.configserver.com/free/csf.tgz #Download CSF using wget.
$ tar zxvf csf.tgz #Unpack it.
$ yum install perl-libwww-perl #Make sure perl modules are installed ...
$ yum install perl-Time-HiRes  #Otherwise it will generate an error.
$ cd csf
$ ./install.sh #Install CSF.
 
#MAKE SURE YOU HAVE YOUR BAND-AID READY
 
$ /etc/init.d/csf start #Start CSF. (Note: You can also use '$ service csf start')

Once you start CSF, you can see a list of the default rules that load at startup. CSF defaults to a DROP policy:

$ iptables -nL | grep policy
Chain INPUT (policy DROP)
Chain FORWARD (policy DROP)
Chain OUTPUT (policy DROP)

Don’t ever run “iptables -F” unless you want to lock yourself out. In fact, you might want to add “This server is running CSF – do not run ‘iptables -F’” to your /etc/motd, just as a reminder/warning to others.

CSF loads on startup by default. This means that if you get locked out, a simple reboot probably won’t fix the problem. Runlevels 2, 3, 4, and 5 are all on:

$ chkconfig --list | grep csf
csf             0:off   1:off   2:on    3:on    4:on    5:on    6:off

Some features of CSF will not work unless you have certain iptables modules installed. I believe they are installed by default in CentOS, but if you custom-built your iptables, they might not all be installed. Run this script to see if all modules are installed:

$ /etc/csf/csftest.pl
Testing ip_tables/iptable_filter...OK
Testing ipt_LOG...OK
Testing ipt_multiport/xt_multiport...OK
Testing ipt_REJECT...OK
Testing ipt_state/xt_state...OK
Testing ipt_limit/xt_limit...OK
Testing ipt_recent...OK
Testing xt_connlimit...OK
Testing ipt_owner/xt_owner...OK
Testing iptable_nat/ipt_REDIRECT...OK
Testing iptable_nat/ipt_DNAT...OK
 
RESULT: csf should function on this server

As I mentioned, this is the default iptables installation on a minimal CentOS 6.0 image, so chances are good that these modules are already installed on your system. It never hurts to check, though.

The CSF Configuration File

The primary CSF configuration is stored in the well-documented /etc/csf/csf.conf file. CSF is extremely configurable, so there are a lot of options to read over. Let’s take a look over some of the more important features:

Learn about CSF configuration options, Allow and Deny Lists, and the CSF Command Line Tool »

March 7, 2013

Script Clip: HTML5 Audio Player with jQuery Controls

By in Development, Tips and Tricks

HTML5 and jQuery provide mind-blowing functionality. Projects that would have taken hours of development and hundreds of lines of code a few years ago can now be completed in about the time it’ll take you to read this paragraph. If you wanted to add your own audio player on a web page in the past, what would it have involved? Complicated elements? Flash (*shudders*)? It was so complicated that most developers just linked to the audio file, and the user just downloaded the file to play it locally. With HTML5, an embedded, cross-browser audio player can be added to a page with five lines of code, and if you want to get really fancy, you can easily use jQuery to add some custom controls.

If you’ve read any of my previous blogs, you know that I love when I find little code snippets that make life as a web developer easier. My go-to tools in that pursuit are HTML5 and jQuery, so when I came across this audio player, I knew I had to share. There are some great jQuery plugins to play music files on a web page, but they can be major overkill for a simple application if you have to include comprehensive controls and themes. Sometimes you just want something simple without all of that overhead:

Oooh… Ahhh…

That song — Pop Bounce by SoftLayer’s very own Chris Interrante — is written in five simple lines of HTML5 code:

<audio style="width:550px; margin: 0 auto; display:block;" controls>
  <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.ogg" type="audio/ogg">
  <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>

If IE 9+, Chrome 6+, Firefox 3.6+, Safari 5+ and Opera 10+ would all agree on supported file formats for the <audio> tag, the code snippet would be even smaller. I completely geek out over it every time I look at it and remember the days of yore. As you can see, the HTML5 application has some simple default controls: Play, Pause, Scan to Time, etc. As a developers, I couldn’t help but look for a to spice it up a little … What if we want to fire an event when the user plays, pauses, stops or takes any other action with the audio file? jQuery!

Make sure your jQuery include is in the <head> of your page:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

Now let’s use jQuery to script separate “Play” and “Pause” links … And let’s have those links fire off an alert when they are pressed:

$(document).ready(function(){
  $("#play-button").click(function(){
   $("#audioplayer")[0].play();
   alert('You have played the audio file!');
  })    
 
  $("#pause-button").click(function(){
   $("#audioplayer")[0].pause();
   alert('You have paused the audio file!');
  })    
})

With that script in the <head> as well, the HTML on our page will look like this:

<div class=:"audioplayer">
  <audio id="audioplayer" name="audioplayer" controls loop>
    <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.ogg" type="audio/ogg">
    <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
  </audio>
 
  <a id="play-button" href="#">Play!</a>
  <a id="pause-button" href="#">Pause!</a>
</div>

Want proof that it works that simply? Boom.

You can theme it any way you like; you can add icons instead of the text … The world is your oyster. The bonus is that you’re using one of the lightest media players on the Internet! If you decide to get brave (or just more awesome), you can explore additional features. You’re using jQuery, so your possibilities are nearly limitless. If you want to implement a “Stop” feature (which returns the audio back to the beginning when “Stop” is pressed), you can get creative:

$("#stop-button").click(function(){
    $("#audioplayer")[0].currentTime = 0; // return the audio file back to the beginning
}

If you want to include some volume controls, those can be added in a snap as well:

$("#volumeUp").click(function(){
    $("#audioplayer")[0].volume +=0.1;
}
 
$("#volumeDown").click(function(){
    $("#audioplayer")[0].volume -=0.1;
}

Try it out and let me know what you think. Your homework is to come up with some unique audio player functionality and share it here!

-Cassandra

February 20, 2013

Global Game Jam: Build a Video Game in 48 Hours

By in Development, International

You’re a conflicted zombie that yearns to be human again. Now you’ve got to dodge grandma and babies in an 8-bit side-scroller. Now you’re Vimberly Koll, and you have to stop Poseidon from raining down on the Global Game Jam. At the end of Global Game Jam Vancouver, teams of developers, 3D artists, level designers and sound engineers conceptualized and created these games (along with a number of others) in less than 48 hours. Building a game in a weekend is no small task, so only the best and brightest game developers in the world converge on over 300 sites in 63 countries to show off their skills.

For the fifth annual Global Game Jam, more than 16,000 participants committed a weekend to learning from and collaborating with their peers in a worldwide game development hackathon. I was lucky enough to get to sit in on the action in Vancouver, and I thought I’d give you a glimpse into how participants make game development magic happen in such a short period of time.

Vancouver Global Game Jam

Day 1 (Friday Night): The Brainstorm
More than 260 participants poured into an open study area of the Life Sciences building at the Univerity of British Columbia to build the next best distraction … er, video game. The event kicked off with a keynote from Brian Proviciano, a game development prodigy, who shared his history and offered sage advice for those interested in the industry. Following a comical 20-second idea pitch session, the caffeine began to flow and the brainstorm commenced.

Inspiration could come from anywhere, and a perfect example is the “Poseidon” game I mentioned above: GGJVancouver organizer Kimberly Voll had sprinklers rain on her office a few days prior to the event, so someone decided to make a game out of that situation. This year, the Global Game Jam introduced an interesting twist that they called “diversifiers.” Diversifiers are side-challenges for extra credit, and two of my favorites were “Atari Age” — the game has to be smaller than 4kb — and “May the (Web) Force be With You” — the game has to run in a browser.

Fast-forward two hours, and as you look around, you see storyboards and scripts being written, characters being born, and a few intrepid developers starting to experiment with APIs, game engines , and external controllers to find some additional flair for their final products. You wouldn’t expect a game made in 48 hours to incorporate an iOS Eye Tracking API or the Leap Motion gesture controller, but these developers are ambitious!

As the concepts are finalized, team members rotate in and out for sleep, and some even go home to get some rest — a good idea on the first night since everyone usually pulls an all-nighter on Saturday.

Vancouver Global Game Jam

Day 2 (Saturday): Laying the Foundation
It was cool to walk the aisles and peer over peoples’ shoulders as musical scores, wrangled code and character models were coming together. However, the scene wasn’t all smiles and hugs; a few groups were wrestling quirky bugs and integration issues, and in some cases, they ended up having to completely reboot their approach. Day 2 set the course for all of the teams. A few teams disbanded due to disagreements or unfixable bugs, and some developers peeled off from their teams to follow an untamed passion. In the Global Game Jam, there are no rules … only games.

Vancouver Global Game Jam

Day 3 (Sunday): Sleep, What’s That?
By Day 3, the building starts feeling like a college dorm during finals week when everyone is staying up all night to study or finish their comp-sci assignments (I know it wasn’t just me…). Running on various vehicles of caffeine, teams worked heads-down all day to meet their 3pm deadline. Sighs of relief and high fives were exchanged when the games were submitted, and the event concluded with a pizza party and demo session where everyone could see and share the fruits of their labor.

Vancouver Global Game Jam

As I left the conference, teams were given the opportunity to showcase their games on the big screen to a chorus of laughter and applause. It was an awesome experience, and I’m glad SoftLayer sponsored it so that I could attend, take it all in and meet a ton of outstanding up-and-coming game developers. If you’re into making games (or you’ve thought about it), check out the Global Game Jam one of these years.

Just don’t forget to bring deodorant … for your neighbor’s sake.

-@andy_mui

Photo Credit Shout-Outs: Alex Larente, Ligia Brosch, Naz Madani. Great shots!

February 14, 2013

Tips and Tricks – Building a jQuery Plugin (Part 2)

By in Development, Tips and Tricks

jQuery plugins don’t have to be complicated to create. If you’ve stumbled upon this blog in pursuit of a guide to show you how to make a jQuery plugin, you might not believe me … It seems like there’s a chasm between the “haves” of jQuery plugin developers and the “have nots” of future jQuery developers, and there aren’t very many bridges to get from one side to the other. In Part 1 of our “Building a jQuery Plugin” series, we broke down how to build the basic structure of a plugin, and in this installment, we’ll be adding some usable functionality to our plugin.

Let’s start with the jQuery code block we created in Part 1:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "This is", // this will be the default value of this var
                anotherVar: "our awesome",
                coolVar: "plugin!",
            };
            var options = $.extend(defaults, options);
            this.each(function() {
                ourString = myVar + " " + anotherVar + " " + coolVar;
            });
            return ourString;
    };
}) (jQuery);

We want our plugin to do a little more than return, “This is our awesome plugin!” so let’s come up with some functionality to build. For this exercise, let’s create a simple plugin that allows truncates a blob of text to a specified length while providing the user an option show/hide the rest of the text. Since the most common character length limitation on the Internet these days is Twitter’s 140 characters, we’ll use that mark in our example.

Taking what we know about the basic jQuery plugin structure, let’s create the foundation for our new plugin — slPlugin2:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140,
            moreLink: "read more",
            lessLink: "collapse",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
    };
})(jQuery);

As you can see, we’ve established four default variables:

  • length: The length of the paragraph we want before we truncate the rest.
  • moreLength: What we append to the paragraph when it is truncated. This will be the link the user clicks to expand the rest of the text.
  • lessLink: What we append to the paragraph when it is expanded. This will be the link the user clicks to collapse the rest of the text.
  • trailingText: The typical ellipses to append to the truncation.

In our jQuery plugin example from Part 1, we started our function with this.each(function() {, and for this example, we’re going to add a return for this to maintain chainability. By doing so, we’re able to manipulate the segment with methods. For example, if we started our function with this.each(function() {, we’d call it with this line:

$('#ourParagraph').slPlugin2();

If we start the function with return this.each(function() {, we have the freedom to add further manipulation:

$('#ourParagraph').slPlugin2().bind();

With such a simple change, we’re able to add method calls to make one massive dynamic function.

Let’s flesh out the actual function a little more. We’ll add a substantial bit of code in this step, but you should be able to follow along with the changes via the comments:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140, 
            moreLink: "read more",
            lessLink: "collapse",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
 
        // return this keyword for chainability
        return this.each(function() {
            var ourText = $(this);  // the element we want to manipulate
            var ourHtml = ourText.html(); //get the contents of ourText!
            // let's check if the contents are longer than we want
            if (ourHtml.length > options.length) {
                var truncSpot = ourHtml.indexOf(' ', options.length); // the location of the first space (so we don't truncate mid-word) where we will end our truncation.
 
   // make sure to ignore the first space IF the text starts with a space
   if (truncSpot != -1){
       // the part of the text that will not be truncated, starting from the beginning
       var firstText = ourHtml.substring(0, truncSpot);
 
       // the part of the text that will be truncated, minus the trailing space
       var secondText = ourHtml.substring(truncSpot, ourHtml.legnth -1);
                }
            }
        })
    };
})(jQuery);

Are you still with us? I know it seems like a lot to take in, but each piece is very straightforward. The firstText is the chunk of text that will be shown: The first 140 characters (or whatever length you define). The secondText is what will be truncated. We have two blobs of text, and now we need to make them work together:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140, 
            moreLink: "read more",
            lessLink: "read less",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
 
        // return this keyword for chainability
        return this.each(function() {
            var ourText = $(this);  // the element we want to manipulate
            var ourHtml = ourText.html(); //get the contents of ourText!
            // let's check if the contents are longer than we want
            if (ourHtml.length > options.length) {
                var truncSpot = ourHtml.indexOf(' ', options.length); // the location of the first space (so we don't truncate mid-word) where we will end our truncation.
 
   // make sure to ignore the first space IF the text starts with a space
   if (truncSpot != -1){
       // the part of the text that will not be truncated, starting from the beginning
       var firstText = ourHtml.substring(0, truncSpot);
 
       // the part of the text that will be truncated, minus the trailing space
       var secondText = ourHtml.substring(truncSpot, ourHtml.legnth -1);
 
       // perform our truncation on our container ourText, which is technically more of a "rewrite" of our paragraph, to our liking so we can modify how we please. It's basically saying: display the first blob then add our trailing text, then add our truncated part wrapped in span tags (to further modify)
       ourText.html(firstText + options.trailingText + '<span class="slPlugin2">' + secondText + '</span>');
 
       // but wait! The secondText isn't supposed to show until the user clicks "read more", right? Right! Hide it using the span tags we wrapped it in above.
       ourText.find('.slPlugin2').css("display", "none");
                }
            }
        })
    };
})(jQuery);

Our function now truncates text to the specified length, and we can call it from our page simply:

<script src="jquery.min.js"></script>
<script src="jquery.slPlugin2.js"></script>
<script type="text/javascript">
$(document).ready(function() {  
    $('#slText').slPlugin2();  
});
</script>

Out of all the ways to truncate text via jQuery, this has to be my favorite. It’s feature-rich while still being fairly easy to understand. As you might have noticed, we haven’t touched on the “read more” and “read less” links or the expanding/collapsing animations yet, but we’ll be covering those in Part 3 of this series. Between now and when Part 3 is published, I challenge you to think up how you’d add those features to this plugin as homework.

-Cassandra