A second project – Material Design

With the introduction of the Lollipop; the latest mobile OS for Android devices, Google developers decided to introduce a minimalistic interior design. The idea behind it was to create a visual language for users, so much that it synthesizes the classic principles of attractive design with the innovation and possibility of technology and science introduced in the new operating system. This is called material design. In simpler words, material design is a comprehensive guide for visual, motion, and interaction design across platforms and devices. Android provides the following elements for you to build material design apps:

  • A new theme

The material theme provides a new style, system widgets that let developers and designers set their colour palette, and default animations for touch feedback and activity transitions.

  • New widgets for complex views

Android provides two new widgets for displaying cards and lists with material design styles and animations. These are the recycler and card views. In the app which we will be creating, we will mostly use the Card layout implemented in the CardView. CardView extends the FrameLayout class and lets you show information inside cards that have a consistent look across the platform. CardView widgets can have shadows and rounded corners.

  • New APIs for custom shadows and animations

In addition to the X and Y properties, views in Android now have a Z property. This new property represents the elevation of a view, which determines the size of the shadow and the drawing order. This gives a 3D look to each element in the layout. The new animation APIs let developers create custom animations for touch feedback in UI controls. Touch feedback animations are built into several standard views, such as buttons. The project will consist of a native Android application, which connects to a mySQL database through PHP scripting. The app will be developed for a closed audience group of youths who attend a particular religious oriented group, named TiBi. It will consist of the following features:

  1. Login for users including user registration
  2. A main page with contact information and a daily inspirational quote chosen randomly from a list of inspirational quotes.
  3. A list of events oragnised by the group with event details in the form of a list.
  4. A chat page, where all users can chat in a group.
  5. A map showing the location of the meeting places.
  6. A link to the Facebook page of the group.
  7. Push notification to inform users when an event is created.
  8. The ability to send anonymous feedback in the App.

The project will follow the Gantt Chart below to be able to be completed on time: http://publish.smartsheet.com/d246556440e64ed389d2a99fb1c42302 On the database end, the app will be needing the following tables to be able to communicate with the database:

  • Users
  • Events
  • Feedback
  • Quotes

ERD tibiApp

An ERD with the above table can be seen in the following link: Each of the tables will have the following columns with their data types:

User table
Column Name Data Type Parameters Description
userID INTEGER PK, Not null Contains unique ID for each user.
fullName VARCHAR(50) Not null Contains user name and surname.
userEmail VARCHAR(50) Unique, Not null Contains user’s email.
password VARCHAR(60) Not null Contains hashed password.
dateCreated TIMESTAMP Not null Date user was created in database.
dateModified TIMESTAMP Can be null Date user details were modified in database.
Event table
Column Name Data Type Parameters Description
eventID INTEGER PK, Not null Contains unique ID for each event.
eventName VARCHAR(50) Not null Contains an event’s name.
eventType VARCHAR(20) Not null Contains an event type for each event.
eventDate DATETIME Not null Contains event date and time for each event.
dateCreated TIMESTAMP Not null Date event was created in database.
dateModified TIMESTAMP Can be null Date event was modified in database.
Quotes table
Column Name Data Type Parameters Description
quoteID INTEGER PK, Not null Contains unique ID for each quote.
quoteName VARCHAR(250) Not null Contains a quote’s content.
quoteAuthor VARCHAR(20) Not null Contains the author of the quote.
dateCreated TIMESTAMP Not null Date quote was created in database.
Feedback table
Column Name Data Type Parameters Description
messageID INTEGER PK, Not null Contains unique ID for each feedback message.
messageContent VARCHAR(250) Not null Contains an message content.
dateCreated TIMESTAMP Not null Date message was created in database.
messageSent TINYINT Not null Controls if email with message was sent to Admin.

Tools which have been used

As a final post I will be including the different software applications which have been used to build the FireFIle application. I will be including the tools used to build both the front end, as used in the first 6 weeks to build the client side, and also the server side tools, used during the second 6 wekes of development.

Brackets

Brackets is an open source software application which is oriented to build client side applications with specific focus on JavaScript programming. This tools has helped me understand better the HTML and CSS technologies, since I had very little beckground of the technologies until then. Most importantly, it helped me in my testing in JavaScript functions, to make sure that the client side scripting worked perfectly.

Sublime Text

In some occasions, the free version of sublime text was used to explain JavaScript functions in details and be able to code them. This tool would be better in coding jQuery functions and 3rd party JavaScript libraries, but since it was required that we could not use these in the project, therefore, Sublime’s technology could not be used to the max.

Browsers

The mainstream browsers such as Google Chrome, Firefox, Internet Explorer and Safari were all used to test the viewability of the website across these different browsers. Since not all browsers support the same functions and libraries, it was therefore important for the site to be tested on all of these browsers. Sometimes, the client side code needed to cater for different browsers through the CSS scripts. This has already been discussed in earlier blog posts, when Client Side development was being discussed.

Also, the website needed to be tested on mobile devices, therefore a different css file needed to be included to handle smaller screens. This has also been discussed earlier.

XAMPP

Passing onto server side scripting, XAMPP was used as a package to create a local php server and develop the server side scripting. The program was also used to create the SSL certificate used to secure the website access and prevent it from being hacked by unwanted users. Bundled within the XAMPP package was the PHPmyAdmin database which was used to create the database to store the tables which contained the relevant data related to the FireFIle project.

PHPStorm

The server side scripting of the FireFile project was done by PHPStorm, which is a robust IDE specifically designed to code for PHP scripts. When the database was connected to the IDE, it was much easier to code the several functions for selections, insertions, updates and deletes.

Further Improvements

Nearing the end of the implementation of the FireFile project, this blog post will be dedicated to possible future features which could be implemented to the system. In some of these implementations, code will also be included to show that these could be implemented, had the time to implement the project been longer.

File Encryption/Decryption

This feature has already been discussed in details in the 8th blog with sample code to implement that feature in the post itself. Therefore here, we will go more in detail about the theoretical aspect behind the encryption/decryption of the files.

The below is a defenition of the crypt function which is a PHP function taken from W3 schools:

The crypt() function returns a string encrypted using DES, Blowfish, or MD5 algorithms. This function behaves different on different operating systems, some operating systems supports more than one type of encryption. PHP checks what algorithms are available and what algorithms to use when it is installed. The exact algorithm depends on the format and length of the salt parameter. Salts help make the encryption more secure by increasing the number of encrypted strings that can be generated for one specific string with one specific encryption method.

File Sharing

Although this has not been discussed beforehand in the php blog posts, the FireFile system is already prepared to implement this feature on the database end. What this feature basically does is actually give the ability to share files or entire directories with other users of FireFile. The restriction which FireFile will have is that in order to share files and folders, the other user need to have an account too. This can be done simply by entering an SQL statement to add the user_Id of the user whom the owner of the file wishes to access the file with. The user would then see the files and folders that have been shared with him/her in a sepearate section of the main page.

Inform the user by Email

There are functions in which FireFile can use the users’ email to inform them of certain communications. Some of these are the following:

1. When a new account is created

2. When a file/folder is shared with a user

3. To recover a lost password

4. To market promotions

5. Any form of communication with the users is ideally done through emails

The code which could be used to implement such features is the following:

<?php $to = 'joedoe@gmail.com'; 
$subject = 'FireFile - Account recovery'; 
$message = 'hello'; 
$headers = 'From: webmaster@example.com' . "\r\n" . 
'Reply-To: webmaster@example.com' . "\r\n" . 
'X-Mailer: PHP/' 
.phpversion(); mail($to, $subject, $message, $headers); 
?>

Create a mobile App

One of the most over-used technologies nowadays, is mobile development. A mobile application would make the whole repository accessible even on the go. All that is needed is a client side application for Android and Apple devices, since the server side coding has already been done by PHP. To our advantage is the fact that through JSON technology, the data can be accessed very easily from the database through PHP.

The Actual File Management System

Finally, we have come to the blog post where the actual file system will be created. This blog post will show how an actual file can be uploaded, registered into the database and downloaded onto the user’s PC. A file repository is very useful for several functions including a cloud repository for important files, file sharing with other users (which can be implemented as a future functionality in this project) and remote access to the files and folders from different locations.

A convention which was used in this project was that all php code was included in seperate files, and a call was made from the php files containing the HTML scripts to call the files. A simple file upload for example can be seen in the following code:

<?php $cam = "";
if (isset($_POST['folder'])){
$cam = "";
$path = $path . "/" . $_POST['folder'];
$cam = "?cam=".$_POST['folder'];
header("Location: index.php".$cam);
}?>
<?php
$uploadFolder = $path ."/";
entryLog($path . " -- ".gethostbyaddr(getenv("REMOTE_ADDR"))." ======== ".$_FILES['userFile']['name'] ." =========> UPLOAD");
if (!move_uploaded_file($_FILES['userFile']['tmp_name'], $uploadFolder . $_FILES['userFile']['name'])) {
print("<center><b>FireFile could not make this operation</b></center>");
}
else{
header("Location: main.php".$cam);
}
?>

The code above is able to upload a file and set it in a folder which contains the user_id. It does not contain the username for security reasons. Therefore, if there is any  security breaches into the FireFile system, the user’s Email would not be visible to the hackers. Instead they would only see the id.

The file location is inserted in the database through the following query:

On the other hand, the system gets the files already uploaded through the following code.

 $folderName = sqlQuery("SELECT folderName FROM FILES WHERE user_id = $user_id");
 $fileName = sqlQuery("SELECT fileName FROm Files WHERE user_id = $user_id");
 $fileLocation = "SELECT location from Files WHERE ID = $userId";

It then displays them in the HTML code through the following HTML code:

 <div id= "main-container">
 <nav class="main-menu">
 <ul>
 <li>
 <a href="#">
 <span class="nav-text">
 Download file
 </span>
 </a>
 </li>
 <li class="has-subnav">
 <a href="#">
 <span class="nav-text">
 Delete file
 </span>
 </a>
 </li>
 </ul>
 </nav>
 <section id = "control-container">
 <div id = "image-container">
 <?php
 foreach ($folderName as $foName){
 echo'<section>';
 echo'<img src="images/Red%20icon.png" style="width:100px;height:80px">';
 echo'<h3>'. $fileName['folderName']."</h3>";
 echo'</section>';
 }
 ?>
 </div>
 <div id = "image-container">
 <?php
 foreach ($fileName as $fiName){
 echo'<section>';
 echo'<img src="images/File.png" style="width:100px;height:80px">';
 echo'<h3>'. $fileName['folderName']."</h3>";
 echo'</section>';
 }
 ?>
 </div>
 </section>
 </div>

The files can also be saved in a directory through the following code:

if (isset($_GET['cam']))
 $user_id = $_GET['user_id'];
 $user_id = $_GET['cam'];
$pathFolder= $path."/";
if (isset($_GET['folderName']))
{
 $pathFolder = $pathFolder.$user_id."/".$_GET['folderName'];
 
 if (!file_exists($pathFolder))
 mkdir($pathFolder,0777,TRUE);
 $newFolder = sqlQuery("INSERT INTO Folder SET folder_Name = 'folderName', Location = $pathFolder, user_id = $user_id, createdDate = ");
}
header("Location: main.php?cam=".$user_id);

As the Files and folders can be created, they can also be deleted. The files can be deleted through the following code:

if (isset($_GET['cam']))
$user_id = $_GET['cam'];
$delFile = "DELETE FROM Files WHERE file_id = $cam";
header("Location: main.php?cam=".$user_id);
?>

In the same way, a folder can be deleted through the following code:

if (isset($_GET['cam']))
$user_id = $_GET['user_id'];
$user_id = $_GET['cam'];
$pathFolder= $path."/";
if (isset($_GET['folderName'])){
$pathFolder = $pathFolder.$user_id."/".$_GET['folderName'];
 
if (!file_exists($pathFolder))
mkdir($pathFolder,0777,TRUE);
$newFolder = sqlQuery("INSERT INTO Folder SET folder_Name = 'folderName', Location = $pathFolder, user_id = $user_id, createdDate = ");
}
header("Location: main.php?cam=".$user_id);

On the database end the deletion is made through a simple SQL statement.

Giving life to a static website

What gives life to the a website nowadays is the functionality of server side scripting languages such as PHP, ASP and JSP languages. Although HTML, CSS and Javascript have developed so much that that they can visually function as a great asset to create attractive websites, when it comes to passing sessions from one page to another, communucating with the database and performing certain functions, it is best to use server side scripting languages to perform such actions.

While ASP and JSP are proprietary programming languages, on the other hand, PHP is an open source language. Therefore most of its develepment is made by developers all around the globe. This makes PHP more oriented to make improvements on old libraries, develop new features and fix any bugs found. PHP development had its initialisation in 1994 when Rasmus Lerdorf wrote a series of Common Gateway Interface commands, which he used to maintain his personal homepage. He extended them to add the ability to work with web forms in the HTML of those days and enabled them to communicate with databases. At the time, programming had been purely procedural, since Object Oriented programming was still in its very early stages.

PHP developed together in line with other programming languages to communicate with relational databases, and even 4th generation data repositories. It was also developed itself into an object oriented programming langauge, as will be shown in the code snippets below.

User Access

In order to register a new user in the FireFile and verify the username and password, PHP fetches the username and password for the registered user and confronts them with the ones entered by the user in the form. This is done through the following code:

if (isset($_POST['email'])&& isset($_POST['password'])) {
$email = htmlspecialchars($email);
 $password = htmlspecialchars($password);
$email = $_POST['email']; //$email here is the name of the textbox in the form
 $password = $_POST['password']; //$password here is the name of the textbox in the form
if (!empty($email) && !empty($password)) {
$chkUser = "SELECT 'user_Id' FROM 'Users' WHERE 'username' = '$email' AND 'password' = '$password'";
if ($chkUserValidate = mysql_query($chkUser)) {
 $row_count = mysql_num_rows($chkUserValidate);
if ($row_count == 0) {
 echo 'Invalid username or password';
 } else {
 $user_Id = mysql_result($chkUserValidate, 0, 'user_id');
 $_SESSION['user_Id'] = user_id;
 session_start();
 header("Location: main.php");
 }
 } else {
 echo 'You must supply a username and password';
 }
 }
}

The code above checks if the user is already registered in the database and logs the user in if the account exists and takes him/her to the main page. Otherwise prompts the user with the relevant error messages.

The register page has the following php code to create a new user:

if ($num_rows > 0) {
$errorMessage = "Username already taken";
}
else {
$SQL = "INSERT INTO 'Users'('name', 'Surname', 'userEmail', 'password', 'mobile', 'createdDate')
VALUES($name, $surname,$userEmail, md5($password), $mobile,$createdDate)";
$result = mysql_query($SQL);
session_start();
$_SESSION['user_id'] = user_id;
header ("Location: main.php");
}
?>

Session Management

In the code above, apart from checking for the correct username and password, we also created a session with the user_Id which we got from the database. This is used throughout all the period the user is logged into the database, to make sure that only data related to the user who is logged in is shown. This is called session management.

Session variables store user information to be used across multiple pages (e.g. username, favorite color, etc). By default, session variables last until the user closes the browser. In this case, the user_Id is passed on through the different pages of the site to show the files, folders and settings for that particular user:

if ($num_rows > 0) {
 $errorMessage = "Username already taken";
}
else {
$SQL = "INSERT INTO 'Users'('name', 'Surname', 'userEmail', 'password', 'mobile', 'createdDate')
VALUES($name, $surname,$userEmail, md5($password), $mobile,$createdDate)";
$result = mysql_query($SQL);
session_start();
$_SESSION['user_id'] = user_id;
header ("Location: main.php");
}
?>

In the main page then, the user_Id is retrieved from the logged session using the following code:

<?php
 session_start();
$user_id = $_GET['user_id'];
$_SESSION['user_id'] = $user_id;
if (!(isset($_SESSION['user_id']) && $_SESSION['user_id'] != '')) {
header ("Location: login.php");
}

Then, in the same file, the Session Data is used to show the list of files which can be accessed by the user:

$uQuery = sqlQuery("SELECT userEmail FROM Users WHERE id = $user_id");
$folderLoc = sqlQuery("SELECT location FROM Files WHERE user_id = $user_id");
$folderArray = array();
$fileArray = array();
$folderName = sqlQuery("SELECT folderName FROM FILES WHERE user_id = $user_id");
$fileName = sqlQuery("SELECT fileName FROm Files WHERE user_id = $user_id");
$fileLocation = "SELECT location from Files WHERE ID = $userId";
if (isset($_GET['cam'])) {
$ncam = "". $_GET['cam'];
?>
<p>
<a class="fadeLink" onClick="msgProcessed(true);" href="index.php?cam=<?php echo setUpperPath($_GET['cam'])?>"><img src="images/open.gif" alt="Folder" width="16" height="16" border="0" align="absmiddle"><?php echo ($_GET['cam'])?>/..</a>
</p>
<?php
}

Object Oriented PHP classes

Just like in other programming languages, it would very untidy to write PHP code in the same file as the HTML code. Therefore, in this project, where php was needed to operate lengthy functions such as file upload or the file management system, the code was written in a seperate PHP file and call in the php file containing the HTML scripts.

An example of this is in the file upload code:

if (isset($_POST['folder'])){
$path = $path . "/" . $_POST['folder'];
$cam = "?cam=".$_POST['folder'];
}?>

<?php
$uploadFolder = $path ."/";
entryLog($path . " -- ".gethostbyaddr(getenv("REMOTE_ADDR"))." ======== ".$_FILES['userFile']['name'] ." =========> UPLOAD");
if (!move_uploaded_file($_FILES['userFile']['tmp_name'], $uploadFolder . $_FILES['userFile']['name'])) {
print("<center><b>FireFile could not make this operation</b></center>");
}else{
header("Location: main.php".$cam);
}
?>

Then, in the actual php file containing the HTML, the following code would be used to call the function:

while ($row = mysql_fetch_assoc($folderName)) {
 $folderArray = array_merge($folderArray, array_map('trim', explode(",", $row['folderName'])));
 }
while ($row = mysql_fetch_assoc($fileName)) {
 $fileArray = array_merge($fileArray, array_map('trim', explode(",", $row['fileName'])));
 }
if($error==UPLOAD_ERR_OK){
 $file = fopen($tempFileName,"r"); $content = fread($file,filesize($tempFileName)); $encryptedContent = base64_encode($content);
 $encryptedFileSaveName=$uploadDirectory.md5($insert_id).".data";
 $encryptedFile = fopen($encryptedFileSaveName,'w'); fwrite($encryptedFile,$encryptedContent); fclose($encryptedFile); print("File has been upload and encrypted successfully.");
 }else{ print("Error while uploading......"); }
?>

A Secure Repository

One of the main requirements of the project was to include an SSL certificate in the website to be able to secure the files which need to be uploaded. This would enable secure https access to the website and increase the security of the system. A dummy SSL certificate was created by using OpenSSL.

Normally, web traffic is sent in an unencrypted way accross the Internet. That is, anyone with access to the right tools can snoop all of that traffic. This is not ideal in a environment such as the one in FireFile where security and privacy are necessary to give an established repository for files and folders. The Secure Socket Layer is used to encrypt the data being transferred between the web server where the actual files are and the front end.

SSL makes use of public key cryptography (PKI) to create private and public keys, so that anything that is encrypted with these keys can only be decrypted with its corresponding key. So if a message or data stream were encrypted with the server’s private key, it can be decrypted with its corresponding public key. This ensures that the data only could have come from the server.

If SSL utilizes public key cryptography to encrypt the data stream traveling over an Internet connection. The certificate which is by default signed by a trusted Certificate Authority (CA), has the capability to make sure that the certificate holder is in reality the correct entity accessing the data. Without a trusted signed certificate, data may be encrypted, however, the party you are communicating with may not be verified. Without certificates, hacker attacks would be much more common on the Firefile system.

A possible enhancement for the future would be to encyrpt the files and folders uploaded online. This could be done through 2 ways.

Hashing the files and folders uploaded with a password

The uploaded files can be encypted using the same password for the user account using a password which is similar to the example below:

session_start();
$pass[] = "123456";
#create an array of passwords
#add as many as you want

#used for the logout link, changes the session 'loggedin' = false if ?action=logout
if($_GET['action'] == "logout"){
  $_SESSION['loggedin'] = false;
  $_SESSION['username'] = "";
}

if($_SESSION['loggedin'] == false){ #checks if the user isnt logged in
   if(!$_POST['s1']){     #checks if the form has been submitted, if not show it
   }else{
     #username check
     $tmppass = $_POST['pass']; #the password the user has submitted
     $t = count($pass); #count the total passwords
     $i = 0;
#create a loop to go through each password and compare it with the name pass which was submitted
     while($i <= $t){
       if($tmppass !== ""){
        if($tmppass == $pass[$i]){

          $_SESSION['loggedin'] = true;
          header('Location: ?'); #reload the page
          }
        }
      $i++;
     }
    echo "Invalid password 0.o"; #show an error message if the user enters an incorrect pass
   }
die;

The idea behind the method above, is to encrypt the uploaded file or folder with the same password used by the user to log into the system.

Encrypting the files using a javascript class, before it is uploaded using JQuery

The FileReader object used in HTML 5 lets us read the contents of local files using JavaScript, but only if these files have been selected explicitly by the user through the file input’s browse dialog. Below is just a sample code of how could this could be implemented:

if(body.hasClass('encrypt')){
reader.onload = function(e){
var encrypted = CryptoJS.AES.encrypt(e.target.result, password);
a.attr('href', 'data:application/octet-stream,' + encrypted);
a.attr('download', file.name + '.encrypted');
};
reader.readAsDataURL(file);
}