Wednesday, December 24, 2008

Grades

Dear Class,

Thanks for your hard work in this class. For most of you, I think it's obvious how much you learned. And your progress has been impressive to watch.

In case you're interested, here is a break-down of grades in the class. As you'll see from the chart, I applied a "curve" to smooth out the numbers. However, since many students had very high grades, the curve did not have a drastic effect on lowliers.

Here's how letter-grades correspond to number grades:
  • A's are between 91-100
  • B's are between 81-90
  • C's are between 71-80
  • D's are between 51-70
Grades were based upon quizzes, homework, and final projects in about equal portions. I considered class attendance and participation when scores were close to the margins between two letter grades.

A few observations about the grades:
  • Three otherwise failing students went MIA, and their grades are not included in this chart
  • Four otherwise passing students did not complete a final project, and their grades are not included in this chart
  • those who performed on the low end of the chart seemed to stop doing well when we transitioned into PHP/MySQL
  • About half the class did what I would consider "extraordinarily well". This doesn't seem to have any correlation with previous web experience.
  • The median grade was an 80, just on the border between A and B
I welcome any and all feedback about the course. You know my email address.

Happy Holidays!

Amos

Friday, December 5, 2008

Intro to Security on the Web

Security risks on the web fall into 3 general categories:
  1. Server-side risks
  2. Client-side risks
  3. Network eavesdropping
Server-side risks
Every web server is a security risk - you are letting anyone in the world connect to your server and access files, run scripts, upload files, run queries on and store data in your database. The more complicated your setup, both in terms of the server setup as well as your code setup, the more likely you are to have bugs, which in turn makes it more likely you have holes in your security. Possible risks include the theft of confidential information and the installation of malicious scripts onto your servers.

A common example of something hackers will do once they compromise your server is a distributed denial of service attack (DDOS). Hackers will gain access to many insecure servers and install scripts that do nothing but make requests to a particular web server. With thousands of these scripts running concurrently on many compromised servers, hackers can easily create so much traffic for a website that it brings the web server to its knees and is not able to respond to all the requests. This happens all the time to the most popular sites. Usually web servers have software that detects attempted DDOS attacks and has mechanisms for blocking requests from any server that seems to be compromised in this way.

Another common attack is the SQL injection attack. Hackers will try to gain access to your database this way, and can easily steal private information, for example credit card numbers, if you are not careful. This is the primary reason why you should ALWAYS sanitize user input before using it in queries to the database. Make sure what the user has submitted does not contain any weird code in it, and that it is of the type that you expected (e.g. if it's a phone number you expect, make sure it's a phone number the user entered).

Client-side risks
Attackers may also target the client in a variety of ways. Each web browser runs as an application on your local client machine. This means it has access to your file system and everything on it. Since the information that the browser uses to display content from the web is usually coming from servers on the web, there's a chance that a hacker will be able to use a server to send instructions to your browser that may install malicious software, or force the client to do things like upload personal information to the hacker's server.

Multiple layeres of anti-virus software is a must on both PC and Mac for preventing malware from running your computer. Given that the web is a high-risk environment, most web browsers and email clients are thoroughly tested and can be considered secure. However, all of the major web browsers and email clients do issue security updates from time-to-time to fix security problems they find in their software.

Certain types of web applications, such as Java, ActiveX, Silverlight, Flash, Adobe PDF are not natively supported by most web browsers. This means that they must run as separate applications from the web browser (even though they show up in the web browser window), and so these technologies have their own security risks that their developers must constantly mitigate. Like browsers, these technologies are so commonly used that security risks are usually discovered quickly, and updates are sent out that patch the bugs. But bugs do exist, and hackers are always trying to find new ones. Do a search for "flash vulnerabilities" on Google, and you will see examples of exploits that hackers have created using Flash.

Phishing scams are another major client-side risk that you should be aware of. Scammers could create a website, for example, that looks exactly like Amazon.com's checkout page, but is actually created by a hackers in Nigeria. If for some reason you find yourself on this site thinking it is Amazon.com, you may enter your credit card information, which is then used by the hackers to buy gifts for themselves (or other more nefarious things). Phishing scams are also commonly used for identity theft - the phishing sites trick users into revealing personal information which is then used to apply for credit cards, issue passports, buy weapons, etc.

Most web browsers and email clients (e.g. Microsoft Outlook, Mozilla Thunderbird, Mac Mail, etc.), and client security programs (e.g. Norton Antivirus) have ways they try to identify phishing scams. But hackers are constantly figuring out new ways of bypassing or compromising every new tool that developers create, so most software should be updated regularly to keep it secure.

Network eavesdropping
Any time a client communicates with a server, the data is physically transmitted either via electic current in a wire or via radio waves in the air. There are ways hackers can intercept either of these means of communication.

Wireless communication is notoriously insecure. Anyone with a wifi card in their laptop can easily intercept unencrypted data being passed between the wireless router and other laptops. So some people encrypt the data that is passed between the two. The thinking goes that even if someone does intercept the signal, they won't be able to understand it since it's encrypted. However, WEP, the most commonly used encryption protocol available on wireless routers is known to be very weak encryption. WPA2 is supposedly a bit more secure, if it is available on your router. Another way to secure your wireless network is to set up your wireless router to only accept connections from computers with particular MAC addresses. Each computer has a unique MAC address that never changes.

Wired communication, via ethernet cable, or other types of wires, can also be intercepted by someone who plugs into the same network as either the client or the server. Since all communication between client and server shares wires that also are used by other clients and other servers, it's not crazy to imagine that someone could find a way to intercept and listen in on your conversation.

Like wireles communication, there are methods of encrypting communication over the wires so that even if someone does intercept communications, they won't be able to easily decipher them.

Many web servers, especially for e-commerce sites, are called "secure servers". Secure servers use the HTTPS protocol instead of the regular HTTP, so the URL will look like https://something.com, for example. Often, the checkout pages of online stores, or any page that asks the user to enter confidential information will be hosted on a secure server.

HTTPS encrypts the communication between the client and the server using the SSL encryption protocol. So the "secure server" is actually just encrypting the network communication between client and server, not securing the server itself against server attacks. The server and the client still have the same security risks as any other client or server. As with all encyption methods, SSL (and thereby HTTPS) can be hacked - a common exploit being the man-in-the-middle attack.

Further reading:
http://www.w3.org/Security/Faq/
http://www.securityfocus.com/infocus/1864
http://www.windowsecurity.com/articles/Common_Attacks.html
http://www.icir.org/vern/cs294-28/scribe/WebClientAttacks.pdf
http://www.icir.org/vern/cs294-28/syllabus.html

Be careful.

Intro to E-Commerce

The fundamental concepts of e-commerce are easy enough to grasp, and these days most e-commerce sites follow normative standards and conventions. There are three basic components: the storefront, the shopping cart, and the checkout.

The Storefront
When someone is shopping on the web, they want to browse products on a site to see what's available. Usually, products use categorization to make it easy for users to find the sort of products they're looking for.

For example, a shoe store typically has top-level categories such as Men's and Women's. A shoe store might also have one or more levels of sub-categories of each top-level category. For example, the Men's category might have sub-categories such as Boots, Sandals, Dress Shoes, Sneakers etc.

It is not uncommon for a particular product to fall into more than one category. For example, a casual hiking boot may fall under both Hiking and Casual.

Now for a small tangent on the topic of categorization: A modern twist on the idea of categorization is tagging. Many sites, especially "Web 2.0" sites, now offer tags in addition to, or as a replacement for, categories. Tags are just keywords that are associated with a particular product. Often, but not always, tags are user-generated, meaning that users of a site can add whatever keyword they want to a particular product. If users can collaboratively add tags to a product or asset, then the site offers what is known as a folksonomy.

Managing the storefront of an e-commerce site is a matter of organizing products, and managing inventory. How you organize the storefront, and how you categorize your products, are important concepts to work out in the information architecture phase of an e-commerce project, since the methods of navigation and categorization that you choose will affect every aspect of the site architecture.

In terms of development, a storefront would have separate database tables for categories, products, and the association of products to categories.

A typical categories table might have fields for id, title, parent_category_id, and created. A products table would typically have fields for id, title, description, num_available, price, thumbnail_image_path, large_image_path, and created. An association table could have fields for id, product_id, category_id, created, thereby allowing for a many to many relationship between products and categories by thereby having a separate row for each category a particular product belongs to.

The Shopping Cart
Shopping carts are an essential part of any e-commerce site. They take the metaphor of the physical shopping basket, and transpose it into online media. At its most fundamental, a shopping cart is tool for maintaining state and remembering which products a user has selected for purchase so that they can buy them all together as a batch without having to re-enter their billing and shipping info for each one individually.

As you can probably imagine, most shopping carts are simply tables in a database that have fields for user_id, product_id, and quantity (as well as the id and created fields, of course). That way, the database table simply has a row for every product in the user's cart. To get the contents of the cart, you make a query on the table for all rows that match a given user_id.

Payment Processing
The checkout and payment processing parts of an e-commerce site are the most complicated. You need to securely process a transaction on a user's credit card. This entire process should take place on a secure server where all communication between the client and server is encrypted. Also, in order to process credit cards online, you need to have what is known as a merchant account with a bank. To charge cards over the phone, in a store, or online, merchants need these special accounts with a bank.

Assuming you have a merchant account (or are using a payment service that does), the first step in processing payment online is to send the data from a user's shopping cart to a script that then calculates the total fee owed, as well as an taxes and surcharges. Once the user enter's his/her credit card, billing, and shipping info, you perform a transaction on their credit card by first authorizing it with the issuing credit card company.

If the credit card authorization passes, you must process the order with the credit card company by charging their card, remove the items from the user's shopping cart, and make sure your site's product inventory is up-to-date now that you have sold off a few items. Once everything is finished, you show a confirmation screen to the user with an order receipt. Often, the site will automatically send an email to the user (assuming they entered an email address) with the order receipt in it.

One rule of thumb to follow if you are running your own store is never to store sensitive information like credit card numbers in your database. Unless you have a budget to hire a decent security expert, your site can (and very well may) be hacked, and you do not want to be liable for the damages that would result from someone getting a hold on your clients' credit card numbers.

Due to the complication of doing all these steps yourself, most online merchants opt to use a third-party payment processing service that provides security and handles all the dirty work of charging a card for them.

Sunday, November 23, 2008

Version Control Software

When projects require several developers (i.e. designers, developers, html coders, etc), they may run into situations where multiple people try to edit the same file at the same time. This could be problematic, since one developer could easily overwrite another's work.

To prevent one person from overwriting another's work, most teams of coders use version control software. Version control software allows multiple people to simultaneously work on the same files while not overwiting each other's work.

Subversion is probably the most popular version control software:
http://subversion.tigris.org/

CVS is an older version control software. Subversion considered to be the better successor to CVS.
http://ximbiot.com/cvs/wiki/

For our intents and purposes, they are equivalent. There are a few simple concepts for using Subversion or CVS:

The Repository
CVS and Subversion use a type of client/server architecture. The permanent location of all files is on the server, in what is called a Repository. The Repository has the current version of all files, as well as all the older versions of the files. It keeps a permanent record of any changes to the project. Clients can always get the latest copy of the files by copying them from the Repository. So developers generally make changes to files on their local machines, and then upload them to the Repository so that other developers can get the lastest version of the files.

The Client
Your local computer runs a Subversion client that automates the common tasks that you will need to do when using version control. The recommended client for Windows is TortoiseSVN. For Mac, you should check out the client recommendations on the subversion site.

Working Copies
When a developer downloads the latest copy of the files from the Repository, they are placed in what is called a Working Copy. This is exactly what it sounds like - a copy of the original files that a developer can use to work. Once a developer has finished working on them, she has to then upload them back to the Repository so other developers can see the changes.

Updating
To get the latest copy of files from the Repository, a developer runs a command called Update. This automatically downloads the latest files from the Repository.

Committing
When a developer has finished making changes to her Working Copy of the files, she first runs the Update command to make sure that nobody else has modified the same files she is about to upload, and then runs a Commit command that automatically uploads the changed files to the Repository.

Conflicts
When two developers have modified the same files at the same time, and then they both Commit their changes, the second developer to commit his changes will experience a Conflict. Usually the work the developers have done is in different parts of the file, so Subversion or CVS can automatically merge the two versions together. However, in some cases Subversion and CVS cannot figure out how to merge the two versions of the file, so it asks one of the developers to manually merge the two. Subversion will show you the difference between the two files, and you can usually easily see what has to be done to get the two versions to merge correctly.

Reminder: Your Vote Counts

Please remember to vote for what material you want to cover in the next class. If you are viewing this in an RSS reader, you will have to visit my blog home page here in order to vote - the polling widget is on the right side of the page. If you prefer to learn something not included in this poll, add your ideas in the comments section for this post.

Speaking of votes, for something completely unrelated to web development, the PBS website has a vote going on for which short film to show on TV this Saturday. One of the contestants happens to be a film by my brother, so if you're interested, he could use your vote. Voting closes this Tuesday. Click here to watch and vote.

Please note that PBS is using the same Flash media player that I used in my Flash media examples - if you right-click on the videos you will see which media player they are using.

Overview of PHP/MySQL examples

Class 6 - Basic PHP
Class 7 - Intermediate PHP
Class 8 - Basic MySQL
Class 9 - RSS & XML
Class 10 - Object Orientation, Embedding Flash, Creating Social Networks

Saturday, November 22, 2008

Playing Media Files with Flash

To play audio or video files consistently across all the browsers, you will want to use a Flash media player. Flash is the most widely supported application on the web for audio and video files.

There are a variety of Flash media players available online, some free, some not. Here is an example using the freely available JW FLV Media Player, which is the same player used by SimplePie to play podcasts.

The nice thing about the JW FLV Media Player, and other players of its ilk, is that you can relatively easily skin it to make it fit the design of your site.

There are two ways people generally embed Flash players into their XHTML: via the <embed> tag, or using Javascript. This page gives a good overview of the two methods, and the reasons for using the Javascript version.

This example is the same as the first example, but uses the Javascript SWFObject.js library to put the Flash player on the page instead of using the <embed> tag.

Favicons

Favicons are the little icons that show up in the address bar of the web browser for some websites. For example, the favicon for blogger.com is the little orange square with the B in it.



Of course, you will want to create a favicon for your own sites. Favicons are in a special .ico image format that is not natively supported by Photoshop. This article has a good explanation of how to download a Photoshop plugin that lets you save favicons in .ico format using Photoshop.

If you don't have Photoshop, you can still create favicons by using a variety of website services that convert standard .jpg, .gif, or .png image files into .ico format. For example, here is one such site.

To use your favicon once you have created it, make sure the file is named favicon.ico, and put it in the root folder of your website. Then add the following code into the <head> of your XHTML code:

<link rel="shortcut icon" href="./favicon.ico" />

Monday, November 17, 2008

Photoshop Alternatives

Many of you don't want to buy Photoshop. While Photoshop is the absolute standard in image editing on the web, there are some free alternatives:

paint.net

GIMP

Saturday, November 15, 2008

Class 9 - In-Class Assignment

Your assignment from class 7 was to make an image uploading service. Hopefully you have completed that assignment.

Your in-class-assignment for this class is to publish an RSS feed for that site. Now that you are familiar with the concept of an MVC architecture, you will realize that if your site is set up in an MVC style, you will easily be able to apply different Views to the same data.

So your image uploading service will have two views: one in XHTML for web browsers, and another in RSS for RSS feed readers. I have retrofitted the blog example from class 8 so that it now has both an XHTML and an RSS view. Obviously this should be your reference for this assignment.

Additionally, your XHTML view will have a link tag that tells an RSS reader, like Google Reader, Esprsso, or NetVibes, where to find the rss version of your site.

The link tag syntax for RSS feeds is:
<link rel="alternate" type="application/rss+xml" title="NY Times RSS Feed" href="http://nytimes.com/HomePage.xml" />

Any site that has an RSS feed specified in the link tag will show the orange rss icon in the right side of the location bar of your Firefox browser. Clicking that icon will bring you to the RSS feed in Firefox.

SimplePie: an RSS Parser Library for PHP

In class, we've seen an example of how you can use the SimplePie PHP library to pull content from any site's RSS feed and display it on your own pages.

In this example, SimplePie is acting as the Model in our MVC architecture. index.php is theController, and index_view.php is the View.

In the example files, you will notice that there is a folder called "cache". This is where SimplePie temporarily stores copies of the RSS feeds that you load. It keeps each cached copy of the RSS feed for several minutes, so that if you reload your page, it doesn't have to always reload the same data from the site that publishes the RSS feed.

In fact, some sites will ban your site from accessing their RSS feeds forever unless you store cached copies of their feeds. This is because they want to minimize the number of requests that are made to their servers. SimplePie does this by default if you have a "cache" folder available.

So if you use SimplePie, you will need to make sure you have the simplepie.inc file (which holds the main SimplePie code), the cache folder (which stores cached copies of all RSS feeds), and the idn folder (which holds other misc SimplePie files).

Monday, November 10, 2008

Sanitizing User Input

We've discussed the need to sanitize any user-generated data before storing it in your database. This is primarily necessary to make sure users don't accidentally or intentionally wipe out your entire database with a variety of database hacks. But it's also useful to prevent users from trying a variety of other nuisance attacks or hacks, such as putting HTML or Javascript code where it doesn't belong on your site.

The sanitization of data we have seen in class so far is really the bare minimum necessary to protect your database from the most obvious attacks. However, to more thoroughly protect your database, you can use libraries created by security experts that offer a stronger level of protection.

Here is an example of a page that uses one such sanitization script. As with many 3rd party libraries, we don't have to fully understand how this sanitization script works, but we need to know how to use it.

This example has three files: index.php, process_sanitize.php, and sanitize.inc.php

index.php is just an HTML form, where users can enter data. The data a user enters is then submitted to process_sanitize.php

process_sanitize.php then takes this data and sanitizes it. It does so by including the sanitize.inc.php file, and calling a function, sanitize() that is defined therein.

sanitize() takes two parameters: the data to sanitize, and flags that indicate what level of sanitization you want.

The possible flags are: PARANOID, SQL, SYSTEM, HTML, INT, FLOAT, LDAP, UTF8. Because of the smart way these flags are defined by this PHP library, you can combine multiple flags by adding them together, for example SQL + HTML. This would strip out all SQL and HTML commands that a user might try to put into your database. The PARANOID flag is a combination of all the other flags.

Rather than creating your own sanitization scripts, you can include sanitize.inc.php into your own scripts and use it to sanitize your users' data.

Sunday, November 9, 2008

Homework Assignment

This week, there are 3 homework assignments:

1) Finish the Class 8 - In-Class Assignment. Additionally, you should add authentication so that users have to log-in in order to create blog posts and comments. New users must be able to register, and their username and password should be stored in a database table. Each blog post or comment should show the username of the user who posted it.

2) Read the MySQL tutorial

3) Decide what you will be doing for your Final Project. Post your idea to your blog.

...

4) And if you haven't already finished the Class 7 - In-Class Assignment, please do so. Wireframes are here.

Saturday, November 8, 2008

Final Project Requirements

DEADLINE
*All final projects must be completed by the last day of class (December 13).
*This means you have approximately 5 weeks to complete your projects.

REQUIREMENTS
*Final projects must show your mastery of the technologies we have learned in this class: XHTML, CSS, Javascript, PHP, and MySQL.
*Final projects must be completely information architected before you start programming.
*Projects must involve at least 3 distinct web pages.
*You will be required to present your site to the class on December 13
*All filenames must be lowercase with no spaces or special characters
*All variable names in PHP and Javascript must be written in camelCase.
*All CSS class names and IDs must be written in lowercase.
*Final projects must be accessible and working on the web, and must be linked to from your blog.

GRADING
*Grades will be loosely based on your ability to exhibit mastery of Information Architecture and programming techniques.

Information Architecture (20%)
Programming (50%)
Ability to conceptualize and realize a fully-functioning, well thought-out site (30%)

PRESENTATIONS
*You will be required to present your work to the class on December 13th.
*Presentations should be no more than 10 minutes
*Questions to answer in your presentation:
-Who are you, and what is your background?
-What's the purpose of your site and why did you decide to build it?
-Show your information architecture diagrams. Why did you choose this particular navigation structure and why did you place the various bits of information where you did in the wireframes?
-Show your completed site. What do you think works and what doesn't?
-What are problems you had, solutions you arrived at (or didn't), and any other issues you encountered when building the site?
-Is the site a good representation of what you had originally planned?
-What are your plans for the site (if any) once the class is over?
-What are your plans (if any) for continuing on with web development in the future?
-What did you or didn't you learn in this class that you had originally wanted to learn?

PHP Sessions - Maintaining State

In your readings, you may have come across mention of PHP Sessions. Sessions are another mechanism, in addition to GET, POST, and COOKIE parameters that allow you to "maintain state", meaning to pass data from one page to another.

PHP provides a set of functions that allow you to create Session variables. These are variables that are stored on the server, and last for a limited amount of time. They are very similar to Cookies, and in fact PHP does use Cookies to perform some of the tasks involved with Sessions. But PHP hides the internals of how Sessions work, so all you need to do is set the Session variables, and PHP handles the rest.

Here are some pages that cover sessions, and explain how to write PHP code to deal with them:

http://php.about.com/od/advancedphp/ss/php_sessions.htm
http://www.tizag.com/phpT/phpsessions.php
http://www.htmlgoodies.com/beyond/php/article.php/3472581
http://us3.php.net/session

Hint for Class 8 - In-Class Assignment

By now, you're wondering "Where in my code should I retrieve all the comments associated with each blog post?"

Good question. What I recommend is first of all you make a separate Model file for your comments. This will have functions to do all the database CRUD operations, just like the Model for the blog posts does for blog posts.

Just as the blog post Model has a getAllPosts() function, your comment Model will have a getAllComments() function. But unlike the getAllPosts() function, your getAllComments() function will take one parameter: the id of the blog post for which you want to retrieve the comments.

In other words, the function definition will start out like this:


...
function getAllComments($blogPostId) { ... }
...



This function will get all comments associated with the blog post that you specify in $blogPostId. I'll leave it up to you to figure out what the exact MySQL query is that will get those results. But what I recommend is that you return an array of all the comments as the return value for that function.

Then, you will have to call that function from somewhere. The easiest thing is to do that in the View that displays the blog posts.

In your blog View, you have code like this:


<?php foreach ($posts as $post) : ?>
...
<?php endforeach ?>



This code is looping through each blog post and displaying it, so it's the perfect place to add some code to get the comments for the current blog post and display them. So I would do something like this:



<?php foreach ($posts as $post) : ?>
...
<?php foreach (getAllComments($post['id']) as $comment) : ?>
...
<?php endforeach ?>
...
<?php endforeach ?>



This gets an array of all the comments for each blog post, and then loops through each element of that array. So inside that foreach statement where you are looping through all the comments, you put the code to display the comments.

Debugging MySQL

There are two very easy ways to debug your MySQL queries. If you are trying to do a MySQL query and it isn't working, you will want to try these:

1) If you are trying to create queries dynamically by inserting PHP variables into your MySQL queries, such as

$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
$result = mysql_query($myQuery);

where $blogPostId is a PHP variable you are trying to insert into your MySQL statement, make sure that the variable has the value you think it does. You can easily check this by printing out that whole statement to the browser.

$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
echo $mQuery; //print what this query really looks like after the variable is inserted
$result = mysql_query($myQuery);

If the query shows up as "select * from blogcomments where blogpost_id= order by created asc", you now know that the $blogPostId variable is empty.

2) use PHP's mysql_error() function to display any errors thrown by MySQL after you run the query:

$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
$result = mysql_query($myQuery);
echo mysql_error(); //print out any errors thrown by MySQL

Making Timestamps User-Friendly

When we set our MySQL tables to have a "created" field of the type TIMESTAMP with the CURRENT_TIMESTAMP option selected, this records the exact date and time that each row is created in the table.

The format that MySQL uses to record this data is "YYYY-MM-DD HH:MM:SS". However, this is not usually the format that you want to use to display the data on the web page. It's not so easy to read, and definitely is not how most people think of dates.

In order to convert the MySQL TIMESTAMP to a more user-friendly date format, you want to use PHP's built-in date() function. However, PHP's date() function only allows you to change the format of dates that are in Unix Timestamp, which is significantly different from MySQL's TIMESTAMP format.

So, in order to get PHP's date() function to work with MySQL's TIMESTAMP, you first have to convert MySQL's TIMESTAMP format to Unix Timestamp format. To do that, you use PHP's strtotime() function.

Here's the code that does this, from my blog example:


<p>posted <?= date("F j, Y, g:ia", strtotime($post['created'])) ?></p>


This displays on the page as, for example, "posted November 8, 2008, 12:19pm". You can use the date() function to format the date in a wide variety of other formats.

Class 8 - In-Class Assignment

Your assignment is to take the blog example we went over in class, and allow users to add comments to any blog post.

To do this, you will have to first create database tables to hold all the data. You will need a database table for blog posts, and one for blog comments. For this exercise, you can copy the the database tables that I have set up already for the example.

Your blogposts table should have the following structure:


And your blogcomments table should have the following structure:


As with all tables you will create in this class, these two have both an "id" and a "created" field. The "id" field should be the Primary Key, and should be type INT, and make sure it is set to Auto-Increment. The "created" field will be a TIMESTAMP type, and should be set to have the "Current Timestamp".

You will notice that the blogcomments table has a "blogpost_id" field, which is a foreign key that points to the primary key (i.e. the "id" field) of the blogposts table. So If you have a comment that is supposed to be associated with blogpost #5, this "blogpost_id" field will have the number 5 in it for that row in the blogcomments table. That's how you know it is supposed to be associated with blogpost #5.

So for each blog post, you will load all the comments from the blogcomments table where "blogpost_id" is equal to the "id" field of the current blog post. This is the main idea behind relational databases, such as MySQL.

Here is a wireframe of approximately how the page should look:

MySQL Tutorial

Please go through this MySQL Tutorial:
http://www.tizag.com/mysqlTutorial/

Bear in mind that we are using phpMyAdmin to set up and administer our databases.

MVC Architecture

Today we talked about the MVC Architecture, which is a design pattern that nicely separates database operations, logic, and presentation into separate components.

In our blog example, we saw how the blog Model code had separate functions for each CRUD operation. By keeping all direct interaction with the MySQL database in the blog Model, we can separate it from the business logic, contained in the Controller, that determines what to do for each page. This makes our code cleaner, easier to read, and easier to maintain if. If, for example, we decide to change the structure of our database tables, we only have to modify the code in the Model.

Once the Controller has determined what to do on any page, it fetches the appropriate data from the Model, and sends that data to the View, which has all the XHTML code necessary to display the page properly.

One of the nice things about common PHP Frameworks is that they offer clear MVC architecture. For example, I've been using Symfony recently, which forces my code to adhere to strict MVC principles.

Sunday, November 2, 2008

No Class November 29th

There will be no class on November 29th due to the Thanksgiving holiday break. The syllabus is incorrect.

Cookies - Reading, Writing, and Deleting

Here's a decent page about reading, writing, and deleting cookies in PHP:
http://www.w3schools.com/PHP/php_cookies.asp

Saturday, November 1, 2008

File Permissions

Most servers have settings that prevent just anyone from uploading or modifying files on the server. If everyone was allowed to edit every file, the server would have a serious security issue.

However, when you are making a website that allows people to upload files to your server, or to append data to an existing file, you need to make sure that the server knows to allow anyone to do that. Usually, when allowing file uploads, you set aside a particular sub-directory that anyone can modify.

For example, in the upload example we went over in class where users can upload images to the server, we allowed them to put the images into a directory called "files". This directory needs to have permissions settings that allow anyone to write to it. In another example we went over in class, when users save their Contact info into a text file, we need to make sure that text file has the proper permissions settings to allow that.

The easiest way to do this is to use WinSCP or some other file transfer program to set the permissions. In WinSCP, you can right-click on any file or folder on the server, and click "Properties". This pops up a dialog that allows you to modify the permissions settings for that file or folder.

Make sure that the folder where users can upload files on your server has Write permissions for both the Owner of the folder and Others.

Class 7 - In-Class Assignment - Wireframes







Class 7 In-Class Assignment

Your job is to make an image-uploading service. Users of the service can upload images that then show up on the site home page. The home page should show the latest 50 images that have been uploaded.

Users have to log in to see your site. If they are not logged in, they are redirected to the login page.
-this means you need a sign-up page that allows users to register with username/password

The home page displays a list of the 50 latest images that were uploaded
-all images should show the image, a one-line caption, and the username of the user who uploaded it

Here is a step by step breakdown of the tasks that you have to accomplish in order to get this to work:

LOGIN PAGE
-if the user is already logged in, they are redirected to the home page
-otherwise...
-show one text input for username
-show one password input for password
-and a submit button
-this page submits data to a script that checks the login info

SCRIPT TO CHECK THE LOGIN INFO
-receive the data the user entered from the Login Page
-open the users.txt file and see if there are any rows in that file that match the username/password the user entered
-if there is a match, you set a cookie called "loggedin" and set it equal to "true", and then redirect them to the home page
-otherwise, if the login failed, you redirect them to the login page with a user-friendly error message

HOME PAGE
-checks to see if the "loggedin" cookie is equal to "true"
-if it is, you let them see the page
-if it's not, you redirect them to the login page, and show a user-friendly error message
-if they are logged in, you open the "images.txt" file, and load all the data in there
-loop through each line of the text file, and get the image filename, caption, and username associated with that image
-display each image with the caption underneath it along with the username of the user who uploaded that image

UPLOAD PAGE
-users must be logged in to see this page, otherwise they are redirected to the login page with a user-friendly error message
-has a file input for the file the user wants to upload
-has a text input for the caption
-you have to figure out how to get and store the username of the user who is uploading this file
-submits the data to a script called process_upload_image.php that does the actual uploading and storing of the data

PROCESS_UPLOAD_IMAGE.PHP SCRIPT
-checks to make sure the "loggedin" cookie is equal to "true"
-if the user is not logged in, they are redirected to the login page with a user-friendly error
-if they are logged in....
-this script receives the caption and file that the user uploaded
-this script moves that image file to a permanent directory
-you need to make sure you have a variable that stores the path of the where the file was moved to
-this script needs to store the caption, image file path, and username to a text file called "images.txt"
-each new uploaded image will create a new line in the text file
-if there is an error uploading, this page shows a nice user-friendly error message
-if the upload succeeds, it redirects them to the home page with a user-friendly error indicating that their upload succeeded

Tuesday, October 28, 2008

Paragraph Typography

Another nice page about paragraph typography on the web, from the same site as my last post.

http://jontangerine.com/log/2008/06/the-paragraph-in-web-typography-and-design

Elastic Layouts

Here's a great site about how to make sure your pages scale well with elastic layouts:
http://jontangerine.com/log/2007/09/the-incredible-em-and-elastic-layouts-with-css

Monday, October 27, 2008

Client-Side Assignments Must Be Complete

Now that we will be switching focus from client-side technologies to server-side technologies, it's important for grading and other officious duties that you go back and make sure you have completed all the assignments from the first half of this course.

Please make sure I can easily find all the assignments to date by going to your blog. You should have easy-to-find links on your blog to each fully-functioning, completed, ready-to-be-grade assignment. You must have properly followed the instructions and requirements for each assignment. In other words, I'm giving you the chance to go back and clean up any sloppy work, so make sure it's good.

Here are the assignments I expect you to have completed before next class:

Class 1 - Information Architecture - Wireframing
http://nyuwebdevf2008.blogspot.com/2008/09/in-class-assignment.html

Class 2 - Basic XHTML / CSS Layout
http://nyuwebdevf2008.blogspot.com/2008/09/class-2-in-class-assignment.html

Class 3 - Intermediate XHTML / CSS Layout
http://nyuwebdevf2008.blogspot.com/2008/10/class-3-in-class-assignment-1.html

Class 4 - Forms with Javascript
http://nyuwebdevf2008.blogspot.com/2008/10/class-4-in-class-assignment.html

Class 5 - Advanced XHTML / CSS / Javascript
http://nyuwebdevf2008.blogspot.com/2008/10/class-5-in-class-assignment.html

Class Mailing List

Everyone should sign up for the class mailing list. If, for whatever reason, you feel you would like to send an email out to everyone in the class, you can send the email to the mailing list, and it will automatically be forwarded to eveyone.

This is the same list that I have used for several prior classes I have taught, so you should be aware that this list is open to anyone who has ever taken this class.

My former studets are all very nice, and if you post a problem to the lst, more often than not, a former student wil be more than happy to help you out with problems you come across, since they have been there and done that.

If you have not received an invitation to join this mailing list, please send me an email.

Sunday, October 26, 2008

Preventing Flickering on Mouseover and Mouseout Events

As many of you noticed with your e-commerce pages, Javascript mouseover and mouseout events can sometimes behave in unexpected ways. Events can be triggered when you least expect them.

This site outlines the problem clearly:
http://dynamic-tools.net/toolbox/isMouseLeaveOrEnter/

However, since we are using the wonderful prototype.js framework, we can solve this problem more elegantly than this site's authors did using just basic horrible Javascript.

To exhibit my solution to this problem, I have "borrowed" Joanna's site:
http://onepotcooking.com/amosbloomberg/f2008/class6/ecommerce/

If you check the Javascript, you will see I have added some code in the mouseout event handler of the product info divs. In the assignment, we said that when a user mouses out of a product info div, we should hide the div. However, the browser triggers those mouseout events far too often.

The browser thinks a user moused out of one of those divs even when a user mouses over any other element within one of those divs. So we get a flickering effect as the mouseout event handlers hide the divs, and the mouseover event handlers on the thumbnail images immediately show them again. On off on off on off on off, etc.

To solve this, we don't just hide the product info div when the mouseout event is triggered. We first check to make sure the user really moused off of the product info div before hiding it. To do this we check the "relatedTarget" of the mouseout event and make sure it is not a child of the product info div.

The relatedTarget property of any mouseover or mouseout event in Javascript is a built-in property in all Javascript, not just in prototype.js. For mouseover events, it holds the element that the user just left. In the case of mouseout events, it holds the element that the user is going to.

So we chek this relatedTarget element for the mouseout events. If it is a child of the product info div that triggered the mouseout event, we don't hide the product info div. If it's not a child of the product info div, we do hid that div.

All this in a few lines of code, thanks to prototype.js's childOf() function that easily allows us to check whether one element is a child of another element.

Here's the relevant code:

//whenever a user user mouses over the container div, call an event handler
Event.observe(el, 'mouseout', function(evt) {
//regular javascript mouseover and mouseout events automatically have a property "relatedTarget"
//in the case of mouseover events, this property holds the element that user came from before they moused over this element
//in the case of mouseout events, this property holds the element that the user went to after they left this element
var relTarg = $(evt.relatedTarget); //get the relatedTarget for this event, and make sure it has all the nice prototype.js extra functions
//if the relatedTarget is not a child of the current element, and it is not the same element as the current element, hide the product info divs
if (!relTarg.childOf(el) && !(relTarg == el)) {
//prototype.js provides a nice function "childOf()" to check if one element is a child element of another element
//in this case, we've checked to make sure the relatedTarget is not a child of the element that triggered the mouseout event
hideAllContent();
}
});

Saturday, October 25, 2008

Class 6 - In-Class Assignment - Templating

Your in-class assignment, and homework assignment for Class 6 was to use PHP to templatize the e-commerce pages you made last class.

What do I mean templatize? If you had a real store with hundreds or thousands of products, you would not want to hand-code all the pages and hand code all of the image tags and information for all of the products. You would want to use templates for those elements that are common across all pages. You write one snippet of HTML somewhere and re-use it all across the site.

Not only do you not have to rewrite the same code hundreds of times, but templatizing also makes site maintenance easier. If someone wants to change slightly the design of how the products are displayed, for example, they only have to make a change in one place, not in thousands of different places.

For this assignment, you will be templatizing the top-nav section of your pages, the footer, and each of the products in the store. The product thumbnails and product detail information divs for all products in the store should be working off of one template that is applied to all products. Of course, this means that your Javascript code that creates the mouseover effect on all product thumbnails will also have to work with the templates.

You will want to look at the example code we worked on in Class 6 to see how we templatized certain parts of those pages.

Thursday, October 23, 2008

PHP Tutorial

Here is the PHP tutorial site:

http://www.tizag.com/phpT/

Given how many of you are still working on the Javascript assignment, I am not requiring you to have read this by this Saturday. But you will be expected to have covered all of this tutorial by next Saturday.

Saturday, October 18, 2008

Basic Prototype.js Examples

Basic Javascript Examples

Prototype.js - A Javascript Framework

Prototype.js is a "javascript framework". It is a very popular set of Javascript functions and objects that add extra functionality to the basic Javascript commands available in most browsers. Prototype is useful on at least three levels:
  1. it simplifies many things that are normally very complicated in Javascript
  2. it provides a single cross-browser compatible way of doing many routine task that used to have to be done differently for different browsers
  3. Javascript is erratic, moody, and idiosyncratic. Prototype provides a consistent, "reasonable" set of interfaces that act as you would expect them to.
Here are some useful links:
The official prototype.js site
An unofficial (but very popular) guide to prototype.js




Class 5 - In Class Assignment

Your assignment, should you choose to accept it, is to convert this wireframe of an e-commerce store into an actual web page, using XHTML, CSS, and Javascript.

When a user mouses over any of the product thumbnails, more information about that product "pops up" over the thumbnail. When a user mouses off of the thumbnail, the product info disappears again.





Suggestions for how to structure your javascript for this assignment:

1) create an event observer that detects the "load" of the window
2) that observer calls a function called setThumbBehaviors()
3) the function setThumbBehaviors should get a list of all the elements that are thumbnails (hopefully you've set up the thumbnails in your XHTML so that they all have the same class name)
4) loop through each thumbnail element (using the .each() function of prototype), and attach an event observer to each one that detects "mouseover" events
5) the "mouseover" event observer should call a function whenever a user mouses over a thumbnail
6) that function should calculate the exact position of the thumbnail that was moused over, and figure out which "product info" div is associated with that thumbnail (see the tabs example).
7) the function should then make the "product info" div visible, and position it at exactly the same spot as the thumbnail info

Some example files that will help:
How to get the position of any element on the page using prototype.js
An example of a tabbed layout using prototype.js

Saturday, October 11, 2008

Standard Ad Sizes

Banner ads come in a variety of shapes and sizes. When you're designing a site where you intend to show ads, it sometimes helps to have "placeholder" ads so you can make sure that you are leaving enough space available for the ads you will end up running.

This site provides placeholder images of all the common ad sizes.
http://www.webpencil.com/bannersizes.php

Regular Expressions

In class, we have only scratched the surface of how to validate the data that a user enters in a form. For a variety of reasons, you sometimes want to know more exactly whether a user has entered in the type of data that you are expecting to receive from the form.

To do so, you need to use Regular Expressions. Regular Expressions syntax is almost an entire language in itself, and is very confusing to the uninitiated reader. There are thick books devoted to the topic available at most book stores, if you are so inclined.

This site does a decent (but not stellar) job of explaining how Regular Expressions are used.
http://www.regular-expressions.info/

Once you are familiar with the theory behind Regular Expressions, this page will instruct you on how to use them in Javascript.
http://www.regular-expressions.info/javascript.html

Class 4 - In Class Assignment

Your assignment:

imagine you are creating a shopping cart checkout page. The user has to enter his/her Shipping Address and Billing Address. Often, these two addresses are the same. So you want to make it possible for a user to only enter his/her Billing Address and click a checkbox to automatically fill in the Shipping Address with the same info as the Billing Address.

Additionally, if a user unchecks the checkbox, you want to wipe out the data that is entered in the Shipping Address.




Saturday, October 4, 2008

Class 3 - In-Class Assignment #1


Convert this into code!


You must use the types of CSS selectors we discussed today in class, for example:
#container h1 {}
#container > div > h1
#container ul li p
#container ul.ready li p

And, you must make the horizontal top menu using <ul> and <li> tags.

Thursday, October 2, 2008

Updated Class Blog List: Goodbye Netvibes

Netvibes has mysteriously deleted my entire list of class blogs. Due to my own difficulties with Netvibes, and based on some student feedback, I now recommend you switch to Google Reader, which is an alternative blog aggregator.

So you don't have to re-enter all the class blogs, I've created an OPML file with the entire list of class blogs in it. In Google Reader, you will be able to import the OPML file which will automatically set up the entire class blog list for you.

OPML is another subset of XML, like XHTML. But unlike XHTML, OPML is specifically designed to contain abstract lists of things. In this case, it contains a list of RSS feeds (another subset of XML) for all the blogs. (more on OPML here / more on RSS here)

To import the OPML file,
  1. visit this URL in Firefox: http://onepotcooking.com/amosbloomberg/f2008/class_info/blogs/webdev_student_blogs.xml
  2. click File->Save Page As... and save it to your hard drive.
  3. go to your Google Reader page (http://www.google.com/reader) - you will need to set up an account if you don't already have one
  4. on your Google Reader page, you will see a link at the bottom left that reads, "Manage subscriptions". Click it!
  5. on the Settings page, click the tab called, "Import/Export"
  6. Click "Browse" and find the file you saved on your hard drive
  7. Click "Upload"
  8. Done! Now the class blog list should show up on your main Google Reader page

The Secret to Layout: Float and Clear

As we discussed in class 2 (September 27), the secret to creating layouts with CSS depends upon the proper use of the properties "float" and "clear".

For example, say you were trying to code a page with the following layout:

The outer box is meant to represent the outline of the page. The layout is basically a grid: two rows and two columns.

The Question: How do you create that in XHTML and CSS?

The Answer: Using XHTML div tags, and the CSS properties float and clear.

Here is another version of the same diagram, but this one indicates how we would break the first diagram down into blocks of code:

First, a quick explanation of this diagram:

To make things obvious, the boxes in the diagram each show their respective CSS "selectors". In other words, the box titled "div#container" indicates that this is an xhtml div element with an id="container".

As you know, a tag like <div id="container" >
allows us to use a style sheet that is associated only with that id. Similarly, a tag like <div class="column" > allows us to use a style sheet that is associated with all elements that have class="column".

The dotted line around the "br.clear" box indicates that it will actually be invisible on the page.

So our XHTML will look something like this:

<div id="container">

<div class="column"></div>
<div class="column"></div>
<br class="clear" />

<div class="column"></div>
<div class="column"></div>
<br class="clear" />

</div>

And our CSS will look something like this:

#container {
width: 644px; /* the sum of the container padding, plus the widths of all the boxes inside the container, plus all their borders and margins */
/* do not specify the height of the container, this makes it somewhat flexible */
margin: 0 auto; /*centers the div on the page */
border: 1px solid red;
padding: 10px;
}

.column {
float: left; /* allows all divs with clas="column" to stack up horizontally */
width: 300px;
height: 300px;
border: 1px solid orange;
margin: 10px;
}

.clear {
clear: both; /* marks the end of a row. remember, every time you float, you must clear! */
height: 0px;
}


You can see what this looks like here

Saturday, September 27, 2008

Class 2 - In-class Assignment 1

Here is my solution to the assignment:

http://onepotcooking.com/amosbloomberg/f2008/class2/assignment1.html

Typography for the Web: a style guide

This site is a project of a former student of mine. It outlines the best practices for typography on the web:
http://csspunch.com/

Please take a look.

Class 2 - In Class Assignment

Please convert this diagram into XHTML and CSS:Save your code to a file called class2/assignment1.html

Class 2 - In Class Assignment

Please convert this diagram into XHTML and CSS:

Firefox Add-ons

Firefox Add-ons provide extra functionality to the Firefox web browser. These are the add-ons I recommend you install:

Firefox Add-ons
https://addons.mozilla.org/en-US/firefox/

Web Developer Toolbar Add-on
https://addons.mozilla.org/en-US/firefox/search?q=web+developer&cat=all

Firebug Add-on
https://addons.mozilla.org/en-US/firefox/search?q=Firebug&cat=all

Clear Cache Button Add-on
https://addons.mozilla.org/en-US/firefox/search?q=clear+cache&cat=all

Saturday, September 20, 2008

My In-Class Assignment

Click to see the full-size image:

In-Class Assignment

Your in-class assignment is to produce an Information Architecture wireframe diagram of the home page of a pet shop. Please make sure to include all the sections, as outlined in the Pet Shop Functional Requirements

Pet Shop Functional Requirements


-Logo
-Name of the shop
-Location and hours
-Awards Badges section to show the awards this shop has won

-Prominent link to Pet Food Page
-link to Other Products Page

-link to Veterinarians Page

FEATURED PET SECTION
-big image
-pet's name
-pet's age

PET SHOP BLOG
-titles of the last 10 blog posts

MAIN NAVIGATION
-link to Cats
-link to Dogs
-link to Rabbits
-link to Fish
-link to Reptiles
-link to Rodents

Links from Class 1

//WEB BROWSER

Firefox
http://www.mozilla.com/en-US/firefox/


//FILE TRANSFER PROGRAMS

WinSCP (for PC)
http://winscp.net/eng/index.php

Transmit (for Mac)
http://www.panic.com/transmit/

Cyberduck (for Mac)
http://cyberduck.ch/


//TEXT EDITORS

Notepad++ (for PC)
http://notepad-plus.sourceforge.net/uk/site.htm

TextMate (for Mac)
http://macromates.com/

TextWrangler (for Mac)
http://www.barebones.com/products/textwrangler/


//USEFUL WEBSITES

Mailinator - disposable email addresses
http://mailinator.com/

Blogger - blog platform
http://www.blogger.com

Netvibes - blog aggregator
http://netvibes.com

W3Schools - code reference
http://w3schools.com/