Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
TTool
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mbe-tools
TTool
Commits
eb0e9127
Commit
eb0e9127
authored
1 year ago
by
Pierre Dontenville
Browse files
Options
Downloads
Patches
Plain Diff
syntaxe adjustement
parent
e50c587e
No related branches found
No related tags found
1 merge request
!485
Avatar security tests
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
ttool/src/test/java/test/AbstractTest.java
+16
-16
16 additions, 16 deletions
ttool/src/test/java/test/AbstractTest.java
ttool/src/test/java/tmltranslator/DiplodocusSecurityTest.java
+21
-102
21 additions, 102 deletions
...l/src/test/java/tmltranslator/DiplodocusSecurityTest.java
with
37 additions
and
118 deletions
ttool/src/test/java/test/AbstractTest.java
+
16
−
16
View file @
eb0e9127
...
@@ -83,7 +83,7 @@ public abstract class AbstractTest {
...
@@ -83,7 +83,7 @@ public abstract class AbstractTest {
protected
void
checkResultXml
(
final
String
actualCode
,
protected
void
checkResultXml
(
final
String
actualCode
,
final
String
fileName
)
{
final
String
fileName
)
{
System
.
out
.
println
(
"Comparing with "
+
actualCode
.
substring
(
0
,
30
)
+
" with file: "
+
fileName
);
TraceManager
.
addDev
(
"Comparing with "
+
actualCode
.
substring
(
0
,
30
)
+
" with file: "
+
fileName
);
// Since this function fails because tasks are not always in the same order, it is deactivated
// Since this function fails because tasks are not always in the same order, it is deactivated
...
@@ -160,7 +160,7 @@ public abstract class AbstractTest {
...
@@ -160,7 +160,7 @@ public abstract class AbstractTest {
String
line
;
String
line
;
try
{
try
{
while
((
line
=
proc_err
.
readLine
())
!=
null
)
{
while
((
line
=
proc_err
.
readLine
())
!=
null
)
{
System
.
out
.
println
(
"NOC executing err: "
+
line
);
TraceManager
.
addDev
(
"NOC executing err: "
+
line
);
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
//System.out.println("FAILED reading errors");
//System.out.println("FAILED reading errors");
...
@@ -202,16 +202,16 @@ public abstract class AbstractTest {
...
@@ -202,16 +202,16 @@ public abstract class AbstractTest {
}
}
if
(
areEqual
)
{
if
(
areEqual
)
{
System
.
out
.
println
(
"Two buffers have same content."
);
TraceManager
.
addDev
(
"Two buffers have same content."
);
}
else
{
}
else
{
System
.
out
.
println
(
"Two buffers have different content. They differ at line "
+
lineNum
);
TraceManager
.
addDev
(
"Two buffers have different content. They differ at line "
+
lineNum
);
System
.
out
.
println
(
"Buffer1 has "
+
line1
+
" and Buffer2 has "
+
line2
+
" at line "
+
lineNum
);
TraceManager
.
addDev
(
"Buffer1 has "
+
line1
+
" and Buffer2 has "
+
line2
+
" at line "
+
lineNum
);
}
}
reader1
.
close
();
reader1
.
close
();
reader2
.
close
();
reader2
.
close
();
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"FAILED: executing comparison: "
+
e
.
getMessage
());
TraceManager
.
addDev
(
"FAILED: executing comparison: "
+
e
.
getMessage
());
throw
new
AbstractTestException
(
"FAILED: executing comparison: "
+
e
.
getMessage
());
throw
new
AbstractTestException
(
"FAILED: executing comparison: "
+
e
.
getMessage
());
}
}
return
areEqual
;
return
areEqual
;
...
@@ -286,7 +286,7 @@ public abstract class AbstractTest {
...
@@ -286,7 +286,7 @@ public abstract class AbstractTest {
}
}
List
<
String
>
goldenList
=
new
ArrayList
<>();
List
<
String
>
goldenList
=
new
ArrayList
<>();
String
line
;
String
line
;
while
((
line
=
goldenFile
.
readLine
())
!=
null
){
while
((
line
=
goldenFile
.
readLine
())
!=
null
)
{
if
(
line
.
startsWith
(
PROVERIF_QUERY_PREFIX
))
if
(
line
.
startsWith
(
PROVERIF_QUERY_PREFIX
))
goldenList
.
add
(
line
);
goldenList
.
add
(
line
);
}
}
...
@@ -304,7 +304,7 @@ public abstract class AbstractTest {
...
@@ -304,7 +304,7 @@ public abstract class AbstractTest {
String
cleanStr
=
str
.
replaceAll
(
"[0-9]+"
,
""
);
String
cleanStr
=
str
.
replaceAll
(
"[0-9]+"
,
""
);
String
cleanLine
=
line
.
replaceAll
(
"[0-9]+"
,
""
);
String
cleanLine
=
line
.
replaceAll
(
"[0-9]+"
,
""
);
if
(!
cleanStr
.
startsWith
(
cleanLine
.
trim
())
||
cleanLine
.
trim
().
isEmpty
()){
if
(!
cleanStr
.
startsWith
(
cleanLine
.
trim
())
||
cleanLine
.
trim
().
isEmpty
())
{
TraceManager
.
addDev
(
"\""
+
str
+
"\""
+
" not in golden"
);
TraceManager
.
addDev
(
"\""
+
str
+
"\""
+
" not in golden"
);
return
false
;
return
false
;
}
}
...
@@ -323,24 +323,24 @@ public abstract class AbstractTest {
...
@@ -323,24 +323,24 @@ public abstract class AbstractTest {
String
newStr
=
str
;
String
newStr
=
str
;
ArrayList
<
Pair
<
String
,
String
>>
lineComms
=
findIds
(
line
);
ArrayList
<
Pair
<
String
,
String
>>
lineComms
=
findIds
(
line
);
ArrayList
<
Pair
<
String
,
String
>>
strComms
=
findIds
(
str
);
ArrayList
<
Pair
<
String
,
String
>>
strComms
=
findIds
(
str
);
if
(
lineComms
.
size
()!=
strComms
.
size
()){
if
(
lineComms
.
size
()
!=
strComms
.
size
())
{
return
newStr
;
return
newStr
;
}
}
for
(
int
i
=
0
;
i
<
lineComms
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
lineComms
.
size
();
i
++)
{
String
currentIdStr
=
strComms
.
get
(
i
).
getFirst
();
String
currentIdStr
=
strComms
.
get
(
i
).
getFirst
();
if
(
alreadyMapComm
.
containsKey
(
currentIdStr
)){
if
(
alreadyMapComm
.
containsKey
(
currentIdStr
))
{
newStr
=
newStr
.
replaceAll
(
currentIdStr
,
alreadyMapComm
.
get
(
currentIdStr
));
newStr
=
newStr
.
replaceAll
(
currentIdStr
,
alreadyMapComm
.
get
(
currentIdStr
));
}
else
{
}
else
{
newStr
=
newStr
.
replaceAll
(
currentIdStr
,
lineComms
.
get
(
i
).
getFirst
());
newStr
=
newStr
.
replaceAll
(
currentIdStr
,
lineComms
.
get
(
i
).
getFirst
());
alreadyMapComm
.
put
(
currentIdStr
,
lineComms
.
get
(
i
).
getFirst
());
alreadyMapComm
.
put
(
currentIdStr
,
lineComms
.
get
(
i
).
getFirst
());
}
}
TraceManager
.
addDev
(
"\""
+
currentIdStr
+
"\""
+
" has been replaced by "
+
"\""
+
alreadyMapComm
.
get
(
currentIdStr
)
+
"\""
);
TraceManager
.
addDev
(
"\""
+
currentIdStr
+
"\""
+
" has been replaced by "
+
"\""
+
alreadyMapComm
.
get
(
currentIdStr
)
+
"\""
);
}
}
return
newStr
;
return
newStr
;
}
}
private
ArrayList
<
Pair
<
String
,
String
>>
findIds
(
String
query
){
private
ArrayList
<
Pair
<
String
,
String
>>
findIds
(
String
query
)
{
ArrayList
<
Pair
<
String
,
String
>>
comms
=
new
ArrayList
<>();
ArrayList
<
Pair
<
String
,
String
>>
comms
=
new
ArrayList
<>();
if
(
query
.
contains
(
"==>"
)
&&
query
.
matches
(
".*[0-9]+.*"
))
{
if
(
query
.
contains
(
"==>"
)
&&
query
.
matches
(
".*[0-9]+.*"
))
{
int
index
=
query
.
indexOf
(
"==>"
);
int
index
=
query
.
indexOf
(
"==>"
);
...
@@ -367,7 +367,7 @@ public abstract class AbstractTest {
...
@@ -367,7 +367,7 @@ public abstract class AbstractTest {
}
}
queryIndex
+=
incr
;
queryIndex
+=
incr
;
comms
.
add
(
new
Pair
<>(
id
.
toString
(),
position
));
comms
.
add
(
new
Pair
<>(
id
.
toString
(),
position
));
m
=
p
.
matcher
(
query
.
substring
(
queryIndex
));
m
=
p
.
matcher
(
query
.
substring
(
queryIndex
));
}
}
...
...
This diff is collapsed.
Click to expand it.
ttool/src/test/java/tmltranslator/DiplodocusSecurityTest.java
+
21
−
102
View file @
eb0e9127
...
@@ -49,7 +49,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -49,7 +49,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
public
static
void
setUpBeforeClass
()
throws
Exception
{
public
static
void
setUpBeforeClass
()
throws
Exception
{
String
test
=
System
.
getProperty
(
"org.gradle.test.worker"
);
String
test
=
System
.
getProperty
(
"org.gradle.test.worker"
);
String
baseResourcesDir
=
getBaseResourcesDir
();
String
baseResourcesDir
=
getBaseResourcesDir
();
if
(
test
==
null
){
if
(
test
==
null
)
{
baseResourcesDir
=
"test/resources/"
;
baseResourcesDir
=
"test/resources/"
;
}
}
PROVERIF_DIR
=
baseResourcesDir
+
DIR_GEN
;
PROVERIF_DIR
=
baseResourcesDir
+
DIR_GEN
;
...
@@ -59,7 +59,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -59,7 +59,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
}
}
//arguments are defined in @Parameterized.Parameters
//arguments are defined in @Parameterized.Parameters
public
DiplodocusSecurityTest
(
String
model
,
ArrayList
<
String
>
tabs
){
public
DiplodocusSecurityTest
(
String
model
,
ArrayList
<
String
>
tabs
)
{
super
();
super
();
currentModel
=
model
;
currentModel
=
model
;
currentTabs
=
tabs
;
currentTabs
=
tabs
;
...
@@ -68,14 +68,15 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -68,14 +68,15 @@ public class DiplodocusSecurityTest extends AbstractTest {
}
}
@Parameterized
.
Parameters
(
name
=
"{index}: {0}"
)
@Parameterized
.
Parameters
(
name
=
"{index}: {0}"
)
public
static
Collection
models
(){
public
static
Collection
models
()
{
return
Arrays
.
asList
(
new
Object
[][]
{
return
Arrays
.
asList
(
new
Object
[][]
{
//
{"AliceAndBobHW", new ArrayList<>(Arrays.asList("KeyExchange"))}, //the tab which include ID issue in golde
n
//TODO : repair AliceAndBobHW pvspec generatio
n
{
"AliceAndBobHW"
,
new
ArrayList
<>(
Arrays
.
asList
(
"SymmetricExchange"
,
"Nonce"
,
"KeyExchange"
,
"Mac"
,
"SampleAutoSec"
))},
//
{"AliceAndBobHW", new ArrayList<>(Arrays.asList("SymmetricExchange", "Nonce", "KeyExchange", "Mac", "SampleAutoSec"))},
{
"ITA01_v6"
,
new
ArrayList
<>(
Arrays
.
asList
(
"mapAtt"
,
"mapNoProtection"
))},
{
"ITA01_v6"
,
new
ArrayList
<>(
Arrays
.
asList
(
"mapAtt"
,
"mapNoProtection"
))},
{
"Rovers_SPARTA_DIPLO"
,
new
ArrayList
<>(
Arrays
.
asList
(
"NoCountermeasureMapping"
,
"MACMapping"
,
"SymmetricEncryptionNonceMapping"
,
{
"Rovers_SPARTA_DIPLO"
,
new
ArrayList
<>(
Arrays
.
asList
(
"NoCountermeasureMapping"
,
"MACMapping"
))},
"Rover"
))},
// "SymmetricEncryptionNonceMapping" and "Rover" tabs give empty security pragmas from Rovers_SPARTA_DIPLO model
{
"ITSDemo"
,
new
ArrayList
<>(
Arrays
.
asList
(
"Architecture_enc_or"
,
"Architecture_hsm"
))}
//TODO : repair ITSDemo model
//{"ITSDemo", new ArrayList<>(Arrays.asList("Architecture_enc_or", "Architecture_hsm"))}
});
});
}
}
...
@@ -92,7 +93,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -92,7 +93,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
goldenMap
.
clear
();
goldenMap
.
clear
();
//Load current golden map, which is map a tab with its golden pvspec
//Load current golden map, which is map a tab with its golden pvspec
for
(
String
tab
:
currentTabs
){
for
(
String
tab
:
currentTabs
)
{
TraceManager
.
addDev
(
"tab : "
+
tab
);
TraceManager
.
addDev
(
"tab : "
+
tab
);
goldenMap
.
put
(
tab
,
generateGoldenList
(
RESOURCES_DIR
+
currentModel
+
"/"
+
tab
+
"/golden"
));
goldenMap
.
put
(
tab
,
generateGoldenList
(
RESOURCES_DIR
+
currentModel
+
"/"
+
tab
+
"/golden"
));
}
}
...
@@ -102,30 +103,30 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -102,30 +103,30 @@ public class DiplodocusSecurityTest extends AbstractTest {
public
void
testSecurityModels
()
throws
Exception
{
public
void
testSecurityModels
()
throws
Exception
{
// Test if proverif is installed in the path
// Test if proverif is installed in the path
System
.
out
.
println
(
"Testing if \"proverif\" is in the PATH"
);
TraceManager
.
addDev
(
"Testing if \"proverif\" is in the PATH"
);
if
(!(
canExecute
(
"proverif"
)))
{
if
(!(
canExecute
(
"proverif"
)))
{
return
;
return
;
}
}
for
(
String
tab
:
currentTabs
){
for
(
String
tab
:
currentTabs
)
{
System
.
out
.
println
(
"\n\n********** Checking the security of "
+
tab
+
" ********\n"
);
TraceManager
.
addDev
(
"\n\n********** Checking the security of "
+
tab
+
" ********\n"
);
TMLMappingTextSpecification
tmts
=
new
TMLMappingTextSpecification
(
tab
);
TMLMappingTextSpecification
tmts
=
new
TMLMappingTextSpecification
(
tab
);
File
f
=
new
File
(
RESOURCES_DIR
+
currentModel
+
"/"
+
tab
+
"/spec.tmap"
);
File
f
=
new
File
(
RESOURCES_DIR
+
currentModel
+
"/"
+
tab
+
"/spec.tmap"
);
System
.
out
.
println
(
"Loading file: "
+
f
.
getAbsolutePath
());
TraceManager
.
addDev
(
"Loading file: "
+
f
.
getAbsolutePath
());
String
spec
=
null
;
String
spec
=
null
;
try
{
try
{
spec
=
FileUtils
.
loadFileData
(
f
);
spec
=
FileUtils
.
loadFileData
(
f
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"Exception executing: loading "
+
tab
);
TraceManager
.
addDev
(
"Exception executing: loading "
+
tab
);
assertTrue
(
false
);
assertTrue
(
false
);
}
}
System
.
out
.
println
(
"Testing spec "
+
tab
);
TraceManager
.
addDev
(
"Testing spec "
+
tab
);
assertTrue
(
spec
!=
null
);
assertTrue
(
spec
!=
null
);
System
.
out
.
println
(
"Going to parse "
+
tab
);
TraceManager
.
addDev
(
"Going to parse "
+
tab
);
boolean
parsed
=
tmts
.
makeTMLMapping
(
spec
,
RESOURCES_DIR
+
currentModel
+
"/"
+
tab
+
"/"
);
boolean
parsed
=
tmts
.
makeTMLMapping
(
spec
,
RESOURCES_DIR
+
currentModel
+
"/"
+
tab
+
"/"
);
assertTrue
(
parsed
);
assertTrue
(
parsed
);
System
.
out
.
println
(
"Checking syntax "
+
tab
);
TraceManager
.
addDev
(
"Checking syntax "
+
tab
);
// Checking syntax
// Checking syntax
TMLMapping
tmap
=
tmts
.
getTMLMapping
();
TMLMapping
tmap
=
tmts
.
getTMLMapping
();
...
@@ -134,14 +135,14 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -134,14 +135,14 @@ public class DiplodocusSecurityTest extends AbstractTest {
if
(
syntax
.
hasErrors
()
>
0
)
{
if
(
syntax
.
hasErrors
()
>
0
)
{
for
(
TMLError
error:
syntax
.
getErrors
())
{
for
(
TMLError
error:
syntax
.
getErrors
())
{
System
.
out
.
println
(
"Error: "
+
error
.
toString
());
TraceManager
.
addDev
(
"Error: "
+
error
.
toString
());
}
}
}
}
assertTrue
(
syntax
.
hasErrors
()
==
0
);
assertTrue
(
syntax
.
hasErrors
()
==
0
);
// Generate ProVerif code
// Generate ProVerif code
System
.
out
.
println
(
"Generating ProVerif code for "
+
tab
);
TraceManager
.
addDev
(
"Generating ProVerif code for "
+
tab
);
TML2Avatar
t2a
=
new
TML2Avatar
(
tmap
,
false
,
true
,
null
);
TML2Avatar
t2a
=
new
TML2Avatar
(
tmap
,
false
,
true
,
null
);
AvatarSpecification
avatarspec
=
t2a
.
generateAvatarSpec
(
"1"
,
false
);
AvatarSpecification
avatarspec
=
t2a
.
generateAvatarSpec
(
"1"
,
false
);
...
@@ -154,7 +155,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -154,7 +155,7 @@ public class DiplodocusSecurityTest extends AbstractTest {
FileUtils
.
saveFile
(
PROVERIF_DIR
+
pvspecFilename
,
proverif
.
getStringSpec
());
FileUtils
.
saveFile
(
PROVERIF_DIR
+
pvspecFilename
,
proverif
.
getStringSpec
());
TraceManager
.
addDev
(
"Running Proverif"
);
TraceManager
.
addDev
(
"Running Proverif"
);
if
(
goldenMap
.
get
(
tab
)
==
null
){
if
(
goldenMap
.
get
(
tab
)
==
null
)
{
TraceManager
.
addDev
(
"The golden for : "
+
tab
+
" is null"
);
TraceManager
.
addDev
(
"The golden for : "
+
tab
+
" is null"
);
fail
();
fail
();
}
}
...
@@ -165,86 +166,4 @@ public class DiplodocusSecurityTest extends AbstractTest {
...
@@ -165,86 +166,4 @@ public class DiplodocusSecurityTest extends AbstractTest {
TraceManager
.
addDev
(
"Test for "
+
currentModel
+
" model is ended"
);
TraceManager
.
addDev
(
"Test for "
+
currentModel
+
" model is ended"
);
}
}
private
boolean
equals
(
String
line
,
String
str
)
{
str
=
str
.
trim
();
if
(
str
.
startsWith
(
line
.
trim
())
&&
!
line
.
trim
().
isEmpty
())
{
TraceManager
.
addDev
(
"\""
+
str
+
"\""
+
" is in golden"
);
return
true
;
}
String
cleanStr
=
str
.
replaceAll
(
"comm[0-9]+"
,
"comm"
);
String
cleanLine
=
line
.
replaceAll
(
"comm[0-9]+"
,
"comm"
);
if
(!
cleanStr
.
startsWith
(
cleanLine
.
trim
())
||
cleanLine
.
trim
().
isEmpty
()){
TraceManager
.
addDev
(
"\""
+
str
+
"\""
+
" not in golden"
);
return
false
;
}
String
changedStr
=
replaceCommId
(
line
,
str
);
if
(
changedStr
.
startsWith
(
line
.
trim
())
&&
!
line
.
trim
().
isEmpty
())
{
TraceManager
.
addDev
(
"\""
+
changedStr
+
"\""
+
" is in golden"
);
return
true
;
}
TraceManager
.
addDev
(
"\""
+
str
+
"\""
+
" not in golden"
);
return
false
;
}
private
String
replaceCommId
(
String
line
,
String
str
)
{
String
newStr
=
str
;
ArrayList
<
Pair
<
String
,
String
>>
lineComms
=
findComms
(
line
);
ArrayList
<
Pair
<
String
,
String
>>
strComms
=
findComms
(
str
);
if
(
lineComms
.
size
()!=
strComms
.
size
()){
return
newStr
;
}
for
(
int
i
=
0
;
i
<
lineComms
.
size
();
i
++)
{
String
currentIdStr
=
strComms
.
get
(
i
).
getFirst
();
if
(
alreadyMapComm
.
containsKey
(
currentIdStr
)){
newStr
=
newStr
.
replaceAll
(
currentIdStr
,
alreadyMapComm
.
get
(
currentIdStr
));
}
else
{
newStr
=
newStr
.
replaceAll
(
currentIdStr
,
lineComms
.
get
(
i
).
getFirst
());
alreadyMapComm
.
put
(
currentIdStr
,
lineComms
.
get
(
i
).
getFirst
());
}
TraceManager
.
addDev
(
"\""
+
currentIdStr
+
"\""
+
" has been replaced by "
+
"\""
+
alreadyMapComm
.
get
(
currentIdStr
)
+
"\""
);
}
return
newStr
;
}
private
ArrayList
<
Pair
<
String
,
String
>>
findComms
(
String
query
){
ArrayList
<
Pair
<
String
,
String
>>
comms
=
new
ArrayList
<>();
if
(
query
.
contains
(
"==>"
)
&&
query
.
matches
(
".*comm[0-9]+.*"
))
{
int
index
=
query
.
indexOf
(
"==>"
);
int
lookingIndex
=
0
;
//current query substring index
int
queryIndex
=
0
;
//query string index
Pattern
p
=
Pattern
.
compile
(
"comm[0-9]+"
);
Matcher
m
=
p
.
matcher
(
query
);
while
(
m
.
find
())
{
lookingIndex
=
m
.
start
();
queryIndex
+=
lookingIndex
+
4
;
String
idUnit
=
""
+
query
.
charAt
(
queryIndex
);
StringBuilder
id
=
new
StringBuilder
();
int
incr
=
1
;
while
(
idUnit
.
matches
(
"[0-9]"
))
{
id
.
append
(
idUnit
);
idUnit
=
""
+
query
.
charAt
(
queryIndex
+
incr
);
incr
+=
1
;
}
String
position
=
LEFT
;
if
(
queryIndex
>
index
)
{
position
=
RIGHT
;
}
comms
.
add
(
new
Pair
<>(
id
.
toString
(),
position
));
m
=
p
.
matcher
(
query
.
substring
(
queryIndex
));
}
}
return
comms
;
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment