Exam 2023-01-14
Here you find sample answers and marking guidelines to the questions on the exam 2023-01-14.
Peter will not visit the exam. If you find any question unclear, ask an exam supervisor (tentavakt in Swedish) to call Peter, and he will try to clarify.
Max score is 30 points:
- For grade 3, 40% of max score (12 points) is required
- For grade 4, 60% of max score (18 points) is required
- For grade 5, 80% of max score (24 points) is required
You are not allowed to use any aids except:
- The computer you sit at to only enter answers to the questions on this exam
- A dictionary to translate to/from English from/to your native language
- Pen and paper to sketch with (should not be submitted)
Write your answers in either English or Swedish. If you write your answers in Swedish, make sure to not introduce any translation confusement. Write proper sentences (spelling, upper/lower case characters, punctuation, etc.). Answers that do not do this good enough/are vague/are not understandable will not receive full score on the questions.
Answers that are more or less copies of sample answers given to you or copies of text found somewhere else will be rewarded 0 points. Use your own words to answer the questions.
Good luck!
HTTP
Question 1 (1p)
Question
Name the method one should use in HTTP when the request is about:
- Retrieving a resource
- Creating a new resource
- Updating a resource
Note: This question is about HTTP when used properly, and has nothing to do with HTML, web browsers, nor websites.
You will get:
- 0.33 points for each correct name (spelling must be correct)
Sample answer
GET
POST
PUT
Marking guidelines
- 0.33 points for each correct name (spelling must be correct)
Question 2 (1p)
Question
In HTTP, explain what application/x-www-form-urlencoded
is, and when it's used.
Note: This question is about HTTP when used properly, and has nothing to do with HTML, web browsers, nor websites.
Sample answer
application/x-www-form-urlencoded
is a name of a data format. It can be used as value for headers in HTTP requests and HTTP responses, for example the Accept
header and the Content-Type
header.
Marking guidelines
- 0.5 points for explaining what it is (data format/MIME type)
- 0.5 points for when it's used
- -0.1 points for writing something incorrect or confusing
Question 3 (1p)
Question
In HTTP, what would be a good URI one can use to delete the blogpost with id 175
?
Note: This question is about HTTP when used properly, and has nothing to do with HTML, web browsers, nor websites.
Sample answer
In HTTP, the URI should identify the resource the request is about, so the URI could for example be /blogposts/175
.
Marking guidelines
- 1 point for a URI only identifying the resource to be deleted, and nothing else
- -0.25 points for using an
id
placeholder in the URI (HTTP don't contain the placeholder concept, only some web frameworks do that)
Question 4 (1p)
Question
Write the HTTP status code for the following reason phrases:
- Internal Server Error
- Not Found
- OK
- Bad Request
Note: This question is about HTTP when used properly, and has nothing to do with HTML, web browsers, nor websites.
You'll get:
- 0.25 points for each correct answer
Sample answer
500
404
200
400
Marking guidelines
- 0.25 points for each correct answer
HTML
Question 5 (1p)
Question
Place the lines of code below in such order that they form a valid HTML5 document (only place one line of code in each box).
<html>
<h1>Welcome!</h1>
</body>
<head>
</head>
<title>Welcome!</title>
<!DOCTYPE html>
</html>
<body>
Note: All must be correct to get points on this question.
Sample answer
<!DOCTYPE html>
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>
Marking guidelines
- 1 point for all in correct order
Question 6 (1p)
Question
When writing an HTML tutorial on a website, one often wants to write tags like <p>
that are shown as text, instead of being interpreted as a paragraph element by the web browser. Explain what you need to do to make the web browser display the text <p>
instead of interpreting it as the start tag for a paragraph.
Note: This question is only about HTML, and has nothing to do with Handlebars.
Sample answer
You need to write <
and >
as their character entities instead, since these characters have special meaning in HTML (they are part of the syntax for tags). So you would write:
<p>
To make the web browser display:
<p>
Marking guidelines
- 0.9 points for saying
<
and>
needs to be written as their character entities/"escaped" - 0.1 points for showing that you know how character entities are written (doesn't need to be perfect)
Question 7 (1p)
Question
Write the name of an HTML tag that can be placed in the <head>
element and that causes the web browser to send an HTTP request when it receives the HTML code for that tag.
Note: Just write the name of the tag; do not include <
and >
.
Sample answer
link
Marking guidelines
- 1 point for a valid tag name
Example of wrong tags
Some students answered img
. That is wrong, because the <head>
element should only contain meta information about the webpage, and not content.
Some students answered a
. That is wrong for the same reason as img
. Also, an <a>
element does not cause the web browser to send a HTTP request when it receives the HTML code for it, but when the user clicks on it, so it's also wrong answer for that reason.
Question 8 (2p)
Question
Name 4 different block elements in HTML.
Note: Just write the name of the tag; do not include <
and >
.
You'll get:
- 0.5 points for each correct answer (spelling needs to be correct)
- -0.25 points for each incorrect answer
- At lest 0 points on the question
Sample answer
h1
p
ul
div
Marking guidelines
- 0.5 points for each correct answer (spelling needs to be correct)
- -0.25 points for each incorrect answer
- At lest 0 points on the question
Question 9 (1p)
Question
If a user comes to a website with the form below and submits it without making any changes to it, what would the URI of the request look like? Write the URI as your answer.
<form action="/sum" method="GET">
Number 1: <input type="number" name="x" value="123">
Number 2: <input type="number" name="y" value="456">
<input type="submit" value="Compute sum!">
</form>
Sample answer
/sum?x=123&y=456
Marking guidelines
- 0.5 points for correct
x
name and value (123
) - 0.5 points for correct
y
name and value (456
) - Point reductions for errors:
- -0.1 points for surrounding value with quotes
- -0.1 points for using
&&
or.
instead of&
- -0.25 points for missing
/sum
in the beginning - -0.25 points for not having
?
Question 10 (1p)
Question
To make a webpage display some text as a header, you can use the <h1>
element:
<h1>Sunny weather this weekend!</h1>
Another solution is to use a <div>
element that you then style to look like a header using CSS. Explain why it's better to use the <h1>
solution instead of the <div>
+ CSS solution.
Sample answer
The purpose of HTML is to mark up what type of data different text represents. <h1>
will mark the text as a header, so search engines, text to speech tools, etc. know this and can function properly. That information would be lost if you used the <div>
+ CSS solution instead, so search engines and other tools will not be able to understand that that part of the text on the webpage is a header.
Extra info
<div>
has no semantic meaning at all in HTML, and should only be used in those cases we need extra block elements in our code to be able to implement the GUI we want using CSS.
Marking guidelines
- 1 point for the
<div>
+ CSS solution is missing the semantic meaning of the text
CSS
Question 11 (1p)
Question
Name and describe 2 different CSS properties of your choice except color
. For each, provide also an example of a value it can have, and explain the result of using the property with that value.
Sample answer
The CSS property background-color
determines which background color the element should have. For example, the value red
would give the element a red background.
The CSS property font-size
determines how big the text in the element should be. For example, the value 16px
would make the text in the element 16 pixels big.
Marking guidelines
- 1 point for an answer that is largely correct
- Point reductions for errors:
- -0.5 points for only one good declaration
- -0.25 points for no description of the result of applying the value to the property
Question 12 (1p)
Question
What color will the text in the paragraph in the HTML code below have?
<style>
p{
color: red;
}
#p{
color: green;
}
.p{
color: blue;
}
</style>
<p>Some text.</p>
Sample answer
green
Marking guidelines
- 1 point for a correct answer
Question 13 (1p)
Question
Here is some CSS code:
div div#em.p{
width: 50%;
}
Write HTML code that contains a match for the CSS selector in the code above. Write as little HTML code as possibly (don't write any extra elements or attributes that are not needed).
Note: You should only write the HTML code found in the <body>
element (including the <body>
element), you should not write the code for an entire HTML document.
Sample answer
<body>
<div>
<div id="em" class="p">I'm selected!</span>
</div>
</body>
Marking guidelines
- For answers that are close to correct:
- 0.5 points for
<div>
in<body>
- 0.5 points for
<div id="em" class="p">
in<div>
- Point reductions for errors:
- -0.1 points for each unnecessary HTML element
- -0.1 points for each unnecessary HTML attribute
- -0.25 points for each wrong value in/missing HTML attribute
- -0.5 points for syntax error
- 0.5 points for
Question 14 (1p)
Question
Write a CSS selector that selects the element in the HTML code below that contains the text SELECT ME
. The selector should select only that element, and no other.
<body>
<p class="p">Here is <span class="s">SELECT ME</span> <span>some text</span>.</p>
<div class="p">Here is some more text, <span class="s">and some more</span>.</div>
<p>Here is <span class="s">some other</span> text.</p>
</body>
Sample answer
p.p .s
Marking guidelines
- 1 point for an answer that works
Website
Question 15 (2p)
Question
On a website, when a none-logged in user tries to access a page only logged in users should be able to access, the user is redirected to the login page. When the user has logged in on the login page, she is currently always taken to the start page.
Alice is assigned the task to change this, so the user instead comes to the page she first tried to access (the one she was redirected from) after she has successfully logged in. There exist different ways this functionality can be implemented. Suggest the best way you can think of to Alice.
Sample answer
When redirecting the user to the login page, the web application needs to remember the URI for the page the user was on, so the web application later can redirect the user back to that page using that URI after she has successfully logged in. That URI can be remembered in different ways. The best way is to simply to remember it in a query string parameter when redirecting the user to the login page. That way, no additional data need to be stored neither on the client or the server, and users can bookmark the login page leading to a specific page after having logged in.
Marking guidelines
- 2 points for storing the "redirect back" URI in a query string parameter
OR:
- 1.5 points for suggesting another way to store the "redirect back" URI that the server has access to
Question 16 (1p)
Question
On a website containing blogposts spread out over different pages using pagination, the Handlebars code below in a view file is used to show a link to the current page the user is on:
<a href="/projects/pages/{{currentPage}}">{{currentPage}}</a>
The currentPage
value is a number that comes from the model when the Handlebars view is rendered, and all works good.
Bob is then assigned the task to add a link to the next page with blogposts. To do that, Bob changes the code above to:
<a href="/projects/pages/{{currentPage}}">{{currentPage}}</a>
<a href="/projects/pages/{{currentPage + 1}}">{{currentPage + 1}}</a>
Will this work? If yes, then state so. If no, then explain what's wrong, and explain what Bob can do to make the code work as it should.
Sample answer
We can't use arbitrary JavaScript expressions in Handlebars expressions, so {{a + b}}
in Handlebars doesn't work. Instead, Bob should add currentPage + 1
to the model (in the JS code), for example in a property called nextPage
, and then in the Handlebar file use:
<a href="/projects/pages/{{currentPage}}">{{currentPage}}</a>
<a href="/projects/pages/{{nextPage}}">{{nextPage}}</a>
Marking guidelines
- 0.5 points for explaining what's wrong
- 0.5 points for suggesting how to solve it
Question 17 (1p)
Question
On a website, give an example of something that is better stored in a cookie than in the user's session.
Sample answer
Since sessions are short lived, they can't be used to remember information about the user that survives for a long time (for example when visiting the website two different days). But with cookies, such information can be remembered for a long time, so if the website is a store where users can put products in their online basket, then storing those products in a cookie instead of the session can be beneficial (if you want that information to be remembered for long).
Marking guidelines
- 1 point for a valid example
OR:
- 0.5 points for a valid example that doesn't explain what to store in the cookie
Security
Question 18 (1p)
Question
On a website where only the admin should be able to login and delete resources, the following Express code is used to handle requests for deleting a blogpost with a specific id (request.session.isLoggedIn
is true
when the user is logged in as the admin, and false
otherwise):
//...
app.post('/blogposts/:id/delete', function(request, response){
const id = request.params.id
if(!request.session.isLoggedIn){
response.redirect('/login')
}
const query = "DELETE FROM blogposts WHERE id = ?"
const values = [id]
db.run(query, values, function(error){
if(error){
response.render("internal-error.hbs")
}else{
response.redirect('/blogposts')
}
})
})
//...
Is the code good or bad? If yes, then justify why it's good. If bad, then explain why it's bad, and suggest how the code should change to become better.
Sample answer
The code is bad. If someone sends a POST request to /blogposts/45/delete
without being logged in, the blogpost with id 45
will still be deleted, since the code execution doesn't stop at line 8, but the rest of the code in the function is executed as well. A return
statement is needed on line 8, or the rest of the code in the function needs to be put in an else
statement.
Marking guidelines
- 0.5 points for explaining the authorization bug that exist
- 0.5 points for suggesting how to fix the bug
Question 19 (2p)
Question
On a website where the admin can create blogposts, an SQLite table is used to store all the blogposts. The table looks like this (content
is not shown, since that one is quite long, and not all rows are shown):
keyword | title | content | isPublished |
---|---|---|---|
html | HTML is fun! | ... | 1 |
css | CSS is fun too! | ... | 0 |
js | JS is most fun! | ... | 0 |
The idea is that a user should only be able to read the blogposts that have the value 1
for isPublished
.
When receiving an HTTP request to send back a blogpost with a specific keyword
, it is handled like this:
app.js
app.get('/blogposts/:keyword', function(request, response){
const keyword = request.params.keyword
const query = "SELECT * FROM blogposts WHERE isPublished = 1 AND keyword = '"+keyword+"'"
db.get(query, function(error, blogpost){
// Let us assume no database error occurred, so we ignore that.
const model = {
blogpost
}
response.render('blogpost.hbs', model)
})
})
views/blogpost.hbs
<h1>{{blogpost.title}}</h1>
<p>{{blogpost.content}}</p>
As your answer, write a URL a hacker can send to read a blogpost that hasn't been published yet (for example a URL that would send back the blogpost with keyword css
).
Sample answer
/blogposts/' OR keyword='css
Marking guidelines
- 2 points for an answer that largely works
- -0.5 points for each error in an answer that almost works, such as:
- Not have inserted single quotes correct, e.g.
/blogposts/ -1 OR keyword=css
- Not have inserted single quotes correct, e.g.
Question 20 (1p)
Question
On a website where only the admin should be able to create new blogposts, the following code is used (request.session.isLoggedIn
is true
when the user is logged in as the admin, and false
otherwise):
app.js:
//...
app.get('/blogposts/create', function(request, response){
const model = {
isLoggedIn: request.session.isLoggedIn
}
response.render('create-blogpost.hbs', model)
})
app.post('/blogposts/create', function(request, response){
const title = request.body.title
const content = request.body.content
const query = "INSERT INTO blogposts (title, content) VALUES (?, ?)"
const values = [title, content]
db.run(query, values, function(error){
if(error){
response.render('internal-server-error.hbs')
}else{
response.redirect('/blogposts/'+this.lastID)
}
})
})
//...
views/create-blogpost.hbs:
{{#if isLoggedIn}}
<form method="POST" action="/blogposts/create">
Title: <input type="text" name="title">
Content: <input type="text" name="content">
<input type="submit" value="Create">
</form>
{{else}}
<p>Error: have to be logged in to see the create blogpost form.</p>
{{/if}}
Is this part of the website implemented in a secure way? Justify your answer.
Sample answer
No, that part of the website is not implemented in a good way; anyone can send a POST request to /blogposts/create
to create a new blogpost. Sure, only the admin can retrieve the create blogpost form, but that doesn't stop a hacker from being able to send an equivalent POST request from his own computer.
Marking guidelines
- 1 point for correct answer
OR:
- 0.5 points for correct answer and stating other things as weaknesses without explaining how/being incorrect about those
Database
Question 21 (1p)
Question
Below is the table humans
found in an SQLite database (not all rows are shown).
id | name | age |
---|---|---|
1 | Alcie | 10 |
2 | Bob | 20 |
3 | Claire | 15 |
Write an SQL query that sets name
to Alice
for all humans that currently has the name Alcie
.
Note: Don't use placeholders, like ?
, in your query. You don't need to worry about SQL injections, since this is a pure database question, and has nothing to do with web applications.
Sample answer
UPDATE humans SET name = "Alice" WHERE name = "Alcie"
(in SQLite, when testing for equality, both =
and ==
can be used)
Marking guidelines
- 1 point for an answer that is largely correct
OR:
- 0.5 points for a query that contains most required SQL parts, but in wrong order
Point reductions for errors:
- -0.1 points for updating the name to
Alicie
(it should be updated toAlice
) - -0.1 points using
Alice
in theWHERE
clause - -0.1 points for not using quotes around strings
Question 22 (1p)
Question
Below is the table humans
found in an SQLite database (not all rows are shown).
id | name | age |
---|---|---|
1 | Alice | 10 |
2 | Bob | 20 |
3 | Claire | 15 |
Write an SQL query that deletes all humans that are younger than 18
(those who are 18
should not be deleted).
Note: Don't use placeholders, like ?
, in your query. You don't need to worry about SQL injections, since this is a pure database question, and has nothing to do with web applications.
Sample answer
DELETE FROM humans WHERE age < 18
Marking guidelines
- 1 point for an answer that is largely correct
OR:
- 0.5 points for a query that contains most required SQL parts, but in wrong order
Point reductions for errors:
- -0.1 points for using
DELETE something FROM
, or onlyDELETE
, instead ofDELETE FROM
- -0.25 points for writing JavaScript code that contains a syntax error
JavaScript
Question 23 (1p)
Question
Implement the JavaScript function getProductUpTo(lastFactor)
, that receives an integer as argument, and returns the product of the integers between 1
and the integer it receives (including 1
and the received integer).
Sample usage:
getProductUpTo(3) // --> 6 (1 * 2 * 3)
getProductUpTo(5) // --> 120 (1 * 2 * 3 * 4 * 5)
getProductUpTo(1) // --> 1
Sample answer
function getProductUpTo(lastFactor){
let product = 1
for(let factor=1; factor<=lastFactor; factor++){
product *= factor
}
return product
}
Marking guidelines
- 1 point for an answer that largely works
- Point reduction for small mistakes:
- -0.1 points for using global variable
- -0.1 points for using bad name on variable
- -0.1 points for
product
starting on0
- -0.1 points for iteration starting on
0
instead of1
OR:
- 0.25 points for iterating over correct values
Question 24 (1p)
Question
Implement the JavaScript function areAll5(numbers)
, that receives an array with numbers and returns:
true
if all the values in the array is5
false
otherwise
Sample usage:
areAll5([3, 7, 1, 8]) // --> false
areAll5([5, 3, 5, 5]) // --> false
areAll5([5, 5, 5]) // --> true
areAll5([]) // --> true
(if the array is empty, then returning true
is what makes most sense, so that's how your implementation should work as well)
Sample answer
function areAll5(numbers){
for(const number of numbers){
if(number != 5){
return false
}
}
return true
}
Marking guidelines
- 1 point for an answer that largely works
- Point reduction for smaller mistakes:
- -0.1 points for using global variable
- -0.25 points for iterating over indexes instead of values
OR:
- 0.25 points for correctly using the for of loop with good names
Question 25 (2p)
Question
In JavaScript, a movie with a title, a category and a runtime (in minutes) can be represented as an object like this:
const movie = {
title: "Dumb and Dumber",
category: "comedy"
runtimeInMinutes: 106
}
Implement the function getMinutesToWatchMoviesInCategory(movies, category)
, which receives an array with movie objects and a category, and returns the number of minutes it takes to watch all the movies that has that category.
Sample usage:
getMinutesToWatchMoviesInCategory([
{title: "Dumb and Dumber", category: "comedy" runtimeInMinutes: 106},
{title: "Shrek", category: "comedy" runtimeInMinutes: 90},
{title: "Titanic", category: "drama" runtimeInMinutes: 195},
{title: "Shrek 2", category: "comedy" runtimeInMinutes: 92},
], "comedy") // --> 288 (106 + 90 + 92)
Sample answer
function getMinutesToWatchMoviesInCategory(movies, category){
let minutes = 0
for(const movie of movies){
if(movie.category == category){
minutes += movie.runtimeInMinutes
}
}
return minutes
}
Marking guidelines
- 2 points for an answer that largely works
- Point reduction for smaller mistakes:
- -0.25 points for iterating over indexes instead of values
Question 26 (1p)
Question
Alice has created the synchronous function add1(number)
:
function add1(number){
return number + 1
}
Rewrite this function so the caller of the function receives the incremented number through a callback function instead of as a return value.
Then show that you know how to use the new version of the function by using it to increment 5
to 6
, and then log the incremented number in the console using console.log()
.
Sample answer
function add1(number, callback){
callback(number + 1)
}
add1(5, function(incrementedNumber){
console.log(incrementedNumber)
})
Marking guidelines
- 0.5 points for implementing the function with the callback correct
- -0.25 points for not defining the
callback
parameter
- -0.25 points for not defining the
- 0.5 points for using the function with the callback correct