Exam 2023-08-16

Here you find sample answers and marking guidelines to the questions on the exam 2023-08-16.


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:

  1. Deleting a resource
  2. Updating a resource
  3. Creating a new 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

  1. DELETE
  2. PUT
  3. POST

Marking guidelines

  • 0.33 points for each correct name (spelling must be correct)

Question 2 (1p)

Question

Explain why the URI /movies/search?title=Bond (that identifies all movies whose title contains the word/character sequence Bond) is considered a bad URI in HTTP.

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 only identify resources. It should not contain verbs, such as search, so the URI in this case should rather be /movies?title=Bond.

Marking guidelines

  • 1 point for search should not be in the URI

Question 3 (1p)

Question

Name an HTTP header of your choice, explain what it represents/means, show a sample value it can have, and explain how that sample value should be interpreted/what it means.

Note: This question is about HTTP when used properly, and has nothing to do with HTML, web browsers, nor websites.

Sample answer

The HTTP header Content-Type can be used in HTTP requests and responses, and it indicates in which data format the body of the request/response is written in. For example, the value application/json means the body of the request/response is written in JSON format.

Marking guidelines

  • 0.25 points for name
  • 0.25 points for explanation
  • 0.25 points for sample value
  • 0.25 points for explanation of sample value

Question 4 (1p)

Question

Explain when the server should send back the status code 400 in an HTTP response, and when it should send back the status code 500.

Note: This question is about HTTP when used properly, and has nothing to do with HTML, web browsers, nor websites.

You'll get:

  • 0.5 points for each correct answer

Sample answer

The server should send back the status code 400 when there is something wrong with the request, for example when the data in the request contains validation errors.

The server should send back the status code 500 when there is nothing wrong with the request, but something is wrong on the server that prevents it from carrying out the request, for example if it needs to read data from a database, but it currently can't communicate with the database.

Marking guidelines

  • 0.5 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).

  • <h1>Welcome!</h1>
  • <!DOCTYPE html>
  • </body>
  • </head>
  • <body>
  • <title>Welcome!</title>
  • <head>
  • </html>
  • <html>

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

Name the attribute <a> elements can have that indicates which page the user should come to when the user clicks on the element.

Sample answer

href

Marking guidelines

  • 1 point for correct answer
  • -0.25 points for answering with something more than just the attribute name that is wrong or makes it unclear what your answer is

Question 7 (1p)

Question

What type of HTTP request (the name of the method) does the web browser send when it receives the HTML code for an <img> element that contains the src attribute?

Sample answer

GET

Marking guidelines

  • 1 point for correct method name

Question 8 (2p)

Question

Name 3 different inline elements in HTML.

Note: Just write the name of the tag; do not include < and >.

Note: Writing inline-block elements is also OK, but not block elements.

You'll get:

  • 0.66 points for each correct answer (spelling needs to be correct)
    • Only 0.5 points if spelling is wrong

Sample answer

  1. a
  2. span
  3. i

Marking guidelines

  • 0.66 points for each correct answer (spelling needs to be correct)
    • Only 0.5 points if spelling is wrong

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="POST">
   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

(Since the method is POST, the web browser will send a POST request, and pass the data from the form in the body of the request (x=123&y=456). The data is only passed in the querystring of the URI if the method is GET)

Marking guidelines

  • 1 point for correct answer

Question 10 (1p)

Question

Name one HTML tag of your choice that is valid to write in the <head> element in addition to <title>.

Note: Just write the name of the tag; do not include < and >.

Sample answer

link

Marking guidelines

  • 1 point for a valid tag

CSS

Question 11 (1p)

Question

Name and describe 2 different CSS properties of your choice except color and width. 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

  • 0.125 points for each valid property name
  • 0.125 points for each correct property description
  • 0.125 points for each valid sample value
  • 0.125 points for each correct sample value description

Question 12 (1p)

Question

What color will the text in the paragraph in the HTML code below have?

<style>
    
    .p{
        color: brown;
    }
    
    p{
        color: pink;
    }
    
    #p{
        color: white;
    }
    
</style>

<p id="p" class="p">Some text.</p>

Sample answer

white

Marking guidelines

  • 1 point for a correct answer

Question 13 (1p)

Question

Here is some CSS code:

div p #a.b{
  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>
        <p>
            <span id="a" class="b">I will be matched!</span>
        </p>
    </div>
</body>

Marking guidelines

  • 1 point for an answer that is correct/close to correct
  • Point deduction for small errors in close to correct answers:
    • -0.25 points for missing <body>
    • -0.25 points for putting id and/or class on wrong element <p>
    • -0.25 points for missing an element in <p>

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>
    <div>Here is <span class="p">SELECT ME</span> some text.</div>
    <div>Here <span>is some</span> text.</div>
    <div>Here <i class="p">is some</i> text.</div>
    <p>Here <span class="p">is some</span> text.</p>
</body>

Sample answer

div span.p

Marking guidelines

  • 1 point for an answer that works
  • 0.5 points for div span .p

Website

Question 15 (2p)

Question

Explain what a session is, give one example of what it can be used for, and explain how sessions can be implemented (in general, and not in a specific framework/library/package).

Sample answer

A session is a collection of values the server wants to remember about a client/user that is stored on the server. They can for example be used to remember if the user has logged in on the website or not.

The sessions can for example be stored in a database on the server. Each session gets it's own id (known as the session id), which should be hard to guess (so a hacker can't guess other users' session ids), so they are usually long strings of random characters. When a user starts using the website, the server can insert a new post in the database that contains the information the server wants to remember about the user together with a new session id.

The server can then send back the session id in a cookie in the response to the user, and the user should then send back this cookie to the server in all requests it sends to the server in the future. When the server receives these request, it can fetch the session from the database with the session id from the cookie in the request, and that way read out the information it wanted to remember about the user.

Marking guidelines

  • 0.5 points for what a session is (collection of values/information to remember about a user)
  • 0.5 points for example
  • 1 points for implementation details (session id + stored on server + cookie)

Question 16 (1p)

Question

Explain the difference between a webpage and a website.

Sample answer

A webpage is a single HTML document that can be shown in a web browser. All such HTML documents part of the same domain constitutes a website.

Marking guidelines

  • 0.5 points for explaining webpage
  • 0.5 points for explaining website (multiple webpages)

Question 17 (1p)

Question

Name two different middlewares one can add to an Express application, for example two middlewares you have used in the application you built in your project work, and briefly explain what they do.

Sample answer

  • express.urlencoded() (previously bodyParser.urlencoded()): A middleware that makes it possible for us to access the body in HTTP requests using request.body (if it's written in the data format application/x-www-form-urlencoded)
  • expressSession(): A middleware that makes it possible for us to use request.session to access the user's session

Marking guidelines

  • 0.25 points for each name
  • 0.25 points for each explanation

Security

Question 18 (1p)

Question

On a properly implemented website, is it likely that a user can get the session id 10? Justify your answer.

Sample answer

No, that is unlikely. Since session ids should be hard to guess, they should be big numbers or long strings, so a hacker can't "guess" user's session id. If a hacker knows or manages to guess another user's session id, then that hacker can start to use that session id too, and that way act as that user to the server, and that's a security risc.

Marking guidelines

  • 1 point for correct answer and valid justification

Question 19 (2p)

Question

On a website with blogposts, the blogposts are stored in an SQLite database in a table named blogposts that looks like this:

keywordtitlecontentauthor
htmlHTML is fun!...Alice
cssCSS is fun too!...Bob
jsJS is most fun!...Alice
............

content is not shown in the table above, since that one is quite long, and not all rows are shown, since they are quite many.

Claire should add a webpage to the website users can use to search for blogposts matching an entered keyword or an entered title. It should not be possible to search for blogposts matching an entered author, since easily retrieving all blogposts written by a specific user is considered to be a security vulnerability on this website.

Claire adds a webpage with the following HTML code:

<h1>Search blogposts</h1>
<form method="GET" action="/blogposts/search">
    <div>
        Select field to search:
        <select name="field">
            <option value="keyword">Keyword</option>
            <option value="title">Title</option>
        </select>
    </div>
    <div>
        Enter value to match in field:
        <input type="text" name="value">
    </div>
    <input type="submit" value="Search!">
</form>

To handle the search request, she adds the following JS code to the app.js file:

app.get('/blogposts/search', function(request, response){
    
    const field = request.params.field
    const value = request.params.value
    
    const query = "SELECT * FROM blogposts WHERE "+field+" = ?"
    const values = [value]
    
    db.all(query, values function(error, blogposts){
        // Let us assume no database error occurred, so we ignore that.
        
        const model = {
            blogposts
        }
        
        // The file blogposts.hbs is not shown here, but it
        // shows all the blogposts in the model to the user.
        response.render('blogposts.hbs', model)
        
    })
    
})

Does Claire's implementation contain a security vulnerability or not? Justify your answer.

Sample answer

Claire's implementation does contain a security vulnerability. In the HTML code for the <form>, it looks like the user can only choose among the fields keyword and title, but the HTML code can easily be changed client-side by a hacker, so a hacker can easily add author as a third option in the <select> element (i.e. <option value="author">Author</option>), and that way send a request that would search for blogpost written by a specific user. I.e.

(in addition to that:

  • A hacker can craft her own HTTP request from scratch, and write author instead of keyword or title directly in the HTTP request
  • By using string concatenation in the SQL query, she has created an SQL injection vulnerability, so a hacker can easily modify the WHERE part of the query to perform much more complicated searches than what is intended. Also note that using a placeholder (?) instead of "+field+" won't work, since it's not a value in the SQL syntax that should be inserted, and this alone would not solve the problem anyway

)

Marking guidelines

  • 2 points for correct answer and valid justification
  • Only 1.5 points for answers identifying an SQL vulnerability, and suggesting using placeholders solve the problem

Question 20 (1p)

Question

What is the biggest problem with the code below? Justify your answer.

Note: Any user should be able to anonymously create blogposts.

app.js:

//...

app.post('/blogposts/create', function(request, response){
    
    const title = request.body.title
    const content = request.body.content
    
    const errorMessages = []
    
    if(50 < title.length){
        errorMessages.push("The title is too long.")
    }
    if(5000 < content.length){
        errorMessages.push("The content is too long.")
    }
    
    if(0 < errorMessages.length){
        
        const model = {
            title,
            content,
            errorMessages,
        }
        
        response.render("create-blogpost.hbs", model)
        
    }
    
    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)
        }
    })
    
})

//...

Sample answer

Looking at the code, one can see that it validates the blogpost that should be created, and given the conditional statement with the condition 0 < errorMessages.length, the intent seems to be to only create the blogpost (store it in the database) if there are no validation errors. However, this if statement contains no return statement, so even if we enter it and send back a response that shows the validation errors to the user, the rest of the code will continue to execute, so we will create blogposts that contains validation errors. That is the biggest problem with the code.

(then there exist other problems as well, such as:

  • the code will crash if a hacker sends a request without a title or content (that is bad, but no harm done)
  • the error message The title is too long. is not enough informative to the user (i.e. it doesn't mention what the allowed maximum length is))
  • 50 and 5000 have been hardcoded

but none of these are as problematic as creating a blogpost that contains validation errors)

Marking guidelines

  • 1 point for correct answer
  • 0.1 points for saying the database can be spammed

Database

Question 21 (1p)

Question

Below is the table humans found in an SQLite database (not all rows are shown).

idnameage
1Alice10
2Bob20
3Claire15
.........

Write an SQL query that sends back all information about all humans with the name Bob.

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

SELECT * FROM humans WHERE name = "Bob"

(in SQLite, when testing for equality, both = and == can be used)

Marking guidelines

  • 1 point for an answer that is largely correct
  • Point deductions for errors:
    • -0.1 points for missing *
    • -0.25 points for SELECT humans instead of SELECT * FROM
    • -0.25 points for 'name = Bob' instead of name = 'Bob'
    • -0.5 points for GET humans instead of SELECT * FROM
    • -0.5 points for RETRIEVE humans instead of SELECT * FROM
    • -0.75 points for get ALL instead of SELECT * FROM

Question 22 (1p)

Question

Below is the table humans found in an SQLite database (not all rows are shown).

idnameage
1Alice10
2Bob20
3Claire15
.........

Write an SQL query that changes the age of all humans named Claire to 30.

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 age = 30 WHERE name = "Claire"

(in SQLite, when testing for equality, both = and == can be used)

Marking guidelines

  • 1 point for an answer that is largely correct
  • Point deduction for errors:
    • -0.1 points for not using quotes around strings
    • -0.25 points for changing the age to 10 instead of 30

OR:

  • 0.5 points for a query that contains most required SQL parts, but in wrong order
  • Point deduction for errors:
    • -0.1 points for using FROM instead of SET

JavaScript

Question 23 (1p)

Question

Implement the JavaScript function getSumUntil(excludedTerm), that receives an integer as argument, and returns the sum of the integers between 0 and the integer it receives (including 0 BUT EXCLUDING the received integer).

Sample usage:

getSumUntil(5) // --> 10 (0 + 1 + 2 + 3 + 4)
getSumUntil(2) // --> 1 (0 + 1)
getSumUntil(1) // --> 0

Note: You can expect excludedTerm to always be greater than 0.

Sample answer

function getSumUntil(excludedTerm){
    
    let sum = 0
    
    for(let term=0; term<excludedTerm; term++){
        sum += term
    }
    
    return sum
    
}

Marking guidelines

  • 1 point for an answer that largely works
  • Point deduction for small mistakes:
    • -0.1 points for using global variable
    • -0.1 points for using bad name on variable
    • -0.1 points for Function instead of function
    • -0.1 points for including excludedTerm in the sum

OR:

  • 0.25 points for iterating over correct values

Question 24 (1p)

Question

Implement the JavaScript function isAnyGreaterThan10(numbers), that receives an array with numbers and returns:

  • true if at least one of the numbers in the array is greater than 10
  • false otherwise

Sample usage:

isAnyGreaterThan10([3, 7, 1, 8]) // --> false
isAnyGreaterThan10([5, 3, 15, 5]) // --> true
isAnyGreaterThan10([15, 51, 50]) // --> true
isAnyGreaterThan10([]) // --> false

(if the array is empty, then returning false is what makes most sense, so that's how your implementation should work as well)

Sample answer

function isAnyGreaterThan10(numbers){
    
    for(const number of numbers){
        if(10 < number){
            return true
        }
    }
    
    return false
    
}

Marking guidelines

  • 1 point for an answer that largely works
  • Point deduction 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 getNumberOfMoviesInCategories(movies, category1, category2), which receives an array with movie objects and two categories, and returns the number of movies in respective categories as an array containing the two numbers.

Sample usage:

getNumberOfMoviesInCategories([
    {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},,
    {title: "Love Actually", category: "romantic" runtimeInMinutes: 136},
], "comedy", "romantic") // --> [3, 1]

Sample answer

function getNumberOfMoviesInCategories(movies, category1, category2){
    
    let numberOfMovies1 = 0
    let numberOfMovies2 = 0
    
    for(const movie of movies){
        if(movie.category == category1){
            numberOfMovies1 += 1
        }
        if(movie.category == category2){
            numberOfMovies2 += 1
        }
    }
    
    return [numberOfMovies1, numberOfMovies2]
    
}

Marking guidelines

  • 2 points for an answer that largely works
  • Point deduction for smaller mistakes:
    • -0.25 points for not returning an array
    • -0.25 points for iterating over indexes instead of values

Question 26 (1p)

Question

Alice has created the asynchronous functions add1(number, callback) and add5(number, callback):

function add1(number, callback){
    callback(number + 1)
}

function add5(number, callback){
    callback(number + 5)
}

Implement the function add6(number, callback), that can be used like this:

add6(10, function(numberPlus6){
    console.log("10 + 6 = "+numberPlus6)
})

In your implementation of add6 you may not use any mathematical operation yourself, but you have to call add1 and add5 to compute the new number based on the number you receive.

Sample answer

function add6(number, callback){
    add1(number, function(numberPlus1){
        add5(numberPlus1, function(numberPlus6){
            callback(numberPlus6)
        })
    })
}

Marking guidelines

  • 1 point for an answer that largely works