Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
SWEN90006-A1-2019
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Li Congran
SWEN90006-A1-2019
Commits
1cd8c4e2
Commit
1cd8c4e2
authored
Sep 06, 2019
by
CONGRANLI
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add mutant
parent
8448ca41
Pipeline
#6661
failed with stages
in 20 seconds
Changes
91
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
91 changed files
with
3636 additions
and
202 deletions
+3636
-202
AlreadyLoggedInException.java
...mutant-1/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...s/mutant-1/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-1/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-1/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
programs/mutant-1/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...rams/mutant-1/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/mutant-1/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/mutant-1/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-1/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-2/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...s/mutant-2/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-2/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-2/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
programs/mutant-2/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...rams/mutant-2/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/mutant-2/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/mutant-2/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-2/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...utant-3 /swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
.../mutant-3 /swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...t-3 /swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...tant-3 /swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
...rams/mutant-3 /swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...ams/mutant-3 /swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/mutant-3 /swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/mutant-3 /swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
...mutant-3 /swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-4/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...s/mutant-4/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-4/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-4/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
programs/mutant-4/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...rams/mutant-4/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/mutant-4/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/mutant-4/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-4/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-5/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...s/mutant-5/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-5/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-5/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
programs/mutant-5/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...rams/mutant-5/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/mutant-5/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/mutant-5/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-5/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-1/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...l/mutant-1/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-1/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-1/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
...ginal/mutant-1/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...inal/mutant-1/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/original/mutant-1/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/original/mutant-1/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-1/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-2/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...l/mutant-2/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-2/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-2/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
...ginal/mutant-2/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...inal/mutant-2/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/original/mutant-2/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/original/mutant-2/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-2/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...utant-3 /swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
.../mutant-3 /swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...t-3 /swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...tant-3 /swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
...inal/mutant-3 /swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...nal/mutant-3 /swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/original/mutant-3 /swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/original/mutant-3 /swen90006/passbook/PassBook.java
+264
-0
WeakPassphraseException.java
...mutant-3 /swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-4/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...l/mutant-4/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-4/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-4/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
...ginal/mutant-4/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...inal/mutant-4/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/original/mutant-4/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/original/mutant-4/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-4/swen90006/passbook/WeakPassphraseException.java
+14
-0
AlreadyLoggedInException.java
...mutant-5/swen90006/passbook/AlreadyLoggedInException.java
+9
-0
DuplicateUserException.java
...l/mutant-5/swen90006/passbook/DuplicateUserException.java
+9
-0
IncorrectPassphraseException.java
...nt-5/swen90006/passbook/IncorrectPassphraseException.java
+9
-0
InvalidSessionIDException.java
...utant-5/swen90006/passbook/InvalidSessionIDException.java
+9
-0
NoSuchURLException.java
...ginal/mutant-5/swen90006/passbook/NoSuchURLException.java
+11
-0
NoSuchUserException.java
...inal/mutant-5/swen90006/passbook/NoSuchUserException.java
+9
-0
Pair.java
programs/original/mutant-5/swen90006/passbook/Pair.java
+31
-0
PassBook.java
programs/original/mutant-5/swen90006/passbook/PassBook.java
+262
-0
WeakPassphraseException.java
.../mutant-5/swen90006/passbook/WeakPassphraseException.java
+14
-0
PartitioningTests.java
tests/Partitioning/swen90006/passbook/PartitioningTests.java
+4
-202
No files found.
programs/mutant-1/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/mutant-1/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/mutant-1/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/mutant-1/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/mutant-1/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/mutant-1/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/mutant-1/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/mutant-1/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/mutant-1/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/mutant-2/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/mutant-2/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/mutant-2/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/mutant-2/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/mutant-2/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/mutant-2/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/mutant-2/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/mutant-2/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/mutant-2/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/mutant-3 /swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/mutant-3 /swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/mutant-3 /swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/mutant-3 /swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/mutant-3 /swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/mutant-3 /swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/mutant-3 /swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/mutant-3 /swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/mutant-3 /swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/mutant-4/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/mutant-4/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/mutant-4/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/mutant-4/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/mutant-4/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/mutant-4/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/mutant-4/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/mutant-4/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'/'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/mutant-4/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/mutant-5/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/mutant-5/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/mutant-5/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/mutant-5/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/mutant-5/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/mutant-5/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/mutant-5/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/mutant-5/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
||
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
&&
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/mutant-5/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/original/mutant-1/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/original/mutant-1/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/original/mutant-1/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/original/mutant-1/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/original/mutant-1/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/original/mutant-1/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/original/mutant-1/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/original/mutant-1/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/original/mutant-1/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/original/mutant-2/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/original/mutant-2/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/original/mutant-2/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/original/mutant-2/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/original/mutant-2/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/original/mutant-2/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/original/mutant-2/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/original/mutant-2/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/original/mutant-2/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/original/mutant-3 /swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/original/mutant-3 /swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/original/mutant-3 /swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/original/mutant-3 /swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/original/mutant-3 /swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/original/mutant-3 /swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/original/mutant-3 /swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/original/mutant-3 /swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
//---------------mutant--------------
for
(
int
i
=
1
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/original/mutant-3 /swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/original/mutant-4/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/original/mutant-4/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/original/mutant-4/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/original/mutant-4/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/original/mutant-4/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/original/mutant-4/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/original/mutant-4/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/original/mutant-4/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'/'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
||
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/original/mutant-4/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
programs/original/mutant-5/swen90006/passbook/AlreadyLoggedInException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
AlreadyLoggedInException
extends
Exception
{
public
AlreadyLoggedInException
(
String
username
)
{
super
(
"Username already logged in: "
+
username
);
}
}
programs/original/mutant-5/swen90006/passbook/DuplicateUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
DuplicateUserException
extends
Exception
{
public
DuplicateUserException
(
String
username
)
{
super
(
"Username already exists: "
+
username
);
}
}
programs/original/mutant-5/swen90006/passbook/IncorrectPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
IncorrectPassphraseException
extends
Exception
{
public
IncorrectPassphraseException
(
String
username
,
String
passphrase
)
{
super
(
"Incorrect passphrase: "
+
passphrase
+
" for user "
+
username
);
}
}
programs/original/mutant-5/swen90006/passbook/InvalidSessionIDException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
InvalidSessionIDException
extends
Exception
{
public
InvalidSessionIDException
(
Integer
sessionID
)
{
super
(
"Invalid session ID: "
+
sessionID
);
}
}
programs/original/mutant-5/swen90006/passbook/NoSuchURLException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.net.URL
;
public
class
NoSuchURLException
extends
Exception
{
public
NoSuchURLException
(
String
username
,
URL
url
)
{
super
(
"User "
+
username
+
" does not have password for URL "
+
url
.
toString
());
}
}
programs/original/mutant-5/swen90006/passbook/NoSuchUserException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
NoSuchUserException
extends
Exception
{
public
NoSuchUserException
(
String
username
)
{
super
(
"Username does not exist: "
+
username
);
}
}
programs/original/mutant-5/swen90006/passbook/Pair.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
/**
* A pair of objects.
*/
public
class
Pair
<
X
,
Y
>
{
private
X
first
;
private
Y
second
;
public
Pair
(
X
first
,
Y
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
X
getFirst
()
{
return
this
.
first
;
}
public
Y
getSecond
()
{
return
this
.
second
;
}
public
boolean
equals
(
Pair
<
X
,
Y
>
other
)
{
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
}
programs/original/mutant-5/swen90006/passbook/PassBook.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.Set
;
import
java.util.HashSet
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.util.Random
;
import
java.util.Arrays
;
/**
* PassBook is a (fictional) online password manager. A password
* manager is a software application that generates, stores, and
* retrieves login details for users.
*
* A user has an account with PassBook. This account is protected by a
* master password, or passphrase. Each user can store login details
* for multiple websites, identified by their URL. A user can add a
* login details for a given website. The passphrase is used to
* encrypt all passwords, but for this implementation, we have ignored
* encryption.
*
* The PassBook passphrase must conform to the following requirements:
* Must be at least eight characters long and contain at
* least one digit (range 0-9), one letter in the range 'a'-'z', and
* one letter in the range 'A'-'Z'.
*
* Username and passwords for stored URLs have no password
* requirements.
*
* When a user logs into PassBook, they are given a session ID. This
* session ID is used to identify them for all transactions until they
* log out.
*/
public
class
PassBook
{
/** The minimum length of a passphrase */
public
final
static
int
MINIMUM_PASSPHRASE_LENGTH
=
8
;
/** Valid URL protocols for the passbook */
public
final
static
String
[]
VALID_URL_PROTOCOLS
=
{
"http"
,
"https"
};
//The passphrases (master passwords) for all users
private
Map
<
String
,
String
>
passphrases
;
//The login details for all users and the URLs they have stored
private
Map
<
String
,
PasswordTable
>
details
;
//Mapping from session IDs to usernames
private
Map
<
Integer
,
String
>
userIDs
;
//Mapping from usernames to sessionIDs
private
Map
<
String
,
Integer
>
sessionIDs
;
/**
* Constructs an empty passbook.
*/
public
PassBook
()
{
passphrases
=
new
HashMap
<
String
,
String
>();
details
=
new
HashMap
<
String
,
PasswordTable
>();
userIDs
=
new
HashMap
<
Integer
,
String
>();
sessionIDs
=
new
HashMap
<
String
,
Integer
>();
}
/**
* Adds a new user to the passbook.
*
* @param passbookUsername the username for the user to be added
* @param passphrase the passphrase (master password) for the user
* @throws DuplicateUserException if the username is already in the passbook
* @throws WeakPassphraseException if the password does not fit the passphrase
rules (see class documentation)
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
void
addUser
(
String
passbookUsername
,
String
passphrase
)
throws
DuplicateUserException
,
WeakPassphraseException
{
//Check if this user exists
if
(
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
DuplicateUserException
(
passbookUsername
);
}
//check the passphrase strength
else
{
if
(
passphrase
.
length
()
<
MINIMUM_PASSPHRASE_LENGTH
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
boolean
containsLowerCase
=
false
;
boolean
containsUpperCase
=
false
;
boolean
containsNumber
=
false
;
for
(
int
i
=
0
;
i
<
passphrase
.
length
();
i
++)
{
if
(
'a'
<=
passphrase
.
charAt
(
i
)
||
passphrase
.
charAt
(
i
)
<=
'z'
)
{
containsLowerCase
=
true
;
}
else
if
(
'A'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'Z'
)
{
containsUpperCase
=
true
;
}
else
if
(
'0'
<=
passphrase
.
charAt
(
i
)
&&
passphrase
.
charAt
(
i
)
<=
'9'
)
{
containsNumber
=
true
;
}
}
if
(!
containsLowerCase
||
!
containsUpperCase
||
!
containsNumber
)
{
throw
new
WeakPassphraseException
(
passphrase
);
}
}
passphrases
.
put
(
passbookUsername
,
passphrase
);
PasswordTable
pt
=
new
PasswordTable
();
details
.
put
(
passbookUsername
,
pt
);
}
/**
* Checks if a user exists
* @param passbookUsername the passbookUsername
* @return true if and only if this user is in the passbook
*
* Assumption: passbookUsername is non-null
*/
public
boolean
isUser
(
String
passbookUsername
)
{
return
passphrases
.
containsKey
(
passbookUsername
);
}
/**
* Logs a user into the passbook.
*
* @param passbookUsername the passbookUsername for the user
* @param passphrase the passphrase (master password) for the user
* @returns a session ID greater than or equal to 0
* @throws NoSuchUserException if the user does not exist in the passbook
* @throws AlreadyLoggedInException if the user is already logged in
* @throws IncorrectPassphraseException if the passphrase is incorrect for this user
*
* Assumption: passbookUsername and passphrase are non-null
*/
public
int
loginUser
(
String
passbookUsername
,
String
passphrase
)
throws
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
{
//check that the user exists
if
(!
passphrases
.
containsKey
(
passbookUsername
))
{
throw
new
NoSuchUserException
(
passbookUsername
);
}
else
if
(
sessionIDs
.
get
(
passbookUsername
)
!=
null
)
{
throw
new
AlreadyLoggedInException
(
passbookUsername
);
}
else
if
(!
passphrases
.
get
(
passbookUsername
).
equals
(
passphrase
))
{
throw
new
IncorrectPassphraseException
(
passbookUsername
,
passphrase
);
}
//generate a random session ID that is not already taken
int
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
while
(
userIDs
.
containsKey
(
sessionID
))
{
sessionID
=
new
Random
().
nextInt
(
Integer
.
MAX_VALUE
);
}
//add the session ID
sessionIDs
.
put
(
passbookUsername
,
sessionID
);
userIDs
.
put
(
sessionID
,
passbookUsername
);
return
sessionID
;
}
/**
* Logs out a user based on session ID. Has no affect if the session ID does not exist.
*
* @param sessionID the session ID to be terminated
*
* Assumption: session ID is non-null
*/
public
void
logoutUser
(
Integer
sessionID
)
{
sessionIDs
.
remove
(
userIDs
.
get
(
sessionID
));
userIDs
.
remove
(
sessionID
);
}
/**
* Updates the login details for a URL of a user. If the url
* username or password are null, the login details for this URL
* must be removed.
*
* @param sessionID the session ID for the logged-in user
* @param urlUsername the username for the user to be added
* @param url the URL for the username/password pair
* @param urlPassword the password to be add
* @throws InvalidSessionIDException if the session ID does not exists
* @throws MalformedURLException if the protocol is not 'http' or 'https'
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
void
updateDetails
(
Integer
sessionID
,
URL
url
,
String
urlUsername
,
String
urlPassword
)
throws
InvalidSessionIDException
,
MalformedURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
if
(
urlUsername
==
null
&&
urlPassword
==
null
)
{
pt
.
remove
(
url
);
}
else
{
pt
.
put
(
url
,
new
Pair
<
String
,
String
>
(
urlUsername
,
urlPassword
));
details
.
put
(
passbookUsername
,
pt
);
}
}
/**
* Retrieves login details for a given URL and user.
*
* @param sessionID the session ID
* @param url the URL for the password being retrieved.
* @returns the username and password for a given url for the corresponding user
* @throws NoSuchUserException if the username does not exist in the passbook
* @throws MalformedURLException if the syntax is invalid (see class documentation)
* @throws NoSuchURLException if user does not have login for this URL
*
* Assumption: url is non-null and a valid URL object
* Assumption: sessionID is non-null
*/
public
Pair
<
String
,
String
>
retrieveDetails
(
Integer
sessionID
,
URL
url
)
throws
InvalidSessionIDException
,
MalformedURLException
,
NoSuchURLException
{
//check that the session ID exists
String
passbookUsername
=
userIDs
.
get
(
sessionID
);
if
(
passbookUsername
==
null
)
{
throw
new
InvalidSessionIDException
(
sessionID
);
}
else
if
(!
Arrays
.
asList
(
VALID_URL_PROTOCOLS
).
contains
(
url
.
getProtocol
()))
{
throw
new
MalformedURLException
(
passbookUsername
);
}
PasswordTable
pt
=
details
.
get
(
passbookUsername
);
//if this returned nothing, the user has no details for any url
if
(
pt
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
Pair
<
String
,
String
>
pair
=
pt
.
get
(
url
);
//if this returned nothing, the user does not have a login for this url
if
(
pair
==
null
)
{
throw
new
NoSuchURLException
(
passbookUsername
,
url
);
}
return
pair
;
}
//A simple label to improve code readability
private
class
PasswordTable
extends
HashMap
<
URL
,
Pair
<
String
,
String
>>
{}
}
programs/original/mutant-5/swen90006/passbook/WeakPassphraseException.java
0 → 100644
View file @
1cd8c4e2
package
swen90006
.
passbook
;
public
class
WeakPassphraseException
extends
Exception
{
public
WeakPassphraseException
(
String
passphrase
)
{
super
(
"Passphrase does not comply with the PassBook rules\n"
+
"\t- must contains at least "
+
PassBook
.
MINIMUM_PASSPHRASE_LENGTH
+
" characters\n"
+
"\t- must contain at least one numeric character\n"
+
"\t- must contain at least one lower case letter\n"
+
"\t- must contain at least one upper case letter\n"
);
}
}
tests/Partitioning/swen90006/passbook/PartitioningTests.java
View file @
1cd8c4e2
...
...
@@ -69,164 +69,7 @@ public class PartitioningTests
assertTrue
(
WeakPassphraseException
);
}
/* //Passphrase = 8
@Test public void WeakPassphraseException2() throws DuplicateUserException{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "Ab23sda2";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertFalse(WeakPassphraseException);
}
//Passphrase > 8
@Test public void WeakPassphraseException3() throws DuplicateUserException{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "Ab23sda2dsaldaskljdkasl";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertFalse(WeakPassphraseException);
}
// passphrase.length = 8 && passphrase only contain one kind factory in Lower, Upper and Number
@Test public void Contains() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "AAAABBBC";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertTrue(WeakPassphraseException);
}
// passphrase.length = 8 && passphrase only contain two kind factory in Lower, Upper and Number
@Test public void Contains2() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "AAA2232C";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertTrue(WeakPassphraseException);
}
// passphrase.length = 8 && passphrase contain no kind factory in Lower, Upper and Number
@Test public void Contains3() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "'{@[/:Cd";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertTrue(WeakPassphraseException);
}
// passphrase.length = 8 && passphrase contain all kinds factory in Lower, Upper and Number
@Test public void Contains4() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "Ab23cd54";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertFalse(WeakPassphraseException);
}
// passphrase.length > 8 && passphrase only contain one kind factory in Lower, Upper and Number
@Test public void Contains5() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "123456789212";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertTrue(WeakPassphraseException);
}
// passphrase.length > 8 && passphrase only contain two kind factory in Lower, Upper and Number
@Test public void Contains6() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "AAA223293289312C";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertTrue(WeakPassphraseException);
}
// passphrase.length > 8 && passphrase contain no kind factory in Lower, Upper and Number
@Test public void Contains7() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "^&*($%@#%^&*(";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertTrue(WeakPassphraseException);
}
// passphrase.length > 8 && passphrase contain all kinds factory in Lower, Upper and Number
@Test public void Contains8() throws DuplicateUserException
{
boolean WeakPassphraseException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "Ab23cd54vhuy67";
try{
pb.addUser(passbookUsername,passbookphrase);
}
catch (WeakPassphraseException e){
WeakPassphraseException = true;
}
assertFalse(WeakPassphraseException);
}
*/
//passphrase.length >=8 not containsLowerCase
@Test
public
void
NocontainLowerCase
()
throws
DuplicateUserException
{
boolean
WeakPassphraseException
=
false
;
...
...
@@ -318,12 +161,11 @@ public class PartitioningTests
boolean
AlreadyLoggedInException
=
false
;
String
passbookUsername
=
"AlexTina"
;
String
passbookphrase
=
"Abc234hg"
;
String
passbookUsername2
=
"AlexTina"
;
String
passbookphrase2
=
"Abc234hg"
;
try
{
pb
.
addUser
(
passbookUsername
,
passbookphrase
);
pb
.
loginUser
(
passbookUsername
,
passbookphrase
);
pb
.
loginUser
(
passbookUsername
2
,
passbookphrase2
);
pb
.
loginUser
(
passbookUsername
,
passbookphrase
);
}
catch
(
AlreadyLoggedInException
e
){
AlreadyLoggedInException
=
true
;
...
...
@@ -331,26 +173,7 @@ public class PartitioningTests
assertTrue
(
AlreadyLoggedInException
);
}
/* //user has not login
@Test public void AlreadyLoggedInException2() throws NoSuchUserException, IncorrectPassphraseException, WeakPassphraseException, DuplicateUserException {
boolean AlreadyLoggedInException = false;
String passbookUsername = "AlexTina";
String passbookphrase = "Abc234hg";
try{
pb.addUser(passbookUsername,passbookphrase);
pb.loginUser(passbookUsername,passbookphrase);
}
catch (AlreadyLoggedInException e){
AlreadyLoggedInException = true;
}
assertFalse(AlreadyLoggedInException);
}
*/
//passphrase is not equale to the saved one
@Test
public
void
IncorrectPassphraseException
()
throws
WeakPassphraseException
,
DuplicateUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
,
NoSuchUserException
{
boolean
IncorrectPassphraseException
=
false
;
...
...
@@ -419,28 +242,7 @@ public class PartitioningTests
//MalformedURLException
/*
//Protocol = [http,https]
@Test public void MalformedURLException() throws MalformedURLException, WeakPassphraseException, DuplicateUserException, NoSuchUserException, AlreadyLoggedInException, IncorrectPassphraseException, InvalidSessionIDException {
boolean MalformedURLException = false;
Integer sessionID ;
String Username = "AlexTina";
String Password = "Abc234hg";
String urlUsername = "AlexTina";
String urlPassword = "Abc234hg";
pb.addUser(Username,Password);
sessionID = pb.loginUser(Username,Password);
try{
URL url = new URL ("http:AlexTinaAbc234hg");
pb.updateDetails(sessionID,url,urlUsername,urlPassword);
}catch (MalformedURLException e){
MalformedURLException = true;
}
assertFalse(MalformedURLException);
}
*/
//Protocol != [http,https]
@Test
public
void
MalformedURLException2
()
throws
MalformedURLException
,
WeakPassphraseException
,
DuplicateUserException
,
NoSuchUserException
,
AlreadyLoggedInException
,
IncorrectPassphraseException
,
InvalidSessionIDException
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment