Bloom Email Optin Plugin

Using WordPress Child Themes

There are tons of quality WordPress themes out there. You found the perfect one for your site, almost. Everything looks good at first then you decide you need a few little tweaks to the theme code to really fit your needs. Stop modifying the theme directly. Start using WordPress Child Themes. If you aren’t familiar with child themes it’s time to learn about them.

What are WordPress Child Themes?

Child themes in WordPress allow you to inherit the code from a theme template. You can override basically anything you would (PHP, HTML, CSS, JavaScript) as if you were modifying the parent theme directly. However, the benefit of using child themes is that it keeps the parent theme untouched. If you were to modify the theme directly and then update that theme using WordPress’ update feature you would lose all of your customizations. With child themes you won’t lose any of your changes when you update the parent theme as your changes are in their own directory. Plus child themes are so easy there really isn’t an excuse not to use them.

How you can get started with WordPress Child Themes

If you’ve ever tried to create a WordPress theme on your own you already know most of what it takes to create a child theme. If you haven’t dug into creating your own theme yet don’t worry. It’s very simple to create a child theme but it does require some knowledge of HTML, CSS, and PHP. Creating a child theme is a great way to learn about WordPress if you need to brush up on some of those skills.

I’m going to show you how to create a child theme based on the new WordPress default theme Twenty Fifteen. First navigate to the theme directory of you install which is probably something like /wp-content/themes/

wordpress child themes 01

 

Next create a new folder for your child theme. It’s not required to use this format but I general name the folder {theme name}-child. So in this case the folder will be called twentyfifteen-child.


wordpress child theme 02

There are two requirements for child themes. The first is a style.css file and the second is a functions.php file. Next open your favorite text editor (I’ve been using Atom lately). We’re going to create the style.css. You can find an example of this file on the WordPress codex.

Paste the following into your text editor. You should fill in all of the fields but the most important fields are Theme Name (the name you will see in the WordPress admin) and the template section. The template tells WordPress where to go to get the original theme’s file so you want to make sure this name matches the parent theme. I did this for my personal site and had problems with the name’s not matching so be sure to check it.

/*
 Theme Name:   Twenty Fifteen Child
 Theme URI:    http://example.com/twenty-fifteen-child/
 Description:  Twenty Fifteen Child Theme
 Author:       John Ward
 Author URI:   http://example.com
 Template:     twentyfifteen
 Version:      1.0.0
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
 Text Domain:  twenty-fifteen-child
*/

You can add your name and update the urls then save this inside the twentyfifteen-child directory as style.css. Then you’ll want to create another new file in your editor. Paste the following code:

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );

}

You can save this file in the twentyfifteen-child directory as functions.php. This is all the is technically necessary. However, the WordPress Codex also mentions that you may want to make sure the parent theme is loaded first by making the child them a dependent in the functions.php file. To do that you would updated the functions.php file to look like this:

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
    wp_enqueue_style( 'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array('parent-style')
    );
}

Now your new child theme directory should look like this

wordpress child theme 03

Now you can enable the theme in the WordPress -> Appearance section by clicking the activate button on the new child theme.

wordpress child theme 04

 

Once activate your child theme behaves like any other WordPress theme. You can change the look using the built in customizer. You can add and edit widget. Now you can override any of the core files. For example if I wanted to change the background of this white sidebar to a different color.


wordpress child theme 05

 

If I wanted to make it red I would use the browser inspection tool to find out what css I want to override. Keep in mind you can actually change this color using the built in customizer but I’m doing it using CSS as an example.

Using the inspector I see that the div I want to override has an ID of #sidebar

wordpress child theme 06

Then I would open the style.css in my child theme and add a new rule below the comments to make this red.

/*
 Theme Name:   Twenty Fifteen Child
 Theme URI:    http://example.com/twenty-fifteen-child/
 Description:  Twenty Fifteen Child Theme
 Author:       John Ward
 Author URI:   http://example.com
 Template:     twentyfifteen
 Version:      1.0.0
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
 Text Domain:  twenty-fifteen-child
*/
#sidebar{ background:red;}

Which would then give you

wordpress child theme 07

 

As you can see the sidebar is now red because we updated our style.css

What else can you do with WordPress Child Themes?

Now that I’ve showed you how to make a simple CSS change you may be wonder what else you can do. Well you can override any of the file from the original theme. Take a look in the original theme directory.

wordpress child theme 08

You can copy any of those files over to your child theme directory and then start hacking away at the code. Want to do something special in the author bio simply copy the author-bio.php file. Want to change the footer? Copy the footer.php file to your child directory and make your change.

What can go wrong?

The only thing that I’ve seen go wrong is that you can update the parent theme and then things can end up breaking because you have an old version of a file that was updated in your child theme. To fix this you have to compare the new file with the one in your child theme and update accordingly. That’s still better than modifying the original theme because in that case you would lose all your changes.

Let me know if this post helped you out or if you have any other questions. If this post did benefit you please share.

How to parse a CSV file using ruby

Here’s a simple tip on how to parse a comma separated value or CSV file using ruby. Ruby has a standard library available that makes this task very simple. All we need to do is open a CSV file, read it, and parse it using the CSV parser that comes with ruby. Let’s say we want to import a CSV file that contains the fields: name,age,sex.

name,age,sex
john,28,m
julie,19,f
adrienne,42,f
rob,16,m

First off I create the csv file above and saved it as test.csv. Next we need to get started with ruby.

In order to parse this CSV I am going to use the build in CSV library, so we need to require the CSV library.

require 'csv'

Next we need to read the file and store it to a variable

require 'csv'

csv_text = File.read('test.csv')

Now we’re going to tell the CSV library to parse the file, and that the file has headers. When we specify that headers exist, the parse will use the first row as the names for each value.

require 'csv'

csv_text = File.read('test.csv')
csv = CSV.parse(csv_text, :headers => true)

Now, we just need to loop through each record and perform whatever task it is we want to do with the data. In this case I just output to the terminal window using puts.

require 'csv'

csv_text = File.read('test.csv')
csv = CSV.parse(csv_text, :headers => true)

csv.each do |row|										
	puts "Name: #{row['name']} - Age: #{row['age']} -  Sex: #{row['sex']}"
end

As you can see above when we run: csv.each do |row|, that sets the variable row to an array of all the values in the row. It also will use the names from the first column. So to get a certain field we just need to use row[‘fieldname’].

When you run this in the terminal (ruby csv.rb) you should see something like this:

jward-laptop:Desktop jward$ ruby csv.rb
Name: john - Age: 28 -  Sex: m
Name: julie - Age: 19 -  Sex: f
Name: adrienne - Age: 42 -  Sex: f
Name: rob - Age: 16 -  Sex: m

How to Start Website

The internet is ingrained in most of our day to day lives at this point. It’s hard for me to imagine a day that I do not touch the internet in some way. While most people utilize the internet every day, they do not know how to start their own website. This guide is aimed at teaching beginners the basics of how to make a .com website, or really, any website regardless of the extension. If you want to learn how to make a .com website, be prepared for some reading!

I am going to cover several somewhat complex ideas today. Don’t be intimidated if you are not familiar with the concepts, I will do my best to explain these ideas in words that someone new to the web can understand. As always, if you have any questions feel free to post in the comments or even contact us. We do our best to respond to every question, but sometimes we can get overwhelmed.

Today we will cover the basics of creating a website including:

  1. Domain Name Registration
  2. Website Hosting Options
  3. Web Development and Markup
  4. Content Management Systems
  5. How to Get Visitors
  6. Making Money on Your Website

The Domain Name System and Domain Registration

The Domain Name System, or DNS, is a system of assigning human readable names to website addresses. When you visit ebay.com, you are actually being directed to an ebay server via the DNS system. The ebay website itself is actually location on the internet at the IP adress of 66.211.160.88. Think of IP Adresses as the location of your website on the internet. An IP adress works somewhat similar to the way a postal adress works. It notifies the carrier where you are located. To run a website you do not need to know the complex workings of DNS or IP adresses, but it is important to know of them.

Now imagine trying to remember a group of numbers like 66.211.160.88 for every website you would ever want to visit. This is originally how we accessed a website until the DNS system was create. The DNS system contains a record that will associate the name of your website with the IP adress of your website. That way any human can remember the location of your website and type it in.

You may wonder why I this is important to you? Well, the only thing that is really important as a website owner is that you have a registered domain name for your site. You’ll need to pick a name for your website and a top level domain (TLD). There are several available top level domains available for use. Some are reserved for special purposes such as a country code (.us, .uk, .asia) while others are for more general use (.com). The most popular three extensions that most people are familiar with are .com, .net, and .org with .com being the most common by far. The .com domain is actually intended for commercial websites, and most recently the United States has claimed the it was only intended for US based companies (I’m not going to go to far into detail). Anyone can register a .com, .org (originally intended for non-profit organizations), and .net (originally intended for networks) domain name from a domain name registrar. You should look into what other domain names are available. This is especially true if you do not live within the US and/or want to target countries outside of the United States. For more information on the purpose of top-level domains names take a look at this article.

Now that you have a basic understanding of what Domain Names are you need to decide what you want your domain to be. If you intend to register a .com domain be prepared to spend sometime finding a name that will not be registered already. Since .com is the most popular domain name, many of the website are already taken. Some .com domain names can even sell for millions of dollars if they have a good one word domain name. You can use the tools available at the domain name registrar that you choose to find a good domain name.

A domain name registar is the company that will sell you whatever-site-you-want.com. You will be paying yearly to reserve the name for your website. Normally, this should cost some where between $10-20 per year, but can vary depending on the TLD. Some unscrupulous companies will send out mail saying that you need to renew your domain name for $100 a year. They prey on the secretaries or accounts payable clerks who will send out checks like this. This is just something to be aware of. Never pay anyone except for the registrar that you initially choose to register your domain name with.

Two domain name registrars that I have used are namecheap.com and godaddy.com. Godaddy is probably the most popular registrar and is pretty good for beginners as they offer a lot of ad on features. However, most of these features are not needed to run a website. I prefer namecheap because they do not try to up sell you on every product they offer, their support is awesome, and their interface is easy to use. All you need is a domain name and a web host to get up and running.

What is Web Hosting?

Once you’ve decided on a domain name for your website, you will need a place to keep your files. While you could technically keep those on any computer connect to the internet, it’s generally better to have a server designed for this specific purpose. That is where a web host comes in. They have thousands of servers all connected to the web just to host files for various websites. Hosted web servers are designed to respond to web requests and handle the traffic that a website can receive.

There are a few options you will need to consider when deciding on a web host. I’ll touch on each topic later:

  • What type of server will you need (shared, VPS, dedicated server)?
  • Will you need managed support?
  • What operating system you want to use on your server (Windows, Linux)
  • Will you need a control panel (cPanel, etc)?

Shared Hosting

First of all you need to decide what type of hosting you need. Web hosts offer several different server configurations for different types of customers. If you are just planning to run a website as a hobby, or if you are just starting a website you may want to go with share hosting. A share host is one physical web server that hosts multiple websites. Your website would be on the same server as up to hundreds of other websites, however you will still be abled to have your own domain name and manage your website to an extent.

In general, shared hosting doesn’t allow much flexibility when it comes to configuration. This done so that no one person can crash the server for all of the other websites. Like I said, shared hosting is good for hobby sites and low traffic sites. If you have big goals you may want to avoid share web hosting. The downsides are that you don’t have much control over the server and these server can’t handle large amount of traffic. If you generate too much traffic your web host will ask you to upgrade to a better server. Take it from someone who has crashed his shared of share hosting servers: if you have big goals you may want to pass on shared hosting and go for a virtual private server. The main benefit to share hosting is that is can be cheap. You can get shared hosting for about $4-12 per month.

Virtual Private Servers

Also known as a VPS, the virtual private server bridges the gap between share hosting and a full blown dedicated server. These physical servers with many virtual instances of server on them. These virtual instances cannot interfere with each other as they are contained with in their own virtual machine. The benefit to this is that you can have a the control over the server as if it was your own physical machine, but at a much cheaper costs.

Dedicated Servers

The most powerful servers you can buy are dedicated servers. These are physical machines in a datacenter that only run your website. You can usually run several of your own websites on your dedicated server. Dedicated servers can handle many more tasks as you will be able to utilize all of the hard disk space, memory(RAM), and processor cycles. These servers can be configured from a wide range of specification. A host can even setup multiple server in what is know as a cluster. If you get to the point that you need more than a single dedicated server then it is probably time to hire a server administrator to handle this for you. For most needs, a dedicated server is sufficient.

Reseller Hosting

This options provides you with all the benefits of a dedicated server, but also allows you to resell hosting to other websites. Unless you want to get in to the hosting reseller business this option is probably not necessary, but you could choose this if you plan to host a lot of your own domains.

Hosting on the Cloud

Another new option that is appearing is cloud hosting. This basically means that your data is host in a cluster of machines that the host will provide. For example amazon has a cloud hosting service known as s3. They host many sites all on there server farm which resides in “the cloud”. One thing that cloud based hosting can provide is an easy way to scale your server needs as your site grows. For your first website you probably want to stick with a shared or VPS solution, but keep in mind that the cloud option exists.

Managed Hosting

Managed servers are when a hosting company provides support for your server. This basically means you are leasing a server administrator in your hosting plan. Usually managed servers cost a little bit more than non-manage servers, but can be well worth it if you are not familiar with web servers. Even if you are a somewhat confortable with server configuration, a managed solution is a good idea. If you break something or can’t figure out why something is broken, then you can always lean on the support of the hosting company. I fully recommend using a host that provides managed hosting.

Operating Systems

Web servers come in different flavors. You could have a Windows Server that will run Internet Information Service to serve web pages or you could have any flavor of the Linux Operating system and apache or nginx (pronounced engine-x)as your server. While most of you are probably familiar with Windows, Linux with apache is the most popular web server on the internet. It may actually be difficult to find Windows based servers, but they are out there should you really want one. I recommend going with a Linux solution such as CentOS. CentOS is a free enterprise level operating system. Plus if you have managed support you don’t have to worry about knowing how to use Linux.

Control Panels

Another option for administration is a control panel. A control panel is a way to manage your server from the web. It provides an easy to use, graphical interface for configuration of your server. The most popular control panel is called cPanel. Finding a host that offers a control panel, such as cPanel, is highly recommended. Having a control panel will allow you to perform many administration duties without having server knowledge or having to rely on the support from the hosting company.

Where to get hosting?

Here are a few sites that you can look into for hosting. Our website is hosted by surpass hosting.

Once you have a hosting server setup you will need to set your domain name to point to this new server. You’re domain name registrar will be able to help with this step.

Basic Web Development and Mark Up

Once you have a domain name and web server you will need to build some actual webpages. For this task you will need to use HTML. HTML is a markup language that tells the browser how to display your website. You can create static web pages (meaning they do not change or pull in content from any other source) using HTML. For making website look presentable modern developers use CSS. CSS is short for cascading style sheets. Style sheets are additional rules that help the browser display your website in the way you want it to be seen. In addition to HTML and CSS there are also languages such as JavaScript, PHP, Ruby, and Perl involved in website development. We’re not going to go into each of those but luckily you can find some tutorials on those languages on teamtutorials.com. Don’t let a lack of web programming experience scare you away from creating your one website.

Content Management Systems

Content management systems (CMS) are web applications built to allows normal users to administer a website and add content. Most content management systems will give you a nice, web-based, interface for updating your website. It does take a little bit of work to install a CMS, but there are well documented guides on how to do this. If you have a host with cPanel, then it is likely that a program called Fantastico will be include. Fantastico can install several popular content management systems with the click of a button.

There are tons of content management systems available depending on the type of site you want to create. One of the most popular is called WordPress. WordPress was created for blogs, or online diary type sites. Blogs have matured to a popular form of media and WordPress has also matured. One reason I like WordPress is because you can always find the answer to your question with a quick online search. Other types of content management systems exist for forums (buddypress, ip.board, vbulletin), help ticket systems, project management, and almost any other type of site you can imagine. This is also a topic that will take another post to explore but we have several WordPress tutorials available.

Getting Traffic

Once you have a website, the next step is getting visitors. I can’t go to far into each topic, but I want to make you aware of some of the ways you can promote your website.

When I want to find something on the web I generally use a search engine such as google.com. You will want to make sure you website is available to search engined. There are several sites you can pay to “submit” your site to search engines. Never to this. Modern search engines will fine your site provided that it can be crawl. The process of getting your website to rank high in the search results is known as Search Engine Optimization or SEO.

Social networks are also a major traffic source on today’s internet. Sharing your content on sites like Facebook, Twitter, and LinkedIn is a good way to build traffic. If you have a good product or content your users may even share pages for you.

The other main source is advertising. We’re exposed to all types of advertising every day and the internet is no different. There are several types of advertising you can utilize. A few different types to research are Pay Per Click, Pay Per View, Display/Banner advertising, CPM or Cost Per Impression, affiliate programs.

Making Money From Your Website

If you are making a website then chances are you intend to make money from this site. If you have no intention to make money that is ok, but you may want to still look into monetization to pay for your hosting and domain bills. There are many ways to make money off of a website. Some of these include advertising, charging for premium content or membership, affiliate marketing, and lead generation. If you are interested in any of these topics you can find tons of information online. Some of the information is good, most is not. We at teamtutorials.com will be putting together some good courses on traffic generation and how to make money off of your newly formed website.

Simple Array Comparison with Ruby

I ran into a task where I needed to find the differences with some data. Since I’ve not spent much time with ruby I decided to give it a shot. It was surprisingly simple to do what I needed to do in ruby. I’m not going to post the entire details right now, but wanted to leave a quick note here on comparing arrays.

I stored the data I needed to evaluate into an array. I wanted to find the items that appeared in array A but not in array B. Basically all we need to do is included the ruby set library and then it is very very simple to do this.

require 'set'

#create array
a = [1,2,3,4]
b = [2,3,5,6]

#convert to set
a.to_set
b.to_set

#remove items in b from a
diff = (a - b)

#output what ever is left
puts diff

Since I already had my data in an array, I just converted it to a set object. Technically if you are creating a set you could use either of these methods:

a = Set.new[1,2,3]
#or
a = [1,2,3].to_set

Mainly I wanted to add this little snippet so I can refer back to this at some point, but I figured it may help someone else who is new to ruby. For more information on set check out the set documentation.

Why Zen-Coding is an Awesome Time Saver

If you are a web developer doing any kind of CSS and HTML work then you need to be using the zen-coding plugins. So what exactly is zen-coding? It’s not a new language, but more of shortcut system for generating structured code, such as HTML or XML, using a CSS selector like syntax. If you don’t get it yet, you’ll see the beauty within seconds of playing with the language.

There are currently plugins available for a wide range of popular text editors on what ever platform you use for development. I’ve become a MacBook fan lately. I installed the plugin for the popular Coda editor and was off and running in minutes. To see if there is a plugin available for your favorite editor check out the official zen-coding page. Download a version that will work with your favorite editor.

After I installed the Coda plugin I just had to setup the shortcut key I wanted to use for code completion. In my case this is control + e. Then you just have to get familiar with the syntax for generating structured code. If you are familiar with CSS at all then picking up the syntax should be very simple. If you are not familiar with the syntax, put the time in to learn. Trust me, once you know the syntax you will save tons of time coding.

I’ll give you a few short example to get you started.

Let’s say you wanted to general a basic html starter template. All you would have to type is:

html>head+body

What this says is that you want to generate an HTML tag. The ‘>’ character signals that you want the follow tag to be a child, or a nested element, of the head tag. The ‘+’ signals that you want the body tag to be a sibling of of the head tag. Now in my editor all I do is type that line and press control + e and the editor will generate:

<html>
	<head></head>
	<body></body>
</html>

A better example might be if you wanted to create a div with the id of ‘container’ and within that div you want to create an unordered list. Of course we’ll have to add list items to the unordered list and since this will be a menu, we’ll want to add links. Sure you could do this manually, or you could do it like this:

div#container>ul.menu>li*5>a[href="#"]

which will generate:

<div id="container">
	<ul class="menu">
		<li><a href="#"></a></li>
		<li><a href="#"></a></li>
		<li><a href="#"></a></li>
		<li><a href="#"></a></li>
		<li><a href="#"></a></li>
	</ul>
</div>

What if you wanted to add a unique class to each link? You could do something like this:

div#container>ul.menu>li*5>a[href="#"].item-$

You’ll get:

<div id="container">
	<ul class="menu">
		<li><a href="#" class="item-1"></a></li>
		<li><a href="#" class="item-2"></a></li>
		<li><a href="#" class="item-3"></a></li>
		<li><a href="#" class="item-4"></a></li>
		<li><a href="#" class="item-5"></a></li>
	</ul>
</div>

There is much more you can do. You can group items using parenthesis and even add text to elements if you would like.

div#container>(ul.menu>li*5>a[href="#"].item-$)+p.stuff{hello world}

How about this:

<div id="container">
	<ul class="menu">
		<li><a href="#" class="item-1"></a></li>
		<li><a href="#" class="item-2"></a></li>
		<li><a href="#" class="item-3"></a></li>
		<li><a href="#" class="item-4"></a></li>
		<li><a href="#" class="item-5"></a></li>
	</ul>
	<p class="stuff">hello world</p>
</div>

I’ve only demonstrated some of the potential of the zen-coding project. With support for tags, ID and class attributes, custom attributes, multiplication of elements, grouping and nesting there is not much you can’t do. You can fully code an entire document in a single line of syntax if you wish. To find out more make sure you checkout the official zen-coding page, I will definitely be using it.

What’s new in HTML 5

It’s been way too long since we’ve posted anything. With all the news around HTML5 and CSS3 that continues to come out, I thought now might be a good time to talk about some things we will see in the upcoming HTML5 standard.

HTML5 Doctype

The doctype has been simplified in HTML5. Now all you have to do is add the following doctype and your page is HTML5 ready.

<!doctype html>

HTML Structure Tags

The HTML5 standard recognized that most web pages have several type of elements in common. It added more semantic tags to handle these elements. In the previous standard we would use the div tag, but now there are several more descriptive tags available:

  • header – this tag is commonly used to identify the header of the page. However, from what I see in the specification, there is no reason this tag could not be used to denote the header of other content, such as a blog post.
  • footer – the footer tag can be used to define the footer of the html page or the footer of another element.
  • nav – the nav tag is short for navigation. The intention of this tag is to be used for major intersite navigation. Therefore I think it is best used for your site naviagtion (home,contact,about us, etc) but not for use to link to outside side such as you would see in a blogroll.
  • section – used to divide your page into sections. You may see this tag used in a blog to contain several blog posts.
  • article – defines a particular article in a page. I see this tag being used to contain individual blog posts within the seciton tag.
  • aside – right now aside is to be used to define other content on your pages that are not apart of the main content. The only real use I’ve seen is for side bars
  • figure – defines an element that is related to your article. Something like an image or diagram. This also allows for use of the figcaption element to add a caption to the parent figure.
  • mark – used to define an inline content that marked in some way. Could possible replace strong in some cases.
  • time – used to indicate a time value
  • meter – used to indicate a portion of a range. Such as a percentage of free space.
  • progress – can be used to indicate the completion of a task

Dynamic Pages in HTML5?

HTML5 has added some elements that take care of commonly used dynamic functions that would commonly be created using javascript.

  • details – provides details about an element. This would be like tooltips in non-Web applications.
  • datagrid – creates a table that is built from a database or other dynamic source
  • menu – an old tag brought back and given new life allowing you to create a menu system on your Web pages
  • command – defines actions that should happen when a dynamic element is activated

New Multimedia Tags

  • canvas – allows you to create dynamic graphics within your page.
  • video – tag used to add video
  • audio – add sound or music using the audio tag

We’ve just barely scratched the surface of the upcoming standard. In the future we’ll take a deeper look into HTML5 and CSS3. Also I hope to post some examples of how to use these new tags.

8 Must Have iPhone Cheat Sheets for Web Developers

When it comes to development, there are always simple things that we as developers forget. Ever get into a situation where you know how to do something in one language, but can’t quite figure out the correct syntax in another? I’ve put together a list of iOS “cheat sheet” apps that is sure to help with web development. If you are a developer than you must download these apps. You never know when you are going to need them!

HTML 5 Pro Quick Guide

It’s the new thing and you better keep up with the standards or you’ll be left in the dust. More than just a cheat sheet or reference, the HTML5 Pro Quick Guide provides beginners with a simple introduction to the basics, and experts will find the advanced details they need. Loads of extras are included: HTML5 elements, HTML5 attributes, HTML5 events, syntax, document structure, DOCTYPE declarations, colors, font styles, HTML5 version information, and browser compatibility tables for the most popular browsers.

JavaScript Cheat Sheet


Even seasoned web developers need a quick refresher course in JavaScript methods, properties and syntax from time to time. The JavaScript Cheat Sheet for iPhone and iPod Touch is designed to address that need. Use it as a quick reference for topics you’ve already learned but need a few reminders on, or if you’re still a beginner to JavaScript, use it to better understand what JavaScript is capable of.

HTML Cheat Sheet

This is a native app, not just a link out to internet references. It’s searchable and has an easy to use interface that helps you quickly find what you’re looking for. The categories are useful and well defined. The cheatsheet includes examples and quick reference lists for Tags, Attributes, Events, Colors, Character Sets, ASCII, ISO 8859-1 Symbols, ISO 8859-1 Characters, Math Symbols, Greek Letters, URL Encoding, Language Codes, HTTP Status Messages, and more.

Google Cheat Sheet

The Google Cheat Sheet for iPhone and iPod Touch is a quick reference to many of Google’s most popular tools and search techniques. It also covers the powerful, but lesser known tools Google provides to successfully search the web.

CSS Cheat Sheet

Unlike apps that cobble together random references from the web, this cheatsheet is written and reviewed by professional web developers that use CSS on a daily basis. We keep up with changing specifications and provide free updates in the same simple, easy to use format.

php Cheat Sheet

This is a native app, not just a link out to internet references. It’s searchable and has an easy to use interface that helps you quickly find what you’re looking for. The categories are useful and well defined. The cheatsheet includes functions and descriptions for Date & Time, File Handling, Errors, File System, Filter, FTP, HTTP, Libxml, Mail, Math, MySQL, SimpleXML, String, XML Zip, and many more.

RegEx Cheat Sheet

The cheatsheet includes:

* Matching: Normal Classes […] and [^…]
* Matching: Any Character dot (.)
* Class Shorthands (\w, \d, \s, \W, \D, \S)
* POSIX Character Classes (about POSIX, [:alnum:], [:alpha:], [:blank:], etc.)
* Unicode Properties
* Unicode Combining Sequences (\X, and the standard properties list – properties and meanings)
* Anchors and Zero-width Assertions (start and end of line/string, start of match, would boundary, look ahead and look behind)
* Comments and mode modifiers
* Grouping and Conditionals
* and many more

Python Cheat Sheet

This is a native app, not just a link out to internet references. It’s searchable and has an easy to use interface that helps you quickly find what you’re looking for. The categories are useful and well defined.

Unlike apps that cobble together random references from the web, this cheat sheet is written and reviewed by professional web developers that use Python on a daily basis. We keep up with changing specifications and provide free updates in the same simple, easy to use format.

Fix the timthumb.php WordPress exploit

There was a recent exploit found in a common file used to generate thumbnails. I found out about the exploit from Mark Maunder’s site. If you have a server running several wordpress blogs, like us, here is a way to fix all the exploits.

If you don’t want to copy and paste skip to the bottom of the post to download the fix.

First, upload a fixed version of the tim thumb file names timthumb-fix.php

<?php
/**
 * TimThumb script created by Ben Gillbanks, originally created by Tim McDaniels and Darren Hoyt
 * http://code.google.com/p/timthumb/
 * 
 * GNU General Public License, version 2
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 * Examples and documentation available on the project homepage
 * http://www.binarymoon.co.uk/projects/timthumb/
 */

define ('CACHE_SIZE', 1000);				// number of files to store before clearing cache
define ('CACHE_CLEAR', 20);					// maximum number of files to delete on each cache clear
define ('CACHE_USE', TRUE);					// use the cache files? (mostly for testing)
define ('CACHE_MAX_AGE', 864000);			// time to cache in the browser
define ('VERSION', '1.28');					// version number (to force a cache refresh)
define ('DIRECTORY_CACHE', './cache');		// cache directory
define ('MAX_WIDTH', 1500);					// maximum image width
define ('MAX_HEIGHT', 1500);				// maximum image height
define ('ALLOW_EXTERNAL', FALSE);			// allow external website (override security precaution - not advised!)
define ('MEMORY_LIMIT', '30M');				// set PHP memory limit
define ('MAX_FILE_SIZE', 1500000);			// file size limit to prevent possible DOS attacks (roughly 1.5 megabytes)
define ('CURL_TIMEOUT', 10);				// timeout duration. Tweak as you require (lower = better)

// external domains that are allowed to be displayed on your website
$allowedSites = array ();

// STOP MODIFYING HERE!
// --------------------

// sort out image source
$src = get_request ('src', '');
if ($src == '' || strlen ($src) <= 3) {
    display_error ('no image specified');
}

// clean params before use
$src = clean_source ($src);

// get mime type of src
$mime_type = mime_type ($src);

// used for external websites only
$external_data_string = '';

// generic file handle for reading and writing to files
$fh = '';

// check to see if this image is in the cache already
// if already cached then display the image and die
check_cache ($mime_type);

// cache doesn't exist and then process everything
// check to see if GD function exist
if (!function_exists ('imagecreatetruecolor')) {
    display_error ('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');
}

if (function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
	$imageFilters = array (
		1 => array (IMG_FILTER_NEGATE, 0),
		2 => array (IMG_FILTER_GRAYSCALE, 0),
		3 => array (IMG_FILTER_BRIGHTNESS, 1),
		4 => array (IMG_FILTER_CONTRAST, 1),
		5 => array (IMG_FILTER_COLORIZE, 4),
		6 => array (IMG_FILTER_EDGEDETECT, 0),
		7 => array (IMG_FILTER_EMBOSS, 0),
		8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),
		9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),
		10 => array (IMG_FILTER_MEAN_REMOVAL, 0),
		11 => array (IMG_FILTER_SMOOTH, 0),
	);
}

// get standard input properties
$new_width =  (int) abs (get_request ('w', 0));
$new_height = (int) abs (get_request ('h', 0));
$zoom_crop = (int) get_request ('zc', 1);
$quality = (int) abs (get_request ('q', 90));
$align = get_request ('a', 'c');
$filters = get_request ('f', '');
$sharpen = (bool) get_request ('s', 0);

// set default width and height if neither are set already
if ($new_width == 0 && $new_height == 0) {
    $new_width = 100;
    $new_height = 100;
}

// ensure size limits can not be abused
$new_width = min ($new_width, MAX_WIDTH);
$new_height = min ($new_height, MAX_HEIGHT);

// set memory limit to be able to have enough space to resize larger images
ini_set ('memory_limit', MEMORY_LIMIT);

if (file_exists ($src)) {

    // open the existing image
    $image = open_image ($mime_type, $src);
    if ($image === false) {
        display_error ('Unable to open image : ' . $src);
    }

    // Get original width and height
    $width = imagesx ($image);
    $height = imagesy ($image);
	$origin_x = 0;
	$origin_y = 0;

    // generate new w/h if not provided
    if ($new_width && !$new_height) {
        $new_height = floor ($height * ($new_width / $width));
    } else if ($new_height && !$new_width) {
        $new_width = floor ($width * ($new_height / $height));
    }

	// scale down and add borders
	if ($zoom_crop == 3) {

		$final_height = $height * ($new_width / $width);

		if ($final_height > $new_height) {
			$new_width = $width * ($new_height / $height);
		} else {
			$new_height = $final_height;
		}

	}

	// create a new true color image
	$canvas = imagecreatetruecolor ($new_width, $new_height);
	imagealphablending ($canvas, false);

	// Create a new transparent color for image
	$color = imagecolorallocatealpha ($canvas, 0, 0, 0, 127);

	// Completely fill the background of the new image with allocated color.
	imagefill ($canvas, 0, 0, $color);

	// scale down and add borders
	if ($zoom_crop == 2) {

		$final_height = $height * ($new_width / $width);
		
		if ($final_height > $new_height) {
			
			$origin_x = $new_width / 2;
			$new_width = $width * ($new_height / $height);
			$origin_x = round ($origin_x - ($new_width / 2));

		} else {

			$origin_y = $new_height / 2;
			$new_height = $final_height;
			$origin_y = round ($origin_y - ($new_height / 2));

		}

	}

	// Restore transparency blending
	imagesavealpha ($canvas, true);

	if ($zoom_crop > 0) {

		$src_x = $src_y = 0;
		$src_w = $width;
		$src_h = $height;

		$cmp_x = $width / $new_width;
		$cmp_y = $height / $new_height;

		// calculate x or y coordinate and width or height of source
		if ($cmp_x > $cmp_y) {

			$src_w = round ($width / $cmp_x * $cmp_y);
			$src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);

		} else if ($cmp_y > $cmp_x) {

			$src_h = round ($height / $cmp_y * $cmp_x);
			$src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);

		}

		// positional cropping!
		if ($align) {
			if (strpos ($align, 't') !== false) {
				$src_y = 0;
			}
			if (strpos ($align, 'b') !== false) {
				$src_y = $height - $src_h;
			}
			if (strpos ($align, 'l') !== false) {
				$src_x = 0;
			}
			if (strpos ($align, 'r') !== false) {
				$src_x = $width - $src_w;
			}
		}

		imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);

    } else {

        // copy and resize part of an image with resampling
        imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

    }

    if ($filters != '' && function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
        // apply filters to image
        $filterList = explode ('|', $filters);
        foreach ($filterList as $fl) {

            $filterSettings = explode (',', $fl);
            if (isset ($imageFilters[$filterSettings[0]])) {

                for ($i = 0; $i < 4; $i ++) {
                    if (!isset ($filterSettings[$i])) {
						$filterSettings[$i] = null;
                    } else {
						$filterSettings[$i] = (int) $filterSettings[$i];
					}
                }

                switch ($imageFilters[$filterSettings[0]][1]) {

                    case 1:

                        imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
                        break;

                    case 2:

                        imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
                        break;

                    case 3:

                        imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
                        break;

                    case 4:

                        imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);
                        break;

                    default:

                        imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);
                        break;

                }
            }
        }
    }

	// sharpen image
	if ($sharpen && function_exists ('imageconvolution')) {

		$sharpenMatrix = array (
			array (-1,-1,-1),
			array (-1,16,-1),
			array (-1,-1,-1),
		);

		$divisor = 8;
		$offset = 0;

		imageconvolution ($canvas, $sharpenMatrix, $divisor, $offset);

	}

    // output image to browser based on mime type
    show_image ($mime_type, $canvas);

    // remove image from memory
    imagedestroy ($canvas);

	// if not in cache then clear some space and generate a new file
	clean_cache ();

	die ();

} else {

    if (strlen ($src)) {
        display_error ('image ' . $src . ' not found');
    } else {
        display_error ('no source specified');
    }

}


/**
 *
 * @global <type> $quality
 * @param <type> $mime_type
 * @param <type> $image_resized 
 */
function show_image ($mime_type, $image_resized) {

    global $quality;

    $cache_file = get_cache_file ($mime_type);

	switch ($mime_type) {
		case 'jpg':
			imagejpeg ($image_resized, $cache_file, $quality);
			break;

		default:
		case 'png':
			imagepng ($image_resized, $cache_file, floor ($quality * 0.09));
			break;

	}

	show_cache_file ($mime_type);

}


/**
 *
 * @param <type> $property
 * @param <type> $default
 * @return <type> 
 */
function get_request ($property, $default = 0) {

    if (isset ($_GET[$property])) {
        return $_GET[$property];
    } else {
        return $default;
    }

}


/**
 *
 * @param <type> $mime_type
 * @param <type> $src
 * @return <type>
 */
function open_image ($mime_type, $src) {

	switch ($mime_type) {
		case 'jpg':
			$image = imagecreatefromjpeg ($src);
			break;

		case 'png':
			$image = imagecreatefrompng ($src);
			break;

		case 'gif':
			$image = imagecreatefromgif ($src);
			break;
	}

    return $image;

}

/**
 * clean out old files from the cache
 * you can change the number of files to store and to delete per loop in the defines at the top of the code
 *
 * @return <type>
 */
function clean_cache () {

	// add an escape
	// Reduces the amount of cache clearing to save some processor speed
	if (rand (1, 50) > 10) {
		return true;
	}

	flush ();

    $files = glob (DIRECTORY_CACHE . '/*', GLOB_BRACE);

	if (count ($files) > CACHE_SIZE) {
		
        $yesterday = time () - (24 * 60 * 60);

        usort ($files, 'filemtime_compare');
        $i = 0;

		foreach ($files as $file) {

			$i ++;

			if ($i >= CACHE_CLEAR) {
				return;
			}

			if (@filemtime ($file) > $yesterday) {
				return;
			}

			if (file_exists ($file)) {
				unlink ($file);
			}

		}

    }

}


/**
 * compare the file time of two files
 *
 * @param <type> $a
 * @param <type> $b
 * @return <type>
 */
function filemtime_compare ($a, $b) {

	$break = explode ('/', $_SERVER['SCRIPT_FILENAME']);
	$filename = $break[count ($break) - 1];
	$filepath = str_replace ($filename, '', $_SERVER['SCRIPT_FILENAME']);

	$file_a = realpath ($filepath . $a);
	$file_b = realpath ($filepath . $b);

    return filemtime ($file_a) - filemtime ($file_b);

}


/**
 * determine the file mime type
 *
 * @param <type> $file
 * @return <type>
 */
function mime_type ($file) {

	$file_infos = getimagesize ($file);
	$mime_type = $file_infos['mime'];

	// no mime type
	if (empty ($mime_type)) {
		display_error ('no mime type specified');
	}

    // use mime_type to determine mime type
    if (!preg_match ("/jpg|jpeg|gif|png/i", $mime_type)) {
		display_error ('Invalid src mime type: ' . $mime_type);
    }

	$mime_type = strtolower ($mime_type);
	$mime_type = str_replace ('image/', '', $mime_type);

	if ($mime_type == 'jpeg') {
		$mime_type = 'jpg';
	}

    return $mime_type;

}


/**
 *
 * @param <type> $mime_type
 */
function check_cache ($mime_type) {

	if (CACHE_USE) {

		if (!show_cache_file ($mime_type)) {
			// make sure cache dir exists
			if (!file_exists (DIRECTORY_CACHE)) {
				// give 777 permissions so that developer can overwrite
				// files created by web server user
				mkdir (DIRECTORY_CACHE);
				chmod (DIRECTORY_CACHE, 0777);
			}
		}

	}

}


/**
 *
 * @param <type> $mime_type
 * @return <type> 
 */
function show_cache_file ($mime_type) {

	// use browser cache if available to speed up page load
	if (!empty ($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
		if (strtotime ($_SERVER['HTTP_IF_MODIFIED_SINCE']) < strtotime ('now')) {
			header ('HTTP/1.1 304 Not Modified');
			die ();
		}
	}

	$cache_file = get_cache_file ($mime_type);

	if (file_exists ($cache_file)) {

		// change the modified headers
		$gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';
		$gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';

		// send content headers then display image
		header ('Content-Type: ' . $mime_type);
		header ('Accept-Ranges: bytes');
		header ('Last-Modified: ' . $gmdate_modified);
		header ('Content-Length: ' . filesize ($cache_file));
		header ('Cache-Control: max-age=' . CACHE_MAX_AGE . ', must-revalidate');
		header ('Expires: ' . $gmdate_expires);

		if (!@readfile ($cache_file)) {
			$content = file_get_contents ($cache_file);
			if ($content != FALSE) {
				echo $content;
			} else {
				display_error ('cache file could not be loaded');
			}
		}

		die ();

    }

	return FALSE;

}


/**
 *
 * @staticvar string $cache_file
 * @param <type> $mime_type
 * @return string
 */
function get_cache_file ($mime_type) {

    static $cache_file;
	global $src;

	$file_type = '.png';

	if ($mime_type == 'jpg') {
		$file_type = '.jpg';
    }

    if (!$cache_file) {
		// filemtime is used to make sure updated files get recached
        $cache_file = DIRECTORY_CACHE . '/' . md5 ($_SERVER ['QUERY_STRING'] . VERSION . filemtime ($src)) . $file_type;
    }

    return $cache_file;

}


/**
 *
 * @param <type> $url
 * @return <type> 
 */
function validate_url ($url) {
	$pattern = "/\b(?:(?:https?):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i";
	return preg_match ($pattern, $url);
}


/**
 *
 * @global array $allowedSites
 * @param string $src
 * @return string
 */
function check_external ($src) {

	global $allowedSites;

	// work out file details
	$fileDetails = pathinfo ($src);
	$filename = 'external_' . md5 ($src);
	$local_filepath = DIRECTORY_CACHE . '/' . $filename . '.' . strtolower ($fileDetails['extension']);

	// only do this stuff the file doesn't already exist
	if (!file_exists ($local_filepath)) {

		if (strpos (strtolower ($src), 'http://') !== false || strpos (strtolower ($src), 'https://') !== false) {

			if (!validate_url ($src)) {
				display_error ('invalid url');
			}

			$url_info = parse_url ($src);

			// convert youtube video urls
			// need to tidy up the code

			if ($url_info['host'] == 'www.youtube.com' || $url_info['host'] == 'youtube.com') {
				parse_str ($url_info['query']);

				if (isset ($v)) {
					$src = 'http://img.youtube.com/vi/' . $v . '/0.jpg';
					$url_info['host'] = 'img.youtube.com';
				}
			}

			// check allowed sites (if required)
			if (ALLOW_EXTERNAL) {

				$isAllowedSite = true;

			} else {

				$isAllowedSite = false;
				foreach ($allowedSites as $site) {
					if (strpos (strtolower ($url_info['host']), $site) !== false) {
						$isAllowedSite = true;
					}
				}

			}

			// if allowed
			if ($isAllowedSite) {

				if (function_exists ('curl_init')) {

					global $fh;

					$fh = fopen ($local_filepath, 'w');
					$ch = curl_init ($src);

					curl_setopt ($ch, CURLOPT_TIMEOUT, CURL_TIMEOUT);
					curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0');
					curl_setopt ($ch, CURLOPT_URL, $src);
					curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
					curl_setopt ($ch, CURLOPT_HEADER, 0);
					curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
					curl_setopt ($ch, CURLOPT_FILE, $fh);
					curl_setopt ($ch, CURLOPT_WRITEFUNCTION, 'curl_write');

					// error so die
					if (curl_exec ($ch) === FALSE) {
						unlink ($local_filepath);
						touch ($local_filepath);
						display_error ('error reading file ' . $src . ' from remote host: ' . curl_error ($ch));
					}

					curl_close ($ch);
					fclose ($fh);

                } else {

					if (!$img = file_get_contents ($src)) {
						display_error ('remote file for ' . $src . ' can not be accessed. It is likely that the file permissions are restricted');
					}

					if (file_put_contents ($local_filepath, $img) == FALSE) {
						display_error ('error writing temporary file');
					}

				}

				if (!file_exists ($local_filepath)) {
					display_error ('local file for ' . $src . ' can not be created');
				}

				$src = $local_filepath;

			} else {

				display_error ('remote host "' . $url_info['host'] . '" not allowed');

			}

		}

    } else {

		$src = $local_filepath;

	}

    return $src;

}


/**
 * callback for curl command to receive external images
 * limit the amount of data downloaded from external servers
 * 
 * @global <type> $data_string
 * @param <type> $handle
 * @param <type> $data
 * @return <type>
 */
function curl_write ($handle, $data) {

	global $external_data_string, $fh;

	fwrite ($fh, $data);
	$external_data_string .= $data;

	if (strlen ($external_data_string) > MAX_FILE_SIZE) {
		return 0;
	} else {
		return strlen ($data);
	}

}


/**
 * tidy up the image source url
 *
 * @param <type> $src
 * @return string
 */
function clean_source ($src) {

	$host = str_replace ('www.', '', $_SERVER['HTTP_HOST']);
	$regex = "/^(http(s|):\/\/)(www\.|)" . $host . "\//i";

	$src = preg_replace ($regex, '', $src);
	$src = strip_tags ($src);
    $src = check_external ($src);

    // remove slash from start of string
    if (strpos ($src, '/') === 0) {
        $src = substr ($src, -(strlen ($src) - 1));
    }

    // don't allow users the ability to use '../'
    // in order to gain access to files below document root
    $src = preg_replace ("/\.\.+\//", "", $src);

    // get path to image on file system
    $src = get_document_root ($src) . '/' . $src;

	if (!is_file ($src)) {
		display_error ('source is not a valid file');
	}

	if (filesize ($src) > MAX_FILE_SIZE) {
		display_error ('source file is too big (filesize > MAX_FILE_SIZE)');
	}

	if (filesize ($src) <= 0) {
		display_error ('source file <= 0 bytes. Possible external file download error (file is too large)');
	}
	
    return realpath ($src);

}


/**
 *
 * @param <type> $src
 * @return string
 */
function get_document_root ($src) {

    // check for unix servers
    if (file_exists ($_SERVER['DOCUMENT_ROOT'] . '/' . $src)) {
        return $_SERVER['DOCUMENT_ROOT'];
    }

    // check from script filename (to get all directories to timthumb location)
    $parts = array_diff (explode ('/', $_SERVER['SCRIPT_FILENAME']), explode ('/', $_SERVER['DOCUMENT_ROOT']));

	$path = './';
	
	foreach ($parts as $part) {
		if (file_exists ($path . '/' . $src)) {
			return realpath ($path);
		}
		$path .= '../';
	}

    // special check for microsoft servers
    if (!isset ($_SERVER['DOCUMENT_ROOT'])) {
        $path = str_replace ("/", "\\", $_SERVER['ORIG_PATH_INFO']);
        $path = str_replace ($path, '', $_SERVER['SCRIPT_FILENAME']);

        if (file_exists ($path . '/' . $src)) {
            return realpath ($path);
        }
    }

    display_error ('file not found');

}


/**
 * generic error message
 *
 * @param <type> $errorString
 */
function display_error ($errorString = '') {

    header ('HTTP/1.1 400 Bad Request');
	echo '<pre>' . htmlentities ($errorString);
	echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
	echo '<br />TimThumb version : ' . VERSION . '</pre>';
    die ();

}

Then upload our shell script as fix_timthumb.sh:

#!/bin/bash
find /home/ -name 'timthumb.php' -type f -printf '%h\n' | while read line
do
#Remove the old thumb
rm -rf $line/timthumb.php

#Copy fixed thumb
cp timthumb-fix.php $line/timthumb.php

echo $line " done";
done

The all you have to do is execute this command:

sh -x fix_timthumb.sh

The script will find any timthumb.php file and replace it with your fixed file. You will probably need root access to do this.

[tweet2download file=”timthum_fix.zip” tweet=”Replace all timthumb.php files on your server http://su.pr/1Libna” follow=”@teamtutorials” /]

Creating a Pill Icon in Photoshop

In this tutorial you will be learning basic techniques in Photoshop, such as using layer styles, brush and pen tool and effects. The end product will be a glossy pill icon, useful as a logo or an illustration. The tutorial is suitable for absolute beginners.

1. Create a new document
Create a new document by hitting Ctrl+N or Cmd+N on Mac with following values.

For easier workflow make sure you have Auto-Select Layer and Show Transform Controls ticked.

2. Place and trace
Drag and drop the sketch.jpg file into the canvas and resize it with transformation tool to fit. Hit enter.

Lock the sketch bitmap layer by selecting it and clicking on the padlock icon.

Select the pen tool and click on ‘Shape Layer’ in the toolbar.

Start tracing by clicking on any edge of sketch and adding points. Photoshop will create a new shape layer. Try to follow sketch lines to fill one part of the pill icon.

After closing the shape by clicking on the first point, select Direct Selection Tool (Ctrl+Shift+A) to manipulate any misplaced points. You can move them around by clicking twice.

When you’re happy with the shape, click on the layer and name it something descriptive by double clicking on name and click on eye icon to hide it.

Do same with the other part of the pill and get them aligned. Move the right part layer on top of the other by dragging and dropping. Hide the sketch layer.

Now select colors you’ll be using and fill shapes with them by double-clicking layer thumbnail. Colors used in tutorial are RGB(221, 62, 62) and RGB(224, 220, 220).

Select both layers and click ‘Duplicate layers’ in right-click menu. Merge duplicates into one rasterized layer by selecting ‘Merge’ from same menu.

Double click on created layer and click on Color overlay. Select white color and hit OK.

Resize and rotate the shape so it covers a little less than half of the pill.

Ctrl click on one layer’s vector mask thumbnail and hold Ctrl+Shift while clicking on another. This will select both layers’ pixels. Hit Ctrl+Shift+I to inverse selection and hit Delete with ‘highlight’ layer selected. Set layer’s opacity to 25%.

3. Effects
Select the Brush tool and apply the following settings in right-click menu:

Now select pill layer’s pixels once again and paint a highlight on a new layer. Set its opacity to 50%.

With same selection create another layer, set brush size to 200px and select black color. Paint on the bottom of the pill.

Apply following settings:

Paint on the end of the pill. Then set brush size to 400px and touch for highlight. Then paint another line of highlight on top edge of the pill.

Double click on the Right part and Left part layers and apply these layer styles:

Time to sort out our layers. Name them, group them, and let’s move on to final touch.

4. Drop shadow
Duplicate and merge Right and Left part’s layers once again and move it behind them. Overlay it with black color with layer styles.

Choose Edit -> Transform -> Perspective and modify layer according to perspective.

Then fo under Filter -> Blur -> Gaussian Blur and type in 40px. Take layer’s opacity down to 80% and you’re done.

Get the PSD

[tweet2download file=”files.zip” tweet=”Creating a Pill Icon in Photoshop http://su.pr/4004am on @teamtutorials” follow=”@teamtutorials” /]


This tutorial was written by Heidi Pungartnik, web and graphic designer. You can follow her on twitter (@ashocka18) or visit her website at aShocka.com.

Parsing XML Feed to an Array with XPath

Recently while working on a project, I found myself needed to parse several different types of files through the same mechanism (CSV, pipe delimited, XML, and more). I decided that it would be best to get each time of feed to a identical object that could then be run through the same methods regardless of the input type. This tutorial will walk you through using PHP and XPath to parse the values from an XML file and store them into array for later manipulation.

To start, for those that are unfamiliar with XPath. It is a mechanism which will allow you to easily navigate and retrieve elements and attributes from XML and HTML. It’s preety simple to understand and can make life a lot easier when dealing with these languages.
Let’s take a look at the following XML example. An XPath is literally just a path to whatever attribute or element you are looking to get.

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

//catalog/book/title would return the nodes that match that. In this case, there would be 2.

This is the basic idea behind XPath. If you are interested in learning more or need more information please review the information that they have over at w3schools on the subject. They will be able to provide everything you need to get started.

First lets create our method that will do the actually data collection for us:

   function parseXML($feed_url,$field_xpaths)
    {
        //Get file from url
        $file_contents = file_get_contents($feed_url);
        
        //create xml object
        $xml = new SimpleXMLElement($file_contents);

        //Work through all fields we need to collect
        foreach($field_xpaths[0] as $key=>$field_xpath)
        {
            $count = 0;

            //Get an array of fields that match the current xpath
            $xpath_returns = $xml->xpath($field_xpath);
            //Iterate through the array and assign values to the coupon array
            while(list( , $node) = each($xpath_returns))
            {
                $rows[$count][$key] = $node;
                $count++;
            }
        }

        return $rows;
    }

When you break this down, you see how simple this really is to achieve. The way this function is written, it will accept an array for the $field_xpaths variable. Then it will iterate the through the array treating each as it’s own xpath. Each value will use it’s key in the array as it’s name (in my example, these values are pulled from a database, so the column name is the name of the key for that value in the array).

It first grabs the entire contents of the file and associates a SimpleXMLElements object to them. This object will allow us to use XPath operators to navigate through our nodes. For each set in the array (key and value) we get all values that match the XPath provided. We then iterate through each value in the returned array and store it in a master array (in this case it’s just called rows). When this is done processing, all values for each xpath will be stored in an multi dimensional array that you can call by name. For example, I said that mine were from a database and one of my column names (which would then become a key in the array of results) was named store_name. I would then be able to access the stores at $rows[intCount][‘store_name’].

$field_locations = getFieldLocations($result['feed_id']); //Method to query the database and get the XPath values from it. 
$feed_array = parseXML($result['feed_url'],$field_locations); //Calls the parser method.

The above code just calls the function and store the result into the array. You can now take this array and do what you need to with it. That concludes this tutorial. I hope it was easy to follow, and as always, feel free to comment or ask questions. Thanks for reading.

Combine Text Files into One File in Windows, Mac, and Linux

I ran into a problem where I had a zip file that had a document I wanted to copy split into 100 different .txt files. I needed to combine all of the text files into one large file so I could copy all the data.

Windows

You can combine text files in Windows using copy’s binary mode. From the command prompt navigate to the folder with the .txt files and run the following command:

copy /b filename* all.txt /b

Where filename* matches the pattern of your file names and all.txt is the output file.

Mac / Linux / Unix

You can combine files in the unix shell using cat and appending the output to a file:

cat filename* > all.txt

Where filename* matches the pattern of your file names and all.txt is the output file.

This should help save someone a lot of copy and pasting time.

Access a MySQL Database Using PDO

This tutorial will show you how to access a mysql database using the PHP Data Objects interface, also known simply as PDO. One big advantage of using PDO versus other methods is the use of prepared statements which offers much better security than the mysql or mysqli libraries. Also PDO can connect to several different database systems by specifying another driver. It is almost as easy as switching the driver to change from one database system to another (except for DB specific SQL syntax).

This tutorial requires that you already have a mysql database to connect to or know how to create a mysql database and will set one up. If you do not know how to setup a MySQL database then you will want to check out some of our other tutorials.

As I mentioned above PDO supports multiple database systems. If you would like to see which drivers you have available on your server you can print the array of drivers using:

print_r(PDO::getAvailableDrivers()); 

To connect to a MySQL database using PDO you simply need to create a new PDO object and provide the database information:

//Database Credentials
$host = 'localhost';
$database = 'DatabaseName';
$username = 'dbuser';
$password = 'dbpassword';

try {
  $DBH = new PDO("mysql:host=$host;dbname=$database", $username, $password);

}
catch(PDOException $e) {
    echo $e->getMessage();
}

echo "it works";

In the sample above you need to specify the correct information to connect to your database. The $host variable is the system that the database is hosted on. If the database is on the same server that you are executing PHP on then you can simply use localhost. The $database variable is the name of the specific database on the server. $username and $password are just that, the username and password of the database user.

Save the page with a .php extension and execute it. If the database connection works properly than you should simply see a message that says “it works” if not you will see some sort of error that should point you in the right direction to start debugging. Common errors are: wrong user/pass, not allowing a user to connect from other hosts, and syntax errors. If you are having trouble getting this connection to work feel free to ask in the comments.

Now that you have the database connection what do you do with it? I will show you that in future posts.