well, sometimes I think just writing down the problem helps. Here’s what i have, it’s a little ugly in one place but otherwise not too shabby.

This is the finished mark up from my form (I’m asking a user to select the bitrate of an mp3.) I’m trying to recreate this with php and retain the users selection when the form is redisplayed after a failed validation.

<select tabindex=”7″ name=”bitrate”>
<option value=”xxx”>xxx</option>
<option value=”128″>128</option>
<option selected=”selected” value=”160″>160</option>
<option value=”192″>192</option>
<option value=”256″>256</option>
<option value=”320″>320</option>
</select>

To retain the users selection when reloading the form I came up with this php snippet:

$bitrateArray =array(‘xxx’,'128′,’160′,’192′,’256′,’320′) ;
$markupString = ” <select tabindex=”7″ name=”bitrate”>.”constructSelect($bitrateArray, ‘bitrate’).”</select>”;
print $markupString;

function constructSelect($selectArray, $field) {

global $initialDisplay;

if ($initialDisplay) $_REQUEST[$field] = ‘null’; //prevents php throwing an error. messy

$tmpString =”;

for ($i = 0; $i <count($selectArray);$i++)

{

$tmpString = $tmpString.” <option value=’”.$selectArray[$i].”‘”; //the opening half of the tag

if ($_REQUEST[$field] == $selectArray[$i] ) $tmpString = $tmpString.”selected=’selected’>”.$selectArray[$i].”</option>”; //if the user data matches set to selected

else $tmpString = $tmpString.”>”.$selectArray[$i].”</option>”; //else just close the tag

}

return $tmpString;

}

$initialDisplay is a boolean set to true when the form first displays (ie no user input.) The ugly bit – setting the $_REQUEST variable to an arbitrary value so it doesn’t throw an error on the first time round. I’m sure there’s a better way to do that.

Anyway, I’m pretty happy with the solution and I don’t think the fact that the displayed data (value) and the item name (name) have to be equal is going to be a huge problem….perhaps something to improve on later.

I can now set up a collection of arrays or create arrays dynamically and have them populate and retain user input in drop down boxes throughout my site. :)


hmmm. I’m having trouble writing something elegant to set the value of a select box using php. The situation i want to use this in is right after the user has submitted a form and it has failed to validate (for example because the user missed a field, failed to enter numeric data where they should have and so on etc etc). I then need to redisplay the form with all the correct data from there previous attempt…. easy for text fields and checkboxes but I’m struggling with select lists..

anybody have a nice neat snippet of php showing how to do this?


bool?

11May08

Something that was causing me grief today was the boolean data type in phpmyadmin. I was trying to create a table field using the BOOL  and every time I thought I succeeded in doing so phpmyadmin would change it to TINYINT. bah.

Well, it seems using a true or false is fine when constructing a query but when creating a table, according to random poster here:

“in mySQL, there really is no boolean field type. BIT, BOOL and BOOLEAN are simply synonyms for TINYINT(1). A value of zero is considered false. Non-zero values are considered true.”

Which also explained why phpmyadmin was throwing an error why i tried to set the default value of the field to “FALSE”. I set it to 0 and everything works fine. :)


system plan

10May08

first, heres a link to my system plan from last week. The weak part of it is the lack of any meaningful personas… <whinge> as far as the ‘real world’ goes my project is vaguely plausible but I haven’t really put a lot of effort into justifying it (aiming it at real users, finding a market blah blah.) i thought the point of this subject was to demonstrate technologies, not to create a finished, publicly releasable project.. why bother with personas? </whinge>

I’ll probably end up adding some for the final version anyway.

GetId3()

Other things I’ve been working on: I discovered getID3(); a php library which, amongst other things, extracts information directly from the ID3 tag of an MP3. It would be great to add this to my project and cut out all the tediousness that admins would be forced to deal with when entering music information manually into the database. Also its open source / GPL:) and I’m pretty sure i don’t need anything other than basic user access to the server to implement.
If i can find the time i will add this in…

upload_max_size

I also discovered that a setting in php, upload_max_size, is set to 2MB by default. Not having access to the php.ini file i can’t change that, and frankly, I don’t think the uni admins would be to pleased with me sucking up their bandwidth. I will likely re-encode some old mp3’s down to 16kbps or there abouts for the purposes of testing.

PHP email injection

So, last week I was messing about trying to learn php and using the mail() function and building a contact form. I learned that that there are flaws in the way php handles input that can allow users to ‘hijack’ online email forms and get them to mass spam third parties.

The way this is done is that spammers enter extra line feed and carriage returns into one of the header fields of your email form, usually in the “to” or “subject” field that your form provides. Not in the actual form but in the url they submit such as http://www.yoursite.com/yourform.php?to=variable&from=variable etc etc.

After sneakily inserting extra lines they write their own to, cc and bcc etc headers with a list of addresses they intend to spam, and when php’s mail() function attempts to send it assigns these to the actually email header. for example a legit email from a contact form might read:

to: admin@website.com
subject: help me!
from: someuser@website.com

message: help, I can’t change my settings on your site!

but the same hijacked email would look like this if passed a spurious variable in the url eg:

anonymous%40spam.com%0ACcc%3avictim%40site.com%0ABcc%3aanothervictim%40site.com%2cyetanothervictim%40site.com%0ACto%3anewvictim%40site.com

to: admin@website.com
from: anonymous@spam.com
cc: victim@site.com
bcc: anothervictim@site.com, yetanothervictim@site.com
to:newvictim@site.com

subject: buy some v*agra!

So, the spammer by exploiting the way php handles CR/LF instructions adds in his/her own cc and bcc fields (or even a second ‘to’ field as above), meaning our contact page and our mail server are suddenly spewing emails about v*agra and replica watches all over the internet. BAD.

(%0A %0d are LF/CF instructions.)

The way to get around this is to add in some PHP to ’sanitise’ the user input. That is, string match and strip any of the offending characters listed above.

Here’s an example fix taken from securephpwiki.com

<?php
$from = $_POST["sender"]; //looks at the from input from our contact form
$from = urldecode($from); //decode url encoded string (transform %0A %0d to \r or \n)?
if (eregi("(\r|\n)", $from)) { //looks for strings \r or \n, php cr and lf
die("Why ?? :( "); //if found end and return a string 'why ?? :( '
}
?>

I’m glad to have found out about this before using it in a real world project, having a spammer or a bot hijack a form on a legitimate website would be poisonous for that business. (they’d probably be blacklisted eventually)

Well, that’s the limit of my understanding at the moment, here are some of the references I used.
http://www.securephpwiki.com/index.php/Email_Injection
http://www.softswot.com/form-hijacking.php
http://www.astalavista.com/index.php?section=docsys&cmd=details&id=30


mock up pages

19Apr08

warning: long rambling post ahead.

I’m running a little bit behind schedule partly due to devoting time to other subjects and also because even though I tried not to spend too much time mucking about with the visuals, I probably did anyway :( Anyway, I’ve got the page design down and what I’ve come up with is still relatively simple – basically a one page template for everything.

Database changes

When I actually went through the design process I discovered I’d missed a few things earlier.

For the database (see the original here) I realised that Somehow I managed to forget to include an email address for each user, which is essential for allowing registration. I also decided I want to index an image to each piece of music, something like an album cover or artist photo so there’s now an extra column to reference that. Finally I’ve added the column userValidated to the user table. This would be a Boolean automatically set to false when the user has registered and not clicked the special link sent to their nominated email address. When they click that link the would head to a page whose PHP would set this field to true. Standard spam prevention/validation etc…. A user would need to enter a valid username/password and have userValided == true for a successful login.

I’m also thinking I only really need two tables, not three as in my first draft…why make things more complicated than they need to be? My queries would be full of needless inner joins…

revised database tables

New pages

I’ve also decided that i will add a couple of search options for my end users. Keeping things as simple as possible, I’ll provide just three predefined queries; one will throw up some random files, one will return ‘new files’ meaning files that have been added to the database since the users last visit (fileDate vs userLoginDate) and the last one will return all the music files that match the users nominated favourite genre. So, anyway, to reflect this I need a page with a form that will allow the users to choose one of these options. You can see the changes to the flow chart below (click for full size).

revised flowchart

Artwork/mock-ups

I’ve made the pages look like a little bit like what I imagine a commercial site might look like but based on a single template/page to save time and keep things simple. Of course there’s plenty missing (a navigation menu for example) because I don’t have the time or interest to add them.

Oh yeah, and In a moment of shear creative genius (or not), I decided to call my music file sharing site….umm.. musicfiles.com… meh. The thumbnail images follow the flowchart above.

Login:

Login failure:

New user registration

(i’m planning to incorporate the user password strength widget into this page):

New user registration 2

Account validated

Retrieve password

Retrieve password 2

Search

Admin file upload

User file download

Log out

Some graphics came from morguefile.com (free! If you are in need of some quick stock images for a student project or something with $0 budget it’s worth a look) or already had lying around from istockphoto.com. Fonts other than web safe ones are Qlassik, Scriptina and Mplus which are all free.

Also the album art came from freecovers.net which is probably highly dodgy :P


micro & macro

12Apr08

Final Micro/ macro analysis. I forgot to post this earlier in the week:

Hopefully over the next couple of days I’ll post up some pages for my project (photoshop mockups and the html/css only) which I will plug into the final where they will be created dynamically with php.

My learning proposal included a diagram charting the user path through the web page (pictured below). I’ve taken another look at this to help work out what I need to create in terms of pages. Here’s what I’ve come up with.

1) Login page
2) login fail/retrieve password? (form)

3) Registration page (form)
4) Account created

5) user search/select files(form)
6) admin/upload files and description (form)

7) file list/search results
8 ) upload/download complete

9) logout/thank you page.

I’m planning to stick to my learning plan and keep the pages visually simple…

flow chart


I had a go at sketching out what I’d need in terms of a database for my webapp. This is only a starting point and you can be sure there’ll be a lot tweaking and rewriting before it’s ready…also as my other subject progresses (it’s on database design), there will likely be a lot of head-butting the desk as I realise how bad this first effort is :?

anyway, heres the relationship diagram:

relationship diagram

User (uploader) to files = one to many
music to files = one to one

Essentially the user table store the account details, all the details you’d expect to have to fill in when signing up for any old webservice. The userPassword field will most likely be stored as an md5 encrypted string (this should be easy to do since an md5 function is built into php) , the userAge field will be computed from the DOB field and the userFav* fields are where the user is asked to nominate their musicall preferences. userName is the primary key, obviously you can’t have two users with the same username holding an account on the one services so I’ll do a search when they nominated a username and if a row is matched you’ll get the old ’sorry that username is already taken!’ message.

userRole is either admin or user, and userLoginDate is (surprise!) the date of last login. This would be used to compare with the fileDate column and show the user any new files that have been uploaded since their last login.

Also the asterisks indicate fields which can be NULL. I’ll ask nicely for address details but not bar access to users who don’t want to divulge that information. That’s also a pretty common feature to website registration.

The file table stores information about the file itself such as who uploaded the file (userName) , where it is stored on disk (filename) and whether it is publicly available/published (filePublish) or just sitting in the database. fileNo is just a unique generated integer.

The idea behind separating File and Music table was that the music table should hold all the info about the content of the file while the file table holds information about the file itself, regardless of what it’s content is.. (Im not totally convinced two tables here is a good idea but we will see how it goes.) Most of the column data in music will just be taken from an ID3 tag. The exception is the MusicExplicit column which is designed to hold a boolean value indicating the track has explicit content…so kiddies under 18 can’t download Cannibal Corpse tracks :-| .. If I’m feeling masochistic and want to give myself more work I might bother implementing this one.

Some SQL.

So I tried to write a couple of SQL queries to see how my strucutre would work: The basic function according to my flow diagram in the proposal will be to present the users with a list of files they might like to download based on their nominated favourite artist. They will also be presented with a ‘you might also be interested in..’ list based on the favourite genre they have selected.

The SQL for selecting all the tracks of the users favourite genre might go something like this (returning just directory/filename.mp3 via filename):

SELECT fileName
FROM Files
WHERE filePublic = TRUE
AND fileNo IN (SELECT fileNo FROM Music INNER JOIN Users ON userFavGenre = musicGenre) ;

Havent tested that, so its likely full of bugs :(
Select all files in the genre called hiphop where the quality (bitrate) is 160kps or better. Filter out explicit tracks as our user is under 18.

SELECT fileName
FROM Files INNER JOIN Music
ON Files.fileNo = Music.fileNo
WHERE filePublic = TRUE
AND musicGenre = “hiphop”
AND musicBitrate >= 160
AND musicExplicit = false;

In the interests of making life difficult for myself :-| I could possibly work out the explicit selection on the fly with SQL (ie check the user age, return only records where explicit = x) .. but.. eh.. SQL difference problems are too tricky for me at the moment. I could probably also work out the users age and whether they are able to view explicit files via php and another separate sql query.


Final learning proposal is up. Click here.

Ive decided to develop a small web application which will distribute files to users who create an account based on the preferences they indicate when subscribing.

For the purposes of the project I’ve decided to use the model of a music subscription service. I figure that this will give me plenty of options when it comes to matching users with files that match their preferences (genres, favourite artists, year of release, albums and so on.). Anyway, read above for all the gory details.


For most of the week my project proposal was still in limbo awaiting feedback, so I passed the time doing a little research without getting stuck into the really detailed planning. I’ve been reading up on security such as session id’s and cookies as well as a little background on keeping my database safe from sql injection attacks ….all very interesting, and not nearly as scary or confusing as they first sounded.

Recently I created an account on a website (can’t remember exactly where…) and when I was asked to create an account password the site gave me feedback on on whether my choice was weak or strong via a neat little animation. Since users with weak passwords are a huge security issue I thought it would be worth creating my own version of this ‘password strength checker’ to weed out the poor passwords on my web app.

I slapped together some javascript and a working example which can be found here . Enter any random text in the password field to see it work.

When a user creates an account It checks the input as they enter it and evaluates that passwords strength via a little animated bar. I used this and this as a basis for what makes a good password. My formula is a little flaky but essentially it checks for uppercase, lowercase, numbers and punctuation combinations, the more the better. Also, if you enter your username or the string ‘password’ for your new password it will set the strength to zero.

My animating bar is based on on the ABC’s old interactive election website – not that i ripped off the code…just the idea ;) . I also used robert penners tweening equations for actionscript 1 to get the smooth motion. (http://www.robertpenner.com/easing/). Obviously for flash but a simple deal to get working in javascript. Occasionally it seems to jump rather that smoothly animate so I probably have a bug somewhere <shrug>.

OK in firefox, and, by complete accident, IE6/IE7 too..

Anyway, like all of my code its messy as hell but it works… feedback and improvements appreciated.


Whoops. Forgot to post this the other day. Learning proposal is up.