Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Z
zhichan
Overview
Overview
Details
Activity
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
蒋勇
zhichan
Commits
e9cc81da
Commit
e9cc81da
authored
May 07, 2020
by
zhaoxiqing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gsb
parent
54355573
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
121 additions
and
106 deletions
+121
-106
bpo-web/app/base/api/impl/dkcontractApi.js
+1
-0
bpo-web/app/base/api/impl/econtractApi.js
+25
-15
bpo-web/app/base/api/impl/entcontractApi.js
+3
-1
bpo-web/app/base/api/impl/yzcontractApi.js
+4
-2
bpo-web/app/base/controller/impl/ecompanywxuserCtl.js
+1
-0
bpo-web/app/base/controller/impl/userCtl.js
+13
-14
bpo-web/app/base/utils/idcardClient.js
+74
-74
No files found.
bpo-web/app/base/api/impl/dkcontractApi.js
View file @
e9cc81da
...
...
@@ -96,6 +96,7 @@ class DKcontractApi {
return
this
.
returnjson
(
1001001
,
"签名错误"
);
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
dkcontractSve
.
autoSign
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
bpo-web/app/base/api/impl/econtractApi.js
View file @
e9cc81da
...
...
@@ -171,6 +171,11 @@ class EcontractApi {
};
}
for
(
var
idcard
in
idCardList
){
idcard
=
idcard
.
toUpperCase
();
}
try
{
var
signedList
=
await
this
.
econtractSve
.
fiterSignedCards
(
ecompany
.
id
,
idCardList
);
var
unSignList
=
[];
...
...
@@ -243,7 +248,7 @@ class EcontractApi {
// 验证合法性
var
appId
=
obj
.
appId
;
var
nonceStr
=
obj
.
nonceStr
;
var
idNo
=
obj
.
idNo
;
var
idNo
=
obj
.
idNo
.
toUpperCase
()
;
var
startId
=
obj
.
startId
||
0
;
var
userId
=
obj
.
userId
||
""
;
var
userCode
=
obj
.
userCode
||
""
;
...
...
@@ -351,7 +356,7 @@ class EcontractApi {
var
params
=
{
ecompanyId
:
busi
.
ecompany_id
,
startId
:
startId
,
idNo
:
idNo
,
idNo
:
idNo
.
toUpperCase
()
,
pageSize
:
pageSize
,
userId3rd
:
userId
,
};
...
...
@@ -427,7 +432,7 @@ class EcontractApi {
}
var
params
=
{
etemplate_id
:
ecId
,
idNo
:
idNo
,
idNo
:
idNo
.
toUpperCase
()
,
};
try
{
...
...
@@ -532,14 +537,14 @@ class EcontractApi {
async
bankthreeItem
(
item
)
{
var
bankthreelog2
=
{
idName
:
item
.
idName
,
idNo
:
item
.
idNo
,
idNo
:
item
.
idNo
.
toUpperCase
()
,
bankno
:
item
.
bankno
,
pass
:
false
,
}
try
{
var
bankthreeParams
=
{
name
:
item
.
idName
,
//姓名 必填
idno
:
item
.
idNo
,
//身份证 必填
idno
:
item
.
idNo
.
toUpperCase
()
,
//身份证 必填
cardno
:
item
.
bankno
//银行卡 必填
};
...
...
@@ -579,7 +584,7 @@ class EcontractApi {
var
btl
=
await
this
.
bankthreelogSve
.
create
({
appId
:
appId
,
userName
:
userName
,
userIdNo
:
userIdNo
,
userIdNo
:
userIdNo
.
toUpperCase
()
,
userBankNo
:
userBankNo
,
nonceStr
:
nonceStr
,
sign
:
sign
,
...
...
@@ -617,7 +622,7 @@ class EcontractApi {
// var list = await this.econtractSve.findSinedByThree(userName, userIdNo, userBankNo);
let
exists
=
await
this
.
bankthreelogSve
.
findOne
({
userName
:
userName
,
userIdNo
:
userIdNo
,
userIdNo
:
userIdNo
.
toUpperCase
()
,
userBankNo
:
userBankNo
,
result
:
1
,
});
...
...
@@ -632,7 +637,7 @@ class EcontractApi {
var
bankthreeParams
=
{
name
:
userName
,
//姓名 必填
idno
:
userIdNo
,
//身份证 必填
idno
:
userIdNo
.
toUpperCase
()
,
//身份证 必填
cardno
:
userBankNo
//银行卡 必填
};
...
...
@@ -683,7 +688,7 @@ class EcontractApi {
let
exists
=
await
this
.
bankthreelogSve
.
findOne
({
userName
:
userName
,
userIdNo
:
userIdNo
,
userIdNo
:
userIdNo
.
toUpperCase
()
,
userBankNo
:
userBankNo
,
userMobile
:
userMobile
,
result
:
1
,
...
...
@@ -692,7 +697,7 @@ class EcontractApi {
var
btl
=
await
this
.
bankthreelogSve
.
create
({
appId
:
appId
,
userName
:
userName
,
userIdNo
:
userIdNo
,
userIdNo
:
userIdNo
.
toUpperCase
()
,
userBankNo
:
userBankNo
,
userMobile
:
userMobile
,
nonceStr
:
nonceStr
,
...
...
@@ -729,7 +734,7 @@ class EcontractApi {
var
bankParams
=
{
name
:
userName
,
//姓名 必填
idno
:
userIdNo
,
//身份证 必填
idno
:
userIdNo
.
toUpperCase
()
,
//身份证 必填
cardno
:
userBankNo
,
//银行卡 必填
mobile
:
userMobile
,
};
...
...
@@ -791,7 +796,7 @@ class EcontractApi {
var
btl
=
await
this
.
bankthreelogSve
.
create
({
appId
:
appId
,
userName
:
userName
,
userIdNo
:
userIdNo
,
userIdNo
:
userIdNo
.
toUpperCase
()
,
userBankNo
:
userBankNo
,
userMobile
:
userMobile
,
nonceStr
:
nonceStr
,
...
...
@@ -828,7 +833,7 @@ class EcontractApi {
var
bankParams
=
{
name
:
userName
,
//姓名 必填
idno
:
userIdNo
,
//身份证 必填
idno
:
userIdNo
.
toUpperCase
()
,
//身份证 必填
cardno
:
userBankNo
,
//银行卡 必填
mobile
:
userMobile
,
};
...
...
@@ -964,6 +969,7 @@ class EcontractApi {
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
econtractSve
.
autoSign
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -1064,6 +1070,7 @@ class EcontractApi {
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
econtractSve
.
autoSign4
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -1160,6 +1167,7 @@ class EcontractApi {
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
econtractSve
.
autoSigns
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -1229,6 +1237,7 @@ class EcontractApi {
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
econtractSve
.
autoSignTest
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -1318,6 +1327,7 @@ class EcontractApi {
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
econtractSve
.
autoSignPersonalTwo
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -1390,7 +1400,7 @@ class EcontractApi {
async
validateUser
(
obj
,
req
)
{
// 验证合法性
var
idName
=
this
.
trim
(
obj
.
idName
);
var
idNo
=
this
.
trim
(
obj
.
idNo
);
var
idNo
=
this
.
trim
(
obj
.
idNo
.
toUpperCase
()
);
var
accNo
=
this
.
trim
(
obj
.
accNo
);
var
nonceStr
=
obj
.
nonceStr
;
var
sign
=
obj
.
sign
;
...
...
@@ -1687,7 +1697,7 @@ class EcontractApi {
var
idNoList
=
[];
var
idNameList
=
[];
for
(
var
u
of
userList
)
{
idNoList
.
push
(
u
.
idNo
);
idNoList
.
push
(
u
.
idNo
.
toUpperCase
()
);
idNameList
.
push
(
u
.
idName
);
}
...
...
bpo-web/app/base/api/impl/entcontractApi.js
View file @
e9cc81da
...
...
@@ -97,6 +97,7 @@ class EntcontractApi {
return
this
.
returnjson
(
1001001
,
"签名错误"
);
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
entcontractSve
.
autoSign
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -181,6 +182,7 @@ class EntcontractApi {
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
entcontractSve
.
autoSignToPer
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -226,7 +228,7 @@ class EntcontractApi {
var
params
=
{
entcompanyId
:
busi
.
ecompany_id
,
startId
:
startId
,
idNo
:
idNo
,
idNo
:
idNo
.
toUpperCase
()
,
pageSize
:
pageSize
,
userId3rd
:
userId
,
};
...
...
bpo-web/app/base/api/impl/yzcontractApi.js
View file @
e9cc81da
...
...
@@ -203,6 +203,7 @@ class YZContractApi {
return
this
.
returnjson
(
1001001
,
"签名错误"
);
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
entcontractSve
.
yzMerchantAutoSigns
(
param
,
enttemplate
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -288,6 +289,7 @@ class YZContractApi {
return
this
.
returnjson
(
1001001
,
"签名错误"
);
}
try
{
param
.
idNo
=
param
.
idNo
.
toUpperCase
();
var
result
=
await
this
.
econtractSve
.
autoSignNoBank
(
param
);
return
result
;
}
catch
(
error
)
{
...
...
@@ -334,7 +336,7 @@ class YZContractApi {
var
params
=
{
ecompanyId
:
busi
.
ecompany_id
,
startId
:
startId
,
idNo
:
idNo
,
idNo
:
idNo
.
toUpperCase
()
,
pageSize
:
pageSize
,
userId3rd
:
userId
,
};
...
...
@@ -400,7 +402,7 @@ class YZContractApi {
}
var
params
=
{
startId
:
startId
,
idNo
:
idNo
,
idNo
:
idNo
.
toUpperCase
()
,
pageSize
:
pageSize
,
userId3rd
:
merchantId
,
};
...
...
bpo-web/app/base/controller/impl/ecompanywxuserCtl.js
View file @
e9cc81da
...
...
@@ -23,6 +23,7 @@ class ecompanywxuserCtl extends CtlBase {
return
system
.
getErrResult2
(
"您的身份证号格式错误"
);
}
p
.
id_no
=
p
.
id_no
.
toUpperCase
();
var
wxuser
=
{
ecompany_id
:
Number
(
p
.
ecompany_id
),
openId
:
this
.
trim
(
p
.
openId
),
...
...
bpo-web/app/base/controller/impl/userCtl.js
View file @
e9cc81da
...
...
@@ -118,13 +118,13 @@ class UserCtl extends CtlBase {
async
getCurrentUser
(
qobj
,
pobj
,
req
)
{
var
userid
=
req
.
headers
.
referer
.
substr
(
req
.
headers
.
referer
.
indexOf
(
'userid'
)
+
7
);
// var accountInfo = await this.redisClient.get("yd_user_" + userid);
// var mobile = accountInfo.substr(accountInfo.indexOf('mobile') + 9,11);
// var name = accountInfo.substr(accountInfo.indexOf('userName') + 11,accountInfo.indexOf('mobile')-16);
// var personSign = accountInfo.substr(accountInfo.indexOf('personsSign') + 14,18);
// var bankno = accountInfo.substr(accountInfo.indexOf('bankno') + 9,16);
var
accountInfoJson
=
await
this
.
redisClient
.
get
(
"yd_user_"
+
userid
)
||
""
;
var
accountInfo
=
{};
if
(
accountInfoJson
)
{
...
...
@@ -141,7 +141,7 @@ class UserCtl extends CtlBase {
userName
:
name
,
bankno
:
bankno
,
}
var
result
=
{
status
:
0
,
message
:
"success"
,
...
...
@@ -154,7 +154,7 @@ class UserCtl extends CtlBase {
//return system.getResult2(req.session.user);
}
async
loginUser
(
qobj
,
pobj
,
req
)
{
var
u
=
await
super
.
findById
(
req
.
session
.
user
.
id
);
...
...
@@ -230,7 +230,7 @@ class UserCtl extends CtlBase {
var
name
=
accountInfo
.
userName
||
""
;
var
personSign
=
accountInfo
.
personsSign
||
""
;
var
bankno
=
accountInfo
.
bankno
||
""
;
if
(
openid
)
{
var
existedUser
=
await
this
.
service
.
getUserByOpenId
(
openid
,
appkey
);
if
(
existedUser
){
...
...
@@ -241,7 +241,7 @@ class UserCtl extends CtlBase {
content
:
"cookie丢失,urlParam从新load,"
+
JSON
.
stringify
(
req
.
query
)
+
",headers:"
+
JSON
.
stringify
(
req
.
headers
.
referer
),
clientIp
:
""
});
var
tmp
=
{
id
:
existedUser
.
id
,
userName
:
existedUser
.
userName
==
""
?
name
:
existedUser
.
userName
,
...
...
@@ -705,7 +705,7 @@ class UserCtl extends CtlBase {
var
branchCode
=
req
.
query
.
branchCode
||
ecid
;
var
openid3rd
=
req
.
query
.
openid
||
""
;
var
userIdNo
=
(
req
.
query
.
userIdNo
||
""
).
trim
();
var
userIdNo
=
(
req
.
query
.
userIdNo
||
""
).
trim
()
.
toUpperCase
()
;
var
accountInfo
=
{
userName
:
decodeURI
(
req
.
query
.
userName
||
""
)
||
""
,
...
...
@@ -795,8 +795,8 @@ class UserCtl extends CtlBase {
});
}
}
async
loginyd2
(
req
)
{
try
{
//日志记录
...
...
@@ -815,7 +815,7 @@ class UserCtl extends CtlBase {
var
userCode
=
req
.
query
.
userCode
||
""
;
var
branchCode
=
req
.
query
.
branchCode
||
ecid
;
var
userIdNo
=
(
req
.
query
.
userIdNo
||
""
).
trim
();
var
userIdNo
=
(
req
.
query
.
userIdNo
||
""
).
trim
()
.
toUpperCase
()
;
var
accountInfo
=
null
;
if
(
userIdNo
)
{
...
...
@@ -902,7 +902,7 @@ class UserCtl extends CtlBase {
var
userCode
=
req
.
query
.
userCode
||
""
;
var
branchCode
=
req
.
query
.
branchCode
||
ecid
;
var
userIdNo
=
(
req
.
query
.
userIdNo
||
""
).
trim
();
var
userIdNo
=
(
req
.
query
.
userIdNo
||
""
).
trim
()
.
toUpperCase
()
;
var
accountInfo
=
null
;
if
(
userIdNo
)
{
...
...
@@ -1002,7 +1002,7 @@ class UserCtl extends CtlBase {
}
// var loginUser = await this.service.findById(userid);
//var loginUser = await this.service.findById(req.session.user.id);
pobj
.
personsSign
=
pobj
.
personsSign
.
toUpperCase
();
let
uep
=
{
personsSign
:
pobj
.
personsSign
}
...
...
@@ -1319,4 +1319,4 @@ class UserCtl extends CtlBase {
}
}
module
.
exports
=
UserCtl
;
\ No newline at end of file
module
.
exports
=
UserCtl
;
bpo-web/app/base/utils/idcardClient.js
View file @
e9cc81da
...
...
@@ -9,84 +9,84 @@ class IdcardClient {
this
.
check_code
=
[
'1'
,
'0'
,
'X'
,
'9'
,
'8'
,
'7'
,
'6'
,
'5'
,
'4'
,
'3'
,
'2'
];
}
// async checkIDCard(idcard) {
// if (!idcard) {
// return false;
// }
// idcard = idcard.toUpperCase();
// var code = idcard.toString().toUpperCase();
// var last = idcard[17];//最后一个
//
// var seventeen = code.substring(0, 17);
//
// // ISO 7064:1983.MOD 11-2
// // 判断最后一位校验码是否正确
// var arr = seventeen.split("");
// var len = arr.length;
// var num = 0;
// for (var i = 0; i < len; i++) {
// num = num + arr[i] * this.weight_factor[i];
// }
//
// // 获取余数
// var resisue = num % 11;
// var last_no = this.check_code[resisue];
//
// // 格式的正则
// // 正则思路
// /*
// 第一位不可能是0
// 第二位到第六位可以是0-9
// 第七位到第十位是年份,所以七八位为19或者20
// 十一位和十二位是月份,这两位是01-12之间的数值
// 十三位和十四位是日期,是从01-31之间的数值
// 十五,十六,十七都是数字0-9
// 十八位可能是数字0-9,也可能是X
// */
// var idcard_patter = /^[1-9][0-9]{5}([1][9][0-9]{2}|[2][0][0|1][0-9])([0][1-9]|[1][0|1|2])([0][1-9]|[1|2][0-9]|[3][0|1])[0-9]{3}([0-9]|[X])$/;
//
// // 判断格式是否正确
// var format = idcard_patter.test(idcard);
//
// // 返回验证结果,校验码和格式同时正确才算是合法的身份证号码
// return last === last_no && format ? true : false;
// }
async
checkIDCard
(
idCard
)
{
//15位和18位身份证号码的正则表达式
var
regIdCard
=
/^
(
^
[
1-9
]\d{7}((
0
\d)
|
(
1
[
0-2
]))(([
0|1|2
]\d)
|3
[
0-1
])\d{3}
$
)
|
(
^
[
1-9
]\d{5}[
1-9
]\d{3}((
0
\d)
|
(
1
[
0-2
]))(([
0|1|2
]\d)
|3
[
0-1
])((\d{4})
|
\d{3}[
Xx
])
$
)
$/
;
//如果通过该验证,说明身份证格式正确,但准确性还需计算
if
(
regIdCard
.
test
(
idCard
))
{
if
(
idCard
.
length
==
18
)
{
var
idCardWi
=
new
Array
(
7
,
9
,
10
,
5
,
8
,
4
,
2
,
1
,
6
,
3
,
7
,
9
,
10
,
5
,
8
,
4
,
2
);
//将前17位加权因子保存在数组里
var
idCardY
=
new
Array
(
1
,
0
,
10
,
9
,
8
,
7
,
6
,
5
,
4
,
3
,
2
);
//这是除以11后,可能产生的11位余数、验证码,也保存成数组
var
idCardWiSum
=
0
;
//用来保存前17位各自乖以加权因子后的总和
for
(
var
i
=
0
;
i
<
17
;
i
++
)
{
idCardWiSum
+=
idCard
.
substring
(
i
,
i
+
1
)
*
idCardWi
[
i
];
}
var
idCardMod
=
idCardWiSum
%
11
;
//计算出校验码所在数组的位置
var
idCardLast
=
idCard
.
substring
(
17
);
//得到最后一位身份证号码
//如果等于2,则说明校验码是10,身份证号码最后一位应该是X
if
(
idCardMod
==
2
)
{
if
(
idCardLast
==
"X"
||
idCardLast
==
"x"
)
{
return
true
;
}
else
{
return
false
;
}
}
else
{
//用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
if
(
idCardLast
==
idCardY
[
idCardMod
])
{
return
true
;
}
else
{
return
false
;
}
}
}
}
else
{
async
checkIDCard
(
idcard
)
{
if
(
!
idcard
)
{
return
false
;
}
idcard
=
idcard
.
toUpperCase
();
var
code
=
idcard
.
toString
().
toUpperCase
();
var
last
=
idcard
[
17
];
//最后一个
var
seventeen
=
code
.
substring
(
0
,
17
);
// ISO 7064:1983.MOD 11-2
// 判断最后一位校验码是否正确
var
arr
=
seventeen
.
split
(
""
);
var
len
=
arr
.
length
;
var
num
=
0
;
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
num
=
num
+
arr
[
i
]
*
this
.
weight_factor
[
i
];
}
// 获取余数
var
resisue
=
num
%
11
;
var
last_no
=
this
.
check_code
[
resisue
];
// 格式的正则
// 正则思路
/*
第一位不可能是0
第二位到第六位可以是0-9
第七位到第十位是年份,所以七八位为19或者20
十一位和十二位是月份,这两位是01-12之间的数值
十三位和十四位是日期,是从01-31之间的数值
十五,十六,十七都是数字0-9
十八位可能是数字0-9,也可能是X
*/
var
idcard_patter
=
/^
[
1-9
][
0-9
]{5}([
1
][
9
][
0-9
]{2}
|
[
2
][
0
][
0|1
][
0-9
])([
0
][
1-9
]
|
[
1
][
0|1|2
])([
0
][
1-9
]
|
[
1|2
][
0-9
]
|
[
3
][
0|1
])[
0-9
]{3}([
0-9
]
|
[
X
])
$/
;
// 判断格式是否正确
var
format
=
idcard_patter
.
test
(
idcard
);
// 返回验证结果,校验码和格式同时正确才算是合法的身份证号码
return
last
===
last_no
&&
format
?
true
:
false
;
}
// async checkIDCard(idCard) {
// //15位和18位身份证号码的正则表达式
// var regIdCard = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;
// //如果通过该验证,说明身份证格式正确,但准确性还需计算
// if (regIdCard.test(idCard)) {
// if (idCard.length == 18) {
// var idCardWi = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //将前17位加权因子保存在数组里
// var idCardY = new Array(1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2); //这是除以11后,可能产生的11位余数、验证码,也保存成数组
// var idCardWiSum = 0; //用来保存前17位各自乖以加权因子后的总和
// for (var i = 0; i < 17; i++) {
// idCardWiSum += idCard.substring(i, i + 1) * idCardWi[i];
// }
// var idCardMod = idCardWiSum % 11;//计算出校验码所在数组的位置
// var idCardLast = idCard.substring(17);//得到最后一位身份证号码
// //如果等于2,则说明校验码是10,身份证号码最后一位应该是X
// if (idCardMod == 2) {
// if (idCardLast == "X" || idCardLast == "x") {
// return true;
// } else {
// return false;
// }
// } else {
// //用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
// if (idCardLast == idCardY[idCardMod]) {
// return true;
// } else {
// return false;
// }
// }
// }
// } else {
// return false;
// }
// }
/**
*
* @param card
...
...
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