Web Exam help: Difference between revisions
From ICO wiki
Jump to navigationJump to search
(One intermediate revision by the same user not shown) | |||
Line 120: | Line 120: | ||
<?php include "footer.php" ?> | <?php include "footer.php" ?> | ||
</source> | |||
==LAURI-INDEX.PHP== | |||
<source lang="html5"> | |||
<?php | |||
include "header.php"; | |||
require_once "config.php"; | |||
$SQL_IMAGES = " | |||
select | |||
lauri_gallery_image.id, | |||
lauri_gallery_image.hash, | |||
lauri_gallery_image.created | |||
from | |||
lauri_gallery_image | |||
join | |||
lauri_gallery_album | |||
on | |||
lauri_gallery_album.id = lauri_gallery_image.album_id | |||
where | |||
lauri_gallery_album.owner_id = ? | |||
order by | |||
lauri_gallery_image.created desc | |||
limit 2"; | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error); | |||
// Here we check if user is attempting to log in | |||
if ($_SERVER['REQUEST_METHOD'] == "POST") { | |||
$statement = $conn->prepare( | |||
"select * from lauri_gallery_user where email = ? and " . | |||
"password_hash = SHA1(CONCAT(password_salt, ?))"); | |||
$statement->bind_param("ss", $_POST["email"], $_POST["password"]); | |||
$statement->execute(); | |||
$results = $statement->get_result(); | |||
$row = $results->fetch_assoc(); | |||
if (!$row) | |||
echo "Login failed!"; | |||
$_SESSION["user"] = $row; // Set user as logged in | |||
} | |||
// Here we check if the user is logged in | |||
if ($user = @$_SESSION["user"]) { // Extra lazy hack, use $user instead of $_SESSION["user"] from now on | |||
?> | |||
<h1>Hello <?=$user["display_name"];?></h1> | |||
<p> | |||
Add albums <a href="addalbum.php">here</a>. | |||
Upload images <a href="upload.php">here</a>. | |||
</p> | |||
My albums: | |||
<?php | |||
// Here we list user's albums | |||
$statement = $conn->prepare("select * from lauri_gallery_album where owner_id = ?"); | |||
$statement->bind_param("i", $user["id"]); | |||
$statement->execute(); | |||
?><ul><?php | |||
foreach ($statement->get_result() as $row) { | |||
?><li><a href="album.php?id=<?=$row['id']?>"><?=$row['name'];?></a> | |||
<a href="deletealbum.php?id=<?=$row['id']?>">[Delete]</a> | |||
</li><?php | |||
} | |||
?></ul> | |||
My uploads: | |||
<?php | |||
// To show images of the user | |||
$statement = $conn->prepare($SQL_IMAGES); | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
$statement->bind_param("i", $user["id"]); | |||
$statement->execute(); | |||
?><ul class="thumbnails"><?php | |||
foreach ($statement->get_result() as $row) { | |||
?><li> | |||
<img src="thumbnails/<?=$row['hash']?>" title="<?=$row['name'];?>"/> | |||
uploaded <?=$row['created'] ?> | |||
<div id="likes_<?=$row["id"]?>"> | |||
<?php | |||
require_once "common.php"; | |||
show_likes($row["id"]); // show_likes function is defined in common.php | |||
?> | |||
like this | |||
</div> | |||
</li><?php | |||
} | |||
?></ul><?php | |||
} else { | |||
?> | |||
<form method="post"> | |||
<input type="mail" name="email"/> | |||
<input type="password" name="password"/> | |||
<input type="submit" value="Log in!"/> | |||
</form> | |||
<?php | |||
} | |||
?> | |||
</source> | </source> | ||
Line 632: | Line 732: | ||
</source> | </source> | ||
== | == WEB-SHOP== | ||
==INDEX.PHP== | |||
<source lang="html5"> | <source lang="html5"> | ||
<?php | <?php | ||
require_once "config.php"; | require_once "config.php"; | ||
include "header.php"; // This includes <html><head></head><body> | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) | |||
die("Connection to database failed:" . | |||
$conn->connect_error); | |||
$conn->query("set names utf8"); // Support umlaut characters | |||
$ | if (!array_key_exists("timestamp", $_SESSION)) { | ||
$_SESSION["timestamp"] = date('l jS \of F Y h:i:s A'); | |||
} | |||
?> | |||
<h1>Honest Lauri's webshop</h1> | |||
<p> | |||
<button id="update_cart">Update shopping cart now!</button> | |||
<!-- We could actually move login and registration buttons to | |||
separate nav.php file and include it here --> | |||
<?php | |||
if (array_key_exists("user", $_SESSION) and $_SESSION["user"]) { | |||
// In case we put user id in the $_SESSION["user"] we need | |||
// to perform another SQL query to get the full name of the user: | |||
$results = $conn->query( | |||
"SELECT * FROM lauri_users WHERE id = " . $_SESSION["user"]); | |||
if (!$results) die("Query failed: (" . $conn->errno . ") " . $conn->error); | |||
$row = $results->fetch_assoc(); | |||
echo "Hello " . $row["salutation"] . " "; | |||
echo $row["first_name"] . " "; | |||
echo $row["last_name"]; | |||
// Oh how I'd like to do just: | |||
// print "Hello %(salutation)s %(first_name)s %(last_name)s" % $row | |||
?> <a href="orders.php">My Orders</a> <a href="logout.php">Log out</a> | |||
<?php | |||
} else { | |||
// Otherwise offer login fields and button | |||
?> | |||
<form action="login.php" method="post"> | |||
<input id="user" type="text" class="textboxes" name="user"/> | |||
<input type="password" class="textboxes topsecret" name="password"/> | |||
<input type="submit" value="Log in!"/> | |||
</form><?php | |||
} ?> | |||
<button id="remove_button" data-product_id="1">Remove item</button> | |||
<div id="shopping_cart"> | |||
This is initially empty | |||
</div> | |||
<a href="registration.php">Sign up!</a>. <a href="cart.php">Go to shopping cart</a>.</p> | |||
<p class="topsecret">NSA is monitoring you since <?=$_SESSION["timestamp"];?></p> | |||
<p>If you want any of these just call me ;)</p> | |||
<ul> | |||
<?php | |||
$results = $conn->query( | |||
"SELECT id,name,price FROM lauri_products;"); | |||
while ($row = $results->fetch_assoc()) { | |||
?> | |||
<li> | |||
<a href="description.php?id=<?=$row['id']?>"> | |||
<?=$row['name']?></a> | |||
<?=$row['price']?>EUR | |||
</li> | |||
<?php | |||
} | |||
$conn->close(); | |||
?> | |||
</ul> | |||
<?php include "footer.php" ?> | |||
</source> | |||
==CART.PHP== | |||
<source lang="html5"> | |||
<?php | |||
require_once "config.php"; | |||
session_start(); | |||
//include "header.php"; // This includes <html><head></head><body> | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | $conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | ||
$conn or die("Database connection failed:" . $conn->error); | |||
$conn->query("set names utf8"); // Support umlaut characters | |||
if ($_SERVER['REQUEST_METHOD'] == "POST") { | if ($_SERVER['REQUEST_METHOD'] == "POST") { | ||
// We are updating the cart contents | |||
" | $product_id = intval($_POST["id"]); | ||
" | if (array_key_exists($product_id, $_SESSION["cart"])) { | ||
$_SESSION["cart"][$product_id] += intval($_POST["count"]); | |||
} else { | |||
$_SESSION["cart"][$product_id] = intval($_POST["count"]); | |||
} | |||
if ($_SESSION["cart"][$product_id] <= 0) { | |||
unset($_SESSION["cart"][$product_id]); | |||
} | |||
} | |||
?> | |||
<!-- | |||
<h2>Products in shopping cart</h2> | |||
<a href="index.php">Back to product listing</a> | |||
<a href="placeorder.php">Place order</a> | |||
<p> | |||
--> | |||
<ul> | |||
<?php | |||
$results = $conn->query( | |||
"SELECT id,name,price FROM lauri_products;"); | |||
$results or die("Database query failed:" . $conn->error); | |||
while ($row = $results->fetch_assoc()) { | |||
$product_id = $row['id']; | |||
if (array_key_exists($product_id, $_SESSION["cart"])) { | |||
$count = $_SESSION["cart"][$product_id]; | |||
?> | |||
<li> | |||
<?=$count;?> items of | |||
<a href="description.php?id=<?=$product_id;?>"> | |||
<?=$row['name'];?></a> | |||
<?=$row['price'];?>EUR totals in <?= $row['price'] * $count; ?> EUR | |||
<form method="post"> | |||
<input type="hidden" name="id" value="<?=$product_id;?>"/> | |||
<input type="hidden" name="count" value="-1"/> | |||
<input type="submit" value="Remove"/> | |||
</form> | |||
</li> | |||
<?php | |||
} | |||
} | |||
$conn->close(); | |||
?> | |||
</ul> | |||
<?php // include "footer.php" ?> | |||
</source> | |||
==CONFIG.PHP== | |||
<source lang="html5"> | |||
<?php | |||
// This is site specific configuration! | |||
define("DB_SERVER", "localhost"); | |||
define("DB_USER", "test"); | |||
define("DB_PASS", "t3st3r123"); | |||
define("DB_NAME", "test"); | |||
define("DB_PREFIX", "lauri_"); | |||
?> | |||
</source> | |||
==DESCRIPTION.PHP== | |||
<source lang="html5"> | |||
<?php | |||
require_once "config.php"; | |||
include "header.php" ?> | |||
<a href="index.php">Back to product listing</a> | |||
<?php | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) | |||
die("Connection to database failed:" . | |||
$conn->connect_error); | |||
$conn->query("set names utf8"); // Support umlaut characters | |||
$statement = $conn->prepare( | |||
"SELECT `name`, `description`, `price` FROM" . | |||
" `lauri_products` WHERE `id` = ?"); | |||
$statement->bind_param("i", $_GET["id"]); | |||
$statement->execute(); | |||
$results = $statement->get_result(); | |||
$row = $results->fetch_assoc(); | |||
?> | |||
<span style="float:right;"><?=$row["price"];?>EUR</span> | |||
<h1><?=$row["name"];?></h1> | |||
<p> | |||
<?=$row["description"];?> | |||
</p> | |||
<form method="post" action="cart.php"> | |||
<input type="hidden" name="id" value="<?=$_GET["id"];?>"/> | |||
<input type="hidden" name="count" value="1"/> | |||
<input type="submit" value="Add to cart"/> | |||
</form> | |||
<?php include "footer.php" ?> | |||
</source> | |||
== FOOTER.PHP== | |||
<source lang="html5"> | |||
</div> | |||
<footer> | |||
<ul> | |||
<li>Phone: +372 5123 4567</li> | |||
<li><a href="http://facebook.com">Visit us on Facebook!</a></li> | |||
</ul> | |||
</footer> | |||
</body> | |||
</html> | |||
</source> | |||
==HEADER.PHP== | |||
<source lang="html5"> | |||
<?php | |||
// This will make it possible to use persistent $_SESSION at all | |||
session_start(); | |||
if (!array_key_exists("cart", $_SESSION)) { | |||
$_SESSION["cart"] = array(); | |||
// Here we store product it -> count mapping | |||
} | } | ||
?> | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
< | <meta charset="utf-8"/> | ||
<meta name="description" content="Introduction to this guy's website"> | |||
<title>Lauri's webshop</title> | |||
<link type="text/css" rel="stylesheet" href="css/style.css"/> | |||
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'> | |||
<script type="text/javascript" src="js/main.js"></script> | |||
</head> | |||
<body> | |||
<div id="content"> | |||
</source> | |||
==LOGIN.PHP== | |||
<source lang="html5"> | |||
<?php | |||
session_start(); | |||
// This is login.php, here we check if user provided proper credentials | |||
var_dump($_POST); // This is just to check that the data gets to server | |||
include "config.php"; | |||
// This is copy-paste from description.php! | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
?>< | if ($conn->connect_error) | ||
die("Connection to database failed:" . | |||
$conn->connect_error); | |||
$conn->query("set names utf8"); // Support umlaut characters | |||
$statement = $conn->prepare( | |||
"SELECT id, first_name FROM lauri_users | |||
WHERE email = ? AND password = PASSWORD(?)"); | |||
// This is the easiest way to store hashed passwords | |||
// DO NOT USE THIS IN PRODUCTION! | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
$statement->bind_param("ss", $_POST["user"], $_POST["password"]); // <-- | |||
$statement->execute(); | |||
$results = $statement->get_result(); | |||
$row = $results->fetch_assoc(); | |||
if($row) { | |||
$_SESSION["first_name"] = $row["first_name"]; // For lazy people | |||
$_SESSION["user"] = $row["id"]; // This just stores user row number! | |||
header('Location: index.php'); // This will redirect back to index | |||
} else { | } else { | ||
echo "Login failed (invalid username or password)"; | |||
} | |||
?> | |||
</source> | |||
==LOGOUT.PHP== | |||
<source lang="html5"> | |||
<?php | |||
session_start(); | |||
unset($_SESSION["user"]); | |||
header('Location: index.php'); // This will redirect back to index | |||
?> | |||
</source> | |||
==ORDERDETAILS.PHP== | |||
<source lang="html5"> | |||
<?php | |||
require_once "config.php"; | |||
include "header.php" ?> | |||
<a href="index.php">Back to product listing</a> | |||
<?php | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) | |||
die("Connection to database failed:" . | |||
$conn->connect_error); | |||
$conn->query("set names utf8"); // Support umlaut characters | |||
$statement = $conn->prepare( | |||
"SELECT | |||
`lauri_order_products`.`id` AS `order_product_id`, | |||
`lauri_order_products`.`product_id` AS `product_id`, | |||
`lauri_products`.`name` AS `product_name`, | |||
`lauri_order_products`.`unit_price` AS `order_product_unit_price`, | |||
`lauri_order_products`.`count` AS `order_product_count`, | |||
`lauri_order_products`.`unit_price` * `lauri_order_products`.`count` AS `subtotal` | |||
FROM | |||
`lauri_order_products` | |||
JOIN | |||
`lauri_products` | |||
ON | |||
`lauri_order_products`.`product_id` = `lauri_products`.`id` | |||
WHERE | |||
`lauri_order_products`.`order_id` = ? | |||
"); | |||
// This is orderdetail.php | |||
// The SQL code above is copy-paste from wiki, PHP code above is copy-paste from description.php | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
$statement->bind_param("i", $_GET["id"]); // TODO: Check that order belongs to $_SESSION["user"] !!! | |||
$statement->execute(); | |||
$results = $statement->get_result(); | |||
?> | |||
<h1>Order details</h1> | |||
<ul> | |||
<?php | |||
while ($row = $results->fetch_assoc()) { ?> | |||
<li> | |||
<?= $row["product_name"]; ?> | |||
<?= $row["order_product_count"]; ?>x | |||
<?= $row["order_product_unit_price"]; ?>EUR | |||
</li><?php | |||
} | |||
?> | |||
</source> | |||
==ORDERS.PHP== | |||
<source lang="html5"> | |||
<?php | |||
require_once "config.php"; | |||
include "header.php" ?> | |||
<a href="index.php">Back to product listing</a> | |||
<?php | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) | |||
die("Connection to database failed:" . $conn->connect_error); | |||
$conn->query("set names utf8"); | |||
// This is orders.php, again beginning copy-pasted from description.php | |||
$statement = $conn->prepare("SELECT * FROM `lauri_orders` WHERE `user_id` = ?"); | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
// TODO: If $_SESSION["user"] is nonsense, redirect to index.php! | |||
$statement->bind_param("i", $_SESSION["user"]); | |||
if (!$statement->execute()) die("Failed to execute statement"); | |||
$results = $statement->get_result(); | |||
?> | |||
<h1>Orders</h1> | |||
<ul> | |||
<?php | |||
while ($row = $results->fetch_assoc()) { ?> | |||
<li> | |||
<a href="orderdetail.php?id=<?= $row["id"]; ?>"> | |||
Order #<?= $row["id"]; ?> | |||
<?= $row["created"]; ?> | |||
<?= $row["shipping_address"]; ?> | |||
</a> | |||
</li><?php | |||
} | |||
?> | |||
</source> | |||
==PLACRORDER.PHP== | |||
<source lang="html5"> | |||
<?php | |||
// This is placeorder.php, this shall basically move cart contents to database as a new order | |||
// Copypaste from regsubmit.php follows: | |||
require_once "config.php"; | |||
include "header.php"; | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) | |||
die("Connection to database failed:" . | |||
$conn->connect_error); | |||
$conn->query("set names utf8"); // Support umlaut characters | |||
// TODO: If the shopping cart is empty it should not be possible to place an order! | |||
$_SESSION["cart"] or die("User has no items in the shopping cart!"); | |||
// This inserts row to orders table | |||
$statement = $conn->prepare("INSERT INTO `lauri_orders` (`user_id`) VALUES (?)"); | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
$statement->bind_param("i", $_SESSION["user"]); // User ID is the logged in user's ID | |||
if (!$statement->execute()) { | |||
die("Execute failed: (" . $statement->errno . ") " . $statement->error); | |||
} | |||
$order_id = $conn->insert_id; // This contains the ID for the inserted order | |||
// This inserts rows to order_products table | |||
$statement = $conn->prepare( | |||
"INSERT INTO `lauri_order_products` (`order_id`, `product_id`, `count`) VALUES (?,?,?)"); | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
foreach ($_SESSION["cart"] as $product_id => $count) { | |||
$statement->bind_param("iii", $order_id, $product_id, $count); | |||
if (!$statement->execute()) { | |||
die("Execute failed: (" . $statement->errno . ") " . $statement->error); | |||
} | |||
} | |||
// Here of course we should reset shopping cart: | |||
$_SESSION["cart"] = array(); | |||
header('Location: orders.php'); // This should redirect to orders page (which we haven't created yet) | |||
?> | |||
</source> | |||
==REGISTRATION.PHP== | |||
<source lang="html5"> | |||
<?php | |||
require_once "config.php"; | |||
include "header.php"; | |||
?> | ?> | ||
<input type=" | <h1>Register user account</h1> | ||
<input type="password" name="password"/> | |||
<input type=" | <form method="post" action="regsubmit.php"> | ||
</form> | <div> | ||
<label for="email">E-mail</label> | |||
<input type="email" name="email" required/> | |||
</div> | |||
<div> | |||
<label for="password">Password</label> | |||
<input type="password" name="password" required/> | |||
</div> | |||
<div> | |||
<select name="country"> | |||
<option value="ee">Estonia</option> | |||
<option value="lt">Latvia</option> | |||
<option value="lv">Lithuania</option> | |||
</select> | |||
</div> | |||
<div> | |||
<label for="phone">Telephone number</label> | |||
<input type="tel"/> | |||
</div> | |||
<div> | |||
<label for="vatin">VAT indication number</label> | |||
<input type="text" pattern="([A-Z0-9]{4,14})?$"/> | |||
</div> | |||
<div> | |||
<label for="dob">Date of birth</label> | |||
<input type="date" name="dob" placeholder="dd/mm/yyyy" required/> | |||
</div> | |||
<div> | |||
<label for="first_name">First name</label> | |||
<input type="text" name="first_name" required/> | |||
</div> | |||
<div> | |||
<label for="last_name">Last name</label> | |||
<input type="text" name="last_name" required/> | |||
</div> | |||
<div> | |||
<input type="submit"/> | |||
</div> | |||
</form> | |||
<?php include "footer.php" ?> | |||
</source> | |||
==REGSUBMIT.PHP == | |||
<source lang="html5"> | |||
<?php | <?php | ||
require_once "config.php"; | |||
include "header.php"; | |||
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME); | |||
if ($conn->connect_error) | |||
die("Connection to database failed:" . | |||
$conn->connect_error); | |||
$conn->query("set names utf8"); | |||
$statement = $conn->prepare( | |||
"INSERT INTO `lauri_users` ( | |||
`email`, | |||
`password`, | |||
`first_name`, | |||
`last_name`, | |||
`phone`, | |||
`dob`, | |||
`salutation`, | |||
`vatin`, | |||
`company`, | |||
`country`, | |||
`address`) | |||
VALUES (?, PASSWORD(?), ?, ?, ?, ?, ?, ?, ?, ?, ?)"); | |||
# whenever you get "call to a member function ... on a non-object" this means something | |||
# is failing **before** that line so you have to manually check for errors like this: | |||
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); | |||
$statement->bind_param("sssssssssss", | |||
$_POST["email"], | |||
$_POST["password"], | |||
$_POST["first_name"], | |||
$_POST["last_name"], | |||
$_POST["phone"], | |||
$_POST["dob"], | |||
$_POST["salutation"], | |||
$_POST["vatin"], | |||
$_POST["company"], | |||
$_POST["country"], | |||
$_POST["address"]); | |||
if ($statement->execute()) { | |||
echo "Registration was successful! <a href=\"index.php\">Back to main page</a>"; | |||
} else { | |||
if ($statement->errno == 1062) { | |||
// This will result in 200 OK | |||
echo "This e-mail is already registered"; | |||
} else { | |||
// This will result in 500 Internal server error | |||
die("Execute failed: (" . | |||
$statement->errno . ") " . $statement->error); | |||
} | |||
} | } | ||
?> | ?> | ||
</source> | |||
==UPLOAD.PHP== | |||
<source lang="html5"> | |||
<html> | |||
<body> | |||
<form method="post" enctype="multipart/form-data"> | |||
<input type="text" name="product_title"/> | |||
<input type="text" name="product_description"/> | |||
<input type="file" name="product_image" required/> | |||
<input type="file" name="product_thumbnail"/> | |||
<input type="submit"/> | |||
</form> | |||
<!-- You also need: | |||
mkdir uploads | |||
chmod 777 | |||
--> | |||
<?php | |||
if (array_key_exists("product_image", $_FILES)) { | |||
$finfo = finfo_open(FILEINFO_MIME_TYPE); | |||
$mimetype = finfo_file($finfo, $_FILES["product_image"]["tmp_name"]); | |||
if ($mimetype != "application/pdf") die("Go away!"); | |||
$checksum = sha1(file_get_contents( | |||
$_FILES["product_image"]["tmp_name"])) . "." . | |||
pathinfo($_FILES["product_image"]["name"], PATHINFO_EXTENSION); | |||
if (!file_exists("uploads/" . $checksum)) { | |||
copy( | |||
$_FILES["product_image"]["tmp_name"], | |||
"uploads/" . $checksum); | |||
} | |||
} | |||
?> | |||
<p>Mimetype was: <?= $mimetype; ?></p> | |||
<p>Checksum was: <a href="uploads/<?=$checksum;?>"><?=$checksum;?></a> | |||
<p>Filename was: <?=$_FILES["product_image"]["name"];?></p> | |||
<p>File stored at: <?=$_FILES["product_image"]["tmp_name"];?></p> | |||
</body> | |||
</html> | |||
</source> | |||
==STYLE.CSS== | |||
<source lang="html5"> | |||
input[type='password'] { | |||
color: red; | |||
} | |||
/* Apply font family to paragraphs */ | |||
p, ul, li, h1, h2, h, a { | |||
/* Roboto font works only if the font CSS is included from Google */ | |||
font-family: "Roboto", Verdana, Arial, sans-serif; | |||
} | |||
html, body { | |||
margin: 0; | |||
padding: 0; | |||
} | |||
body { | |||
padding: 0 1em; | |||
background-color: #aabbff; | |||
} | |||
#content, footer { /* This expects id="content" ;) */ | |||
margin: 0 auto; | |||
padding: 0 1em; | |||
max-width: 40em; | |||
border: 1px solid #888; | |||
background-color: white; | |||
} | |||
footer { | |||
color: #fff; | |||
background-color: #222; | |||
} | |||
img { /* This will look ugly tho! */ | |||
width: 800px; | |||
height: 100px; | |||
} | |||
</source> | |||
==MAIN.JS== | |||
<source lang="html5"> | |||
// In HTML we only have <button id="update_cart">Update cart</button> | |||
// Wait page to be loaded and then associate click event | |||
document.addEventListener("DOMContentLoaded", function() { | |||
document.querySelector("#update_cart").addEventListener( | |||
"click", updateCart | |||
); | |||
document.querySelector("#remove_button").addEventListener( | |||
"click", removeItem | |||
) | |||
}); | |||
function removeItem() { | |||
console.info("Going to remove product with id from cart:", this.dataset.product_id); | |||
var formData = new FormData(); | |||
formData.append("id", this.dataset.product_id); | |||
formData.append("count", -1); | |||
var request = new XMLHttpRequest(); | |||
request.open('POST', 'cart.php', true); | |||
request.send(formData); | |||
} | |||
// This only defines updateCart function, but it does not run it! | |||
function updateCart() { | |||
var request = new XMLHttpRequest(); | |||
request.open('GET', 'cart.php', true); | |||
// This is an example of callback | |||
request.onload = function() { | |||
// This function runs once response has been received | |||
if (request.status >= 200 && request.status < 400) { | |||
document.querySelector("#shopping_cart").innerHTML = | |||
request.responseText; | |||
} | |||
}; | |||
// This will only start the request | |||
request.send(); | |||
} | |||
</source> | </source> |
Latest revision as of 20:19, 5 June 2016
IMAGE GALLERY
INDEX.php
<?php
require_once "config.php";
include "header.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8");
?>
<h1 style="color:Purple ;font-family:Indie Flower; float:Center"><em><center>Sheela's Image#Gallery</center></em></h1>
<p>
<?php
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$statement = $conn->prepare(
"select * from Sheela_gallery_user where email = ? and " .
"password_hash = SHA1(CONCAT(password_salt, ?))");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("ss", $_POST["email"], $_POST["password"]);
$statement->execute();
$results = $statement->get_result();
$row = $results->fetch_assoc();
if (!$row)
echo "Login failed!";
$_SESSION["user"] = $row;
}
// Here we check if the user is logged in
if ($user = @$_SESSION["user"]) { // Extra lazy hack, use $user instead of $_SESSION["user"] from now on
?>
<h1>Hello <?=$user["display_name"];?></h1>
<p>
Add albums <a href="addalbum.php">here</a>.
Upload images <a href="upload.php">here</a>.
</p>
My albums:
<?php
// Here we list user's albums
$statement = $conn->prepare("select * from Sheela_gallery_album where owner_id = ?");
$statement->bind_param("i", $user["id"]);
$statement->execute();
?><ul><?php
foreach ($statement->get_result() as $row) {
?><li><a href="album.php?id=<?=$row['id']?>"><?=$row['name'];?></a>
<a href="deletealbum.php?id=<?=$row['id']?>">[Delete]</a>
</li><?php
}
?></ul>
My recent uploads:
<?php
// To show images of the user
$statement = $conn->prepare(
"select Sheela_gallery_image.id, Sheela_gallery_image.hash, Sheela_gallery_image.created " .
"from Sheela_gallery_image " .
"join Sheela_gallery_album " .
"on Sheela_gallery_album.id = Sheela_gallery_image.album_id " .
"where Sheela_gallery_album.owner_id = ? " .
"order by Sheela_gallery_image.created desc " .
"limit 2");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $user["id"]);
$statement->execute();
?><ul class="thumbnails"><?php
foreach ($statement->get_result() as $row) {
?><li>
<img src="thumbnails/<?=$row['hash']?>" title="<?=$row['name'];?>"/>
uploaded <?=$row['created'] ?> <?=$row["id"]?>
<?php
$statement = $conn->prepare(
"SELECT Sheela_gallery_user.display_name " .
"FROM Sheela_gallery_likes " .
"JOIN Sheela_gallery_user ON Sheela_gallery_likes.user_id = Sheela_gallery_user.id " .
"WHERE Sheela_gallery_likes.image_id = ?");
$statement->bind_param("i", $row["id"]);
$statement->execute();
$first = true; // First user shall not have comma prefixed
foreach ($statement->get_result() as $like) {
if (!$first) {
echo ", ";
}
echo $like["display_name"];
$first = false; // All other users have their nicknames comma prefixed
}
?>
like this
</li><?php
}
?></ul><?php
} else {
?>
<form method="post">
<input type="mail" name="email"/>
<input type="password" name="password"/>
<input type="submit" value="Log in!"/>
</form>
<?php
}
?>
<a href ="registration.php">Sign up</a>
<p>
<a href="upload.php">Upload Page </a>
<?php include "footer.php" ?>
LAURI-INDEX.PHP
<?php
include "header.php";
require_once "config.php";
$SQL_IMAGES = "
select
lauri_gallery_image.id,
lauri_gallery_image.hash,
lauri_gallery_image.created
from
lauri_gallery_image
join
lauri_gallery_album
on
lauri_gallery_album.id = lauri_gallery_image.album_id
where
lauri_gallery_album.owner_id = ?
order by
lauri_gallery_image.created desc
limit 2";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
// Here we check if user is attempting to log in
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$statement = $conn->prepare(
"select * from lauri_gallery_user where email = ? and " .
"password_hash = SHA1(CONCAT(password_salt, ?))");
$statement->bind_param("ss", $_POST["email"], $_POST["password"]);
$statement->execute();
$results = $statement->get_result();
$row = $results->fetch_assoc();
if (!$row)
echo "Login failed!";
$_SESSION["user"] = $row; // Set user as logged in
}
// Here we check if the user is logged in
if ($user = @$_SESSION["user"]) { // Extra lazy hack, use $user instead of $_SESSION["user"] from now on
?>
<h1>Hello <?=$user["display_name"];?></h1>
<p>
Add albums <a href="addalbum.php">here</a>.
Upload images <a href="upload.php">here</a>.
</p>
My albums:
<?php
// Here we list user's albums
$statement = $conn->prepare("select * from lauri_gallery_album where owner_id = ?");
$statement->bind_param("i", $user["id"]);
$statement->execute();
?><ul><?php
foreach ($statement->get_result() as $row) {
?><li><a href="album.php?id=<?=$row['id']?>"><?=$row['name'];?></a>
<a href="deletealbum.php?id=<?=$row['id']?>">[Delete]</a>
</li><?php
}
?></ul>
My uploads:
<?php
// To show images of the user
$statement = $conn->prepare($SQL_IMAGES);
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $user["id"]);
$statement->execute();
?><ul class="thumbnails"><?php
foreach ($statement->get_result() as $row) {
?><li>
<img src="thumbnails/<?=$row['hash']?>" title="<?=$row['name'];?>"/>
uploaded <?=$row['created'] ?>
<div id="likes_<?=$row["id"]?>">
<?php
require_once "common.php";
show_likes($row["id"]); // show_likes function is defined in common.php
?>
like this
</div>
</li><?php
}
?></ul><?php
} else {
?>
<form method="post">
<input type="mail" name="email"/>
<input type="password" name="password"/>
<input type="submit" value="Log in!"/>
</form>
<?php
}
?>
ADDALBUM.PHP
<?php
include "header.php";
require_once "config.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$statement = $conn->prepare(
"insert into Sheela_gallery_album(name, owner_id) values(?,?)");
$statement->bind_param("si", $_POST["album_name"], $_SESSION["user"]["id"]);
$statement->execute();
}
?>
<form method="post">
<p>Here you can create a new album, it's basically a group of images that are to be uploaded</p>
<label>Enter album name</label>
<input type="text" name="album_name"/>
<input type="submit"/>
</form>
LAURI-ADDALBUM.PHP
<?php
include "header.php";
require_once "config.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$statement = $conn->prepare(
"insert into lauri_gallery_album(name, owner_id) values(?,?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); // check all the errors!
$statement->bind_param("si", $_POST["album_name"], $_SESSION["user"]["id"]);
if (!$statement->execute()) die("Execute failed (" . $conn->errno . ") " . $conn->error); // check all the errors!
header("Location: album.php?id=" . mysqli_insert_id($conn)); // This will redirect to newly created album page
}
?>
<form method="post">
<p>Here you can create a new album, it's basically a group of images that are to be uploaded</p>
<label>Enter album name</label>
<input type="text" name="album_name"/>
<input type="submit"/>
</form>
ALBUM.PHP
<?php
include "header.php";
require_once "config.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
?>
Back to landing page <a href="index.php">here</a>.
Upload images <a href="upload.php">here</a>
Images of album:
ss<?php
// To show images of the album
$statement = $conn->prepare(
"select Sheela_gallery_image.hash, Sheela_gallery_image.created " .
"from Sheela_gallery_image " .
"where Sheela_gallery_image.album_id = ? " .
"order by Sheela_gallery_image.created desc");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $_GET["id"]);
$statement->execute();
?><ul><?php
foreach ($statement->get_result() as $row) {
?><li><img src="thumbnails/<?=$row['hash']?>"
title="<?=$row['name'];?>"/> uploaded <?=$row['created']?></li><?php
}
?></ul>
LAURI-ALBUM.PHP
<?php
include "header.php";
require_once "config.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
?>
Back to landing page <a href="index.php">here</a>.
Upload images <a href="upload.php">here</a>
Images of album:
<?php
// To show images of the album
$statement = $conn->prepare(
"select lauri_gallery_image.hash, lauri_gallery_image.created " .
"from lauri_gallery_image " .
"where lauri_gallery_image.album_id = ? " .
"order by lauri_gallery_image.created desc");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $_GET["id"]);
$statement->execute();
?><ul><?php
foreach ($statement->get_result() as $row) {
?><li><img src="thumbnails/<?=$row['hash']?>"
title="<?=$row['name'];?>"/> uploaded <?=$row['created']?></li><?php
}
?></ul>
COMMOM.PHP
<?php
function show_likes($image_id) {
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
$statement = $conn->prepare("
select id
from Sheela_gallery_like
where image_id = ? and user_id = ?");
$statement->bind_param("ii", $image_id, $_SESSION["user"]["id"]);
$statement->execute();
$result = $statement->get_result(); // Consume the results of the executed query
// Here we will check if user already likes this image
if ( $result->fetch_array() ) {
// we got a row -> user already likes this image
echo '<button onClick="unlike(' . $image_id . ');">Unlike!</button>';
} else {
// or if no rows -> user hasn't liked it yet
echo '<button onClick="like(' . $image_id . ');">Like!</button>';
}
$statement = $conn->prepare(
"SELECT Sheela_gallery_user.display_name " .
"FROM Sheela_gallery_like " .
"JOIN Sheela_gallery_user ON Sheela_gallery_like.user_id = Sheela_gallery_user.id " .
"WHERE Sheela_gallery_like.image_id = ?");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $image_id);
$statement->execute();
$first = true; // First user shall not have comma prefixed
foreach ($statement->get_result() as $like) {
if (!$first) {
echo ", ";
}
echo $like["display_name"];
$first = false; // All other users have their nicknames comma prefixed
}
};
?>
LAURI-COMMON.PHP
<?php
function show_likes($image_id) {
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
$statement = $conn->prepare("
select id
from lauri_gallery_like
where image_id = ? and user_id = ?");
$statement->bind_param("ii", $image_id, $_SESSION["user"]["id"]);
$statement->execute();
$result = $statement->get_result(); // Consume the results of the executed query
// Here we will check if user already likes this image
if ( $result->fetch_array() ) {
// we got a row -> user already likes this image
echo '<button onClick="unlike(' . $image_id . ');">Unlike!</button>';
} else {
// or if no rows -> user hasn't liked it yet
echo '<button onClick="like(' . $image_id . ');">Like!</button>';
}
$statement = $conn->prepare(
"SELECT lauri_gallery_user.display_name " .
"FROM lauri_gallery_like " .
"JOIN lauri_gallery_user ON lauri_gallery_like.user_id = lauri_gallery_user.id " .
"WHERE lauri_gallery_like.image_id = ?");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $image_id);
$statement->execute();
$first = true; // First user shall not have comma prefixed
foreach ($statement->get_result() as $like) {
if (!$first) {
echo ", ";
}
echo $like["display_name"];
$first = false; // All other users have their nicknames comma prefixed
}
};
?>
CONFIG.PHP
<?php
// This is site specific configuration! Do not commit this to Git!
define("DB_SERVER", "localhost");
define("DB_USER", "test");
define("DB_PASS", "t3st3r123");
define("DB_NAME", "test");
define("DB_PREFIX", "Sheela_");
?>
DELETEALBUM.PHP
<?php
include "header.php";
require_once "config.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
$statement = $conn->prepare(
"delete from Sheela_gallery_album where id = ?");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error); // check all the errors!
$statement->bind_param("i", $_GET["id"]);
if (!$statement->execute()) die("Execute failed (" . $conn->errno . ") " . $conn->error); // check all the errors!
header("Location: index.php");
FOOTER.PHP
</div>
<footer>
<ul>
<li>Phone: +372 1234 4567</li>
<li><a href="http://facebook.com">Visit us on Facebook!</a></li>
</ul>
</footer>
</body>
</html>
HEADER.PHP
<?php
session_set_cookie_params(0, '/~ssumathi', 'enos.itcollege.ee', 0, 1);
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="description" content="Introduction to this Image_Gallery">
<title>This goes into the titlebar</title>
<link type="text/css" rel="stylesheet" href="css/style.css"/>
<script type="text/javascript"src="js/main.js"></script>
</head>
<body>
<div id ="content">
LIKE.PHP
<?php
// like.php?image_id=123 will attempt to add like to an image for currenty logged in user
session_start();
require_once "config.php";
require_once "common.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
$statement = $conn->prepare("
insert into Sheela_gallery_like (image_id, user_id)
values (?, ?)");
$statement->bind_param("ii", $_GET["image_id"], $_SESSION["user"]["id"]);
$statement->execute();
show_likes($_GET["image_id"]); // This will simply return a fragment of HTML
?>
LOGOUT.PHP
<?php
session_start();
session_destroy();
unset($_SESSION["user"]);
header('Location: index.php'); // This will redirect back to index
REGISTRATION.PHP
<?php
require_once "config.php";
include "header.php";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
$statement = $conn->prepare(
"INSERT INTO `Sheela_gallery_user` (`email`, `password_salt`, `password_hash`, `display_name`) " .
"VALUES (?, ?, ?, ?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$salt = substr(str_shuffle(
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$statement->bind_param("ssss",
$_POST["email"],
$salt,
sha1($salt . $_POST["password"]),
$_POST["display_name"]);
if ($statement->execute()) {
header("Location: index.php");
} else {
if ($statement->errno == 1062) {
echo "This e-mail is already registered";
} else {
die("Execute failed: (" . $statement->errno . ") " . $statement->error);
}
}
}
?>
<form method="post"><!-- This form is submitted to the same reg.php file with POST method -->
<ul>
<li>e-mail: <input type="mail" name="email" value="<?=@$_POST['email'];?>" required/></li>
<li>password: <input type="password" name="password" pattern="[a-zA-Z0-9]{8,16}" title="Password has to be at least 8 characters" required/></li>
<li>nickname: <input type="text" name="display_name" placeholder="cute honeybunny" pattern="[a-z]{3,10}" required/></li>
</ul>
<input type="submit"/>
</form>
UPLOAD.PHP
<?php
include "header.php";
require_once "config.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if (array_key_exists("uploaded_image", $_FILES)) {
if ($_FILES["uploaded_image"]["error"] == 1) die("Too big image!"); // File size check
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $_FILES["uploaded_image"]["tmp_name"]);
if (strpos($mimetype, "image/") != 0) // This is basically mimetype.startswith("image/")
die("Go away! Only images allowed!");
$checksum = sha1(file_get_contents(
$_FILES["uploaded_image"]["tmp_name"])) . "." .
pathinfo($_FILES["uploaded_image"]["name"], PATHINFO_EXTENSION);
// Keep the original image in uploads/ folder
if (!file_exists("uploads/" . $checksum)) {
copy(
$_FILES["uploaded_image"]["tmp_name"],
"uploads/" . $checksum);
}
// Generate thumbnail, this assumes you have created thumbnails/ folder and set permissions to 777
if (!file_exists("thumbnails/" . $checksum)) {
$im = new Imagick("uploads/" . $checksum);
$im->thumbnailImage(128, 0); // Width of 128px and automatically determine height based on aspect ratio
$im->writeImage("thumbnails/" . $checksum);
}
// Generate smaller version of the image
if (!file_exists("small/" . $checksum)) {
$im = new Imagick("uploads/" . $checksum);
$im->thumbnailImage(960, 0); // Width of 960px and automatically determined height
$im->writeImage("small/" . $checksum);
}
// TODO: Check that specified album is owned by the currently logged in user (SQL select query!)
// something like this, if you find a matching row the upload permission is granted:
// select * from Sheela_gallery_album where owner_id = $_SESSION["user]["id"] and id = $_POST['album_id']
// These four lines are the new stuff!
$statement = $conn->prepare("insert into `Sheela_gallery_image` (`album_id`, `name`, `hash`) values (?,?,?)");
$statement->bind_param("iss", $_POST["album_id"], $_FILES["uploaded_image"]["name"], $checksum);
$statement->execute();
?>
<p>Mimetype was: <?= $mimetype; ?></p>
<p>Original was: <a href="uploads/<?=$checksum;?>"><?=$checksum;?></a>
<p>960px was: <a href="small/<?=$checksum;?>"><?=$checksum;?></a>
<p>Thumbnail was: <a href="thumbnails/<?=$checksum;?>"><?=$checksum;?></a>
<p>Filename was: <?=$_FILES["uploaded_image"]["name"];?></p>
<p>File stored at: <?=$_FILES["uploaded_image"]["tmp_name"];?></p>
<?php
}
?>
<form method="post" enctype="multipart/form-data">
<select name="album_id">
<?php
$statement = $conn->prepare("select id, name from Sheela_gallery_album where owner_id = ?");
$statement->bind_param("i", $_SESSION["user"]["id"]);
$statement->execute();
foreach ($statement->get_result() as $row) {
?>
<option value="<?=$row['id']?>"><?=$row['name']?></option>
<?php
}
?>
</select>
Select file for upload: <input id="file" type="file" name="uploaded_image" accept="image/*">
<input type="submit"/>
</form>
UNLIKE.PHP
<?php
// unlike.php?image_id=123 will attempt to remove a like
session_start();
require_once "config.php";
require_once "common.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) die("Connection to database failed:" . $conn->connect_error);
$statement = $conn->prepare("
delete from lauri_gallery_like
where image_id = ? and user_id = ?
limit 1");
$statement->bind_param("ii", $_GET["image_id"], $_SESSION["user"]["id"]);
$statement->execute();
show_likes( $_GET["image_id"]);
?>
LAURI-MAIN.JS
function like(image_id) {
var request = new XMLHttpRequest();
request.open('GET', 'like.php?image_id=' + image_id, true);
// This is an example of callback
request.onload = function() {
// This function runs once response has been received
if (request.status >= 200 && request.status < 400) {
document.querySelector("#likes_" + image_id).innerHTML =
request.responseText;
}
};
// This will only start the request
request.send();
}
function unlike(image_id) {
var request = new XMLHttpRequest();
request.open('GET', 'unlike.php?image_id=' + image_id, true);
// This is an example of callback
request.onload = function() {
// This function runs once response has been received
if (request.status >= 200 && request.status < 400) {
document.querySelector("#likes_" + image_id).innerHTML =
request.responseText;
}
};
// This will only start the request
request.send();
}
CSS-STYLE.CSS
ul.thumbnails {
list-style: none;
}
ul#thumbnails li {
float: left;
display: block;
width: 160px;
WEB-SHOP
INDEX.PHP
<?php
require_once "config.php";
include "header.php"; // This includes <html><head></head><body>
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8"); // Support umlaut characters
if (!array_key_exists("timestamp", $_SESSION)) {
$_SESSION["timestamp"] = date('l jS \of F Y h:i:s A');
}
?>
<h1>Honest Lauri's webshop</h1>
<p>
<button id="update_cart">Update shopping cart now!</button>
<!-- We could actually move login and registration buttons to
separate nav.php file and include it here -->
<?php
if (array_key_exists("user", $_SESSION) and $_SESSION["user"]) {
// In case we put user id in the $_SESSION["user"] we need
// to perform another SQL query to get the full name of the user:
$results = $conn->query(
"SELECT * FROM lauri_users WHERE id = " . $_SESSION["user"]);
if (!$results) die("Query failed: (" . $conn->errno . ") " . $conn->error);
$row = $results->fetch_assoc();
echo "Hello " . $row["salutation"] . " ";
echo $row["first_name"] . " ";
echo $row["last_name"];
// Oh how I'd like to do just:
// print "Hello %(salutation)s %(first_name)s %(last_name)s" % $row
?> <a href="orders.php">My Orders</a> <a href="logout.php">Log out</a>
<?php
} else {
// Otherwise offer login fields and button
?>
<form action="login.php" method="post">
<input id="user" type="text" class="textboxes" name="user"/>
<input type="password" class="textboxes topsecret" name="password"/>
<input type="submit" value="Log in!"/>
</form><?php
} ?>
<button id="remove_button" data-product_id="1">Remove item</button>
<div id="shopping_cart">
This is initially empty
</div>
<a href="registration.php">Sign up!</a>. <a href="cart.php">Go to shopping cart</a>.</p>
<p class="topsecret">NSA is monitoring you since <?=$_SESSION["timestamp"];?></p>
<p>If you want any of these just call me ;)</p>
<ul>
<?php
$results = $conn->query(
"SELECT id,name,price FROM lauri_products;");
while ($row = $results->fetch_assoc()) {
?>
<li>
<a href="description.php?id=<?=$row['id']?>">
<?=$row['name']?></a>
<?=$row['price']?>EUR
</li>
<?php
}
$conn->close();
?>
</ul>
<?php include "footer.php" ?>
CART.PHP
<?php
require_once "config.php";
session_start();
//include "header.php"; // This includes <html><head></head><body>
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
$conn or die("Database connection failed:" . $conn->error);
$conn->query("set names utf8"); // Support umlaut characters
if ($_SERVER['REQUEST_METHOD'] == "POST") {
// We are updating the cart contents
$product_id = intval($_POST["id"]);
if (array_key_exists($product_id, $_SESSION["cart"])) {
$_SESSION["cart"][$product_id] += intval($_POST["count"]);
} else {
$_SESSION["cart"][$product_id] = intval($_POST["count"]);
}
if ($_SESSION["cart"][$product_id] <= 0) {
unset($_SESSION["cart"][$product_id]);
}
}
?>
<!--
<h2>Products in shopping cart</h2>
<a href="index.php">Back to product listing</a>
<a href="placeorder.php">Place order</a>
<p>
-->
<ul>
<?php
$results = $conn->query(
"SELECT id,name,price FROM lauri_products;");
$results or die("Database query failed:" . $conn->error);
while ($row = $results->fetch_assoc()) {
$product_id = $row['id'];
if (array_key_exists($product_id, $_SESSION["cart"])) {
$count = $_SESSION["cart"][$product_id];
?>
<li>
<?=$count;?> items of
<a href="description.php?id=<?=$product_id;?>">
<?=$row['name'];?></a>
<?=$row['price'];?>EUR totals in <?= $row['price'] * $count; ?> EUR
<form method="post">
<input type="hidden" name="id" value="<?=$product_id;?>"/>
<input type="hidden" name="count" value="-1"/>
<input type="submit" value="Remove"/>
</form>
</li>
<?php
}
}
$conn->close();
?>
</ul>
<?php // include "footer.php" ?>
CONFIG.PHP
<?php
// This is site specific configuration!
define("DB_SERVER", "localhost");
define("DB_USER", "test");
define("DB_PASS", "t3st3r123");
define("DB_NAME", "test");
define("DB_PREFIX", "lauri_");
?>
DESCRIPTION.PHP
<?php
require_once "config.php";
include "header.php" ?>
<a href="index.php">Back to product listing</a>
<?php
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8"); // Support umlaut characters
$statement = $conn->prepare(
"SELECT `name`, `description`, `price` FROM" .
" `lauri_products` WHERE `id` = ?");
$statement->bind_param("i", $_GET["id"]);
$statement->execute();
$results = $statement->get_result();
$row = $results->fetch_assoc();
?>
<span style="float:right;"><?=$row["price"];?>EUR</span>
<h1><?=$row["name"];?></h1>
<p>
<?=$row["description"];?>
</p>
<form method="post" action="cart.php">
<input type="hidden" name="id" value="<?=$_GET["id"];?>"/>
<input type="hidden" name="count" value="1"/>
<input type="submit" value="Add to cart"/>
</form>
<?php include "footer.php" ?>
FOOTER.PHP
</div>
<footer>
<ul>
<li>Phone: +372 5123 4567</li>
<li><a href="http://facebook.com">Visit us on Facebook!</a></li>
</ul>
</footer>
</body>
</html>
HEADER.PHP
<?php
// This will make it possible to use persistent $_SESSION at all
session_start();
if (!array_key_exists("cart", $_SESSION)) {
$_SESSION["cart"] = array();
// Here we store product it -> count mapping
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="description" content="Introduction to this guy's website">
<title>Lauri's webshop</title>
<link type="text/css" rel="stylesheet" href="css/style.css"/>
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
<script type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div id="content">
LOGIN.PHP
<?php
session_start();
// This is login.php, here we check if user provided proper credentials
var_dump($_POST); // This is just to check that the data gets to server
include "config.php";
// This is copy-paste from description.php!
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8"); // Support umlaut characters
$statement = $conn->prepare(
"SELECT id, first_name FROM lauri_users
WHERE email = ? AND password = PASSWORD(?)");
// This is the easiest way to store hashed passwords
// DO NOT USE THIS IN PRODUCTION!
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("ss", $_POST["user"], $_POST["password"]); // <--
$statement->execute();
$results = $statement->get_result();
$row = $results->fetch_assoc();
if($row) {
$_SESSION["first_name"] = $row["first_name"]; // For lazy people
$_SESSION["user"] = $row["id"]; // This just stores user row number!
header('Location: index.php'); // This will redirect back to index
} else {
echo "Login failed (invalid username or password)";
}
?>
LOGOUT.PHP
<?php
session_start();
unset($_SESSION["user"]);
header('Location: index.php'); // This will redirect back to index
?>
ORDERDETAILS.PHP
<?php
require_once "config.php";
include "header.php" ?>
<a href="index.php">Back to product listing</a>
<?php
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8"); // Support umlaut characters
$statement = $conn->prepare(
"SELECT
`lauri_order_products`.`id` AS `order_product_id`,
`lauri_order_products`.`product_id` AS `product_id`,
`lauri_products`.`name` AS `product_name`,
`lauri_order_products`.`unit_price` AS `order_product_unit_price`,
`lauri_order_products`.`count` AS `order_product_count`,
`lauri_order_products`.`unit_price` * `lauri_order_products`.`count` AS `subtotal`
FROM
`lauri_order_products`
JOIN
`lauri_products`
ON
`lauri_order_products`.`product_id` = `lauri_products`.`id`
WHERE
`lauri_order_products`.`order_id` = ?
");
// This is orderdetail.php
// The SQL code above is copy-paste from wiki, PHP code above is copy-paste from description.php
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $_GET["id"]); // TODO: Check that order belongs to $_SESSION["user"] !!!
$statement->execute();
$results = $statement->get_result();
?>
<h1>Order details</h1>
<ul>
<?php
while ($row = $results->fetch_assoc()) { ?>
<li>
<?= $row["product_name"]; ?>
<?= $row["order_product_count"]; ?>x
<?= $row["order_product_unit_price"]; ?>EUR
</li><?php
}
?>
ORDERS.PHP
<?php
require_once "config.php";
include "header.php" ?>
<a href="index.php">Back to product listing</a>
<?php
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" . $conn->connect_error);
$conn->query("set names utf8");
// This is orders.php, again beginning copy-pasted from description.php
$statement = $conn->prepare("SELECT * FROM `lauri_orders` WHERE `user_id` = ?");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
// TODO: If $_SESSION["user"] is nonsense, redirect to index.php!
$statement->bind_param("i", $_SESSION["user"]);
if (!$statement->execute()) die("Failed to execute statement");
$results = $statement->get_result();
?>
<h1>Orders</h1>
<ul>
<?php
while ($row = $results->fetch_assoc()) { ?>
<li>
<a href="orderdetail.php?id=<?= $row["id"]; ?>">
Order #<?= $row["id"]; ?>
<?= $row["created"]; ?>
<?= $row["shipping_address"]; ?>
</a>
</li><?php
}
?>
PLACRORDER.PHP
<?php
// This is placeorder.php, this shall basically move cart contents to database as a new order
// Copypaste from regsubmit.php follows:
require_once "config.php";
include "header.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8"); // Support umlaut characters
// TODO: If the shopping cart is empty it should not be possible to place an order!
$_SESSION["cart"] or die("User has no items in the shopping cart!");
// This inserts row to orders table
$statement = $conn->prepare("INSERT INTO `lauri_orders` (`user_id`) VALUES (?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("i", $_SESSION["user"]); // User ID is the logged in user's ID
if (!$statement->execute()) {
die("Execute failed: (" . $statement->errno . ") " . $statement->error);
}
$order_id = $conn->insert_id; // This contains the ID for the inserted order
// This inserts rows to order_products table
$statement = $conn->prepare(
"INSERT INTO `lauri_order_products` (`order_id`, `product_id`, `count`) VALUES (?,?,?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
foreach ($_SESSION["cart"] as $product_id => $count) {
$statement->bind_param("iii", $order_id, $product_id, $count);
if (!$statement->execute()) {
die("Execute failed: (" . $statement->errno . ") " . $statement->error);
}
}
// Here of course we should reset shopping cart:
$_SESSION["cart"] = array();
header('Location: orders.php'); // This should redirect to orders page (which we haven't created yet)
?>
REGISTRATION.PHP
<?php
require_once "config.php";
include "header.php";
?>
<h1>Register user account</h1>
<form method="post" action="regsubmit.php">
<div>
<label for="email">E-mail</label>
<input type="email" name="email" required/>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" required/>
</div>
<div>
<select name="country">
<option value="ee">Estonia</option>
<option value="lt">Latvia</option>
<option value="lv">Lithuania</option>
</select>
</div>
<div>
<label for="phone">Telephone number</label>
<input type="tel"/>
</div>
<div>
<label for="vatin">VAT indication number</label>
<input type="text" pattern="([A-Z0-9]{4,14})?$"/>
</div>
<div>
<label for="dob">Date of birth</label>
<input type="date" name="dob" placeholder="dd/mm/yyyy" required/>
</div>
<div>
<label for="first_name">First name</label>
<input type="text" name="first_name" required/>
</div>
<div>
<label for="last_name">Last name</label>
<input type="text" name="last_name" required/>
</div>
<div>
<input type="submit"/>
</div>
</form>
<?php include "footer.php" ?>
REGSUBMIT.PHP
<?php
require_once "config.php";
include "header.php";
$conn = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error)
die("Connection to database failed:" .
$conn->connect_error);
$conn->query("set names utf8");
$statement = $conn->prepare(
"INSERT INTO `lauri_users` (
`email`,
`password`,
`first_name`,
`last_name`,
`phone`,
`dob`,
`salutation`,
`vatin`,
`company`,
`country`,
`address`)
VALUES (?, PASSWORD(?), ?, ?, ?, ?, ?, ?, ?, ?, ?)");
# whenever you get "call to a member function ... on a non-object" this means something
# is failing **before** that line so you have to manually check for errors like this:
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("sssssssssss",
$_POST["email"],
$_POST["password"],
$_POST["first_name"],
$_POST["last_name"],
$_POST["phone"],
$_POST["dob"],
$_POST["salutation"],
$_POST["vatin"],
$_POST["company"],
$_POST["country"],
$_POST["address"]);
if ($statement->execute()) {
echo "Registration was successful! <a href=\"index.php\">Back to main page</a>";
} else {
if ($statement->errno == 1062) {
// This will result in 200 OK
echo "This e-mail is already registered";
} else {
// This will result in 500 Internal server error
die("Execute failed: (" .
$statement->errno . ") " . $statement->error);
}
}
?>
UPLOAD.PHP
<html>
<body>
<form method="post" enctype="multipart/form-data">
<input type="text" name="product_title"/>
<input type="text" name="product_description"/>
<input type="file" name="product_image" required/>
<input type="file" name="product_thumbnail"/>
<input type="submit"/>
</form>
<!-- You also need:
mkdir uploads
chmod 777
-->
<?php
if (array_key_exists("product_image", $_FILES)) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $_FILES["product_image"]["tmp_name"]);
if ($mimetype != "application/pdf") die("Go away!");
$checksum = sha1(file_get_contents(
$_FILES["product_image"]["tmp_name"])) . "." .
pathinfo($_FILES["product_image"]["name"], PATHINFO_EXTENSION);
if (!file_exists("uploads/" . $checksum)) {
copy(
$_FILES["product_image"]["tmp_name"],
"uploads/" . $checksum);
}
}
?>
<p>Mimetype was: <?= $mimetype; ?></p>
<p>Checksum was: <a href="uploads/<?=$checksum;?>"><?=$checksum;?></a>
<p>Filename was: <?=$_FILES["product_image"]["name"];?></p>
<p>File stored at: <?=$_FILES["product_image"]["tmp_name"];?></p>
</body>
</html>
STYLE.CSS
input[type='password'] {
color: red;
}
/* Apply font family to paragraphs */
p, ul, li, h1, h2, h, a {
/* Roboto font works only if the font CSS is included from Google */
font-family: "Roboto", Verdana, Arial, sans-serif;
}
html, body {
margin: 0;
padding: 0;
}
body {
padding: 0 1em;
background-color: #aabbff;
}
#content, footer { /* This expects id="content" ;) */
margin: 0 auto;
padding: 0 1em;
max-width: 40em;
border: 1px solid #888;
background-color: white;
}
footer {
color: #fff;
background-color: #222;
}
img { /* This will look ugly tho! */
width: 800px;
height: 100px;
}
MAIN.JS
// In HTML we only have <button id="update_cart">Update cart</button>
// Wait page to be loaded and then associate click event
document.addEventListener("DOMContentLoaded", function() {
document.querySelector("#update_cart").addEventListener(
"click", updateCart
);
document.querySelector("#remove_button").addEventListener(
"click", removeItem
)
});
function removeItem() {
console.info("Going to remove product with id from cart:", this.dataset.product_id);
var formData = new FormData();
formData.append("id", this.dataset.product_id);
formData.append("count", -1);
var request = new XMLHttpRequest();
request.open('POST', 'cart.php', true);
request.send(formData);
}
// This only defines updateCart function, but it does not run it!
function updateCart() {
var request = new XMLHttpRequest();
request.open('GET', 'cart.php', true);
// This is an example of callback
request.onload = function() {
// This function runs once response has been received
if (request.status >= 200 && request.status < 400) {
document.querySelector("#shopping_cart").innerHTML =
request.responseText;
}
};
// This will only start the request
request.send();
}