Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
Sobot_module_Dev
Project
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sobot_android
Sobot_module_Dev
Commits
c0ae4bc4
Commit
c0ae4bc4
authored
Feb 14, 2022
by
郑娜伟
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改bug
parent
b0b74922
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
77 additions
and
388 deletions
+77
-388
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+5
-3
MainActivity.java
app/src/main/java/com/sobot/moduletest/MainActivity.java
+19
-16
MyApp.java
app/src/main/java/com/sobot/moduletest/MyApp.java
+5
-2
build.gradle
sobot_common/build.gradle
+7
-7
sobot-common-publish-mavencentral.gradle
sobot_common/sobot-common-publish-mavencentral.gradle
+2
-2
SobotBaseActivity.java
...main/java/com/sobot/common/ui/base/SobotBaseActivity.java
+2
-2
SobotGlobalContext.java
.../main/java/com/sobot/common/utils/SobotGlobalContext.java
+22
-0
build.gradle
sobot_network/build.gradle
+13
-13
sobot-network-publish-mavencentral.gradle
sobot_network/sobot-network-publish-mavencentral.gradle
+1
-1
SobotBaseUrl.java
...rc/main/java/com/sobot/network/apiUtils/SobotBaseUrl.java
+0
-37
OkHttpUtils.java
...ork/src/main/java/com/sobot/network/http/OkHttpUtils.java
+0
-298
SobotOkHttpUtils.java
...rc/main/java/com/sobot/network/http/SobotOkHttpUtils.java
+1
-7
No files found.
app/src/main/AndroidManifest.xml
View file @
c0ae4bc4
...
...
@@ -2,16 +2,18 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.sobot.moduletest"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<application
android:name=
".MyApp"
android:allowBackup=
"true"
android:icon=
"@mipmap/ic_launcher"
android:label=
"@string/app_name"
android:roundIcon=
"@mipmap/ic_launcher_round"
android:name=
".MyApp"
android:supportsRtl=
"true"
>
<activity
android:name=
".MainActivity"
>
<activity
android:name=
".MainActivity"
android:configChanges=
"orientation|keyboardHidden|screenSize|touchscreen|navigation|locale|fontScale|uiMode|screenLayout|smallestScreenSize"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
...
...
app/src/main/java/com/sobot/moduletest/MainActivity.java
View file @
c0ae4bc4
...
...
@@ -12,6 +12,7 @@ import com.sobot.common.ui.toast.SobotToastUtil;
import
com.sobot.common.utils.SobotCommonApi
;
import
com.sobot.common.utils.SobotImageUtils
;
import
com.sobot.network.http.HttpUtils
;
import
com.sobot.network.http.db.SobotDownloadManager
;
import
com.sobot.pictureframe.SobotBitmapUtil
;
import
com.sobot.utils.SobotLogUtils
;
...
...
@@ -41,6 +42,8 @@ public class MainActivity extends SobotBaseActivity {
img2
=
findViewById
(
R
.
id
.
img2
);
SobotBitmapUtil
.
display
(
this
,
R
.
mipmap
.
ic_launcher
,
img2
);
SobotDownloadManager
.
getInstance
().
get
(
"sdfsdfds"
);
Map
<
String
,
String
>
map
=
new
HashMap
<>();
map
.
put
(
"number"
,
"142160000"
);
map
.
put
(
"companyId"
,
"1eae128b7e394aedafd28828bfa84767"
);
...
...
@@ -54,22 +57,22 @@ public class MainActivity extends SobotBaseActivity {
map
.
put
(
"groupId"
,
"36b0f8eb2de948d99e89c8f0c3d92e68_5"
);
map
.
put
(
"agentPhoneNum"
,
"18600978969"
);
HttpUtils
.
getInstance
().
doPostByJsonString
(
this
,
"https://sobot.com/comm/api/4/call/agentOnWork?access_token=c273b74c-3b37-48cf-937f-9c46940cc19d"
,
map
,
null
,
new
HttpUtils
.
StringCallBack
()
{
@Override
public
void
onResponse
(
String
result
)
{
SobotLogUtils
.
i
(
result
);
}
@Override
public
void
onError
(
Exception
e
,
String
msg
,
int
responseCode
)
{
}
@Override
public
void
inProgress
(
int
progress
)
{
}
});
//
HttpUtils.getInstance().doPostByJsonString(this, "https://sobot.com/comm/api/4/call/agentOnWork?access_token=c273b74c-3b37-48cf-937f-9c46940cc19d", map, null, new HttpUtils.StringCallBack() {
//
@Override
//
public void onResponse(String result) {
//
SobotLogUtils.i(result);
//
}
//
//
@Override
//
public void onError(Exception e, String msg, int responseCode) {
//
//
}
//
//
@Override
//
public void inProgress(int progress) {
//
//
}
//
});
// selectPicFromLocal();
// selectVedioFromLocal();
// openCamera();
...
...
app/src/main/java/com/sobot/moduletest/MyApp.java
View file @
c0ae4bc4
...
...
@@ -2,6 +2,7 @@ package com.sobot.moduletest;
import
android.app.Application
;
import
com.sobot.common.ui.SobotMarkConfig
;
import
com.sobot.common.utils.SobotCommonApi
;
import
com.sobot.network.http.log.SobotNetLogUtils
;
import
com.sobot.utils.SobotLogUtils
;
...
...
@@ -18,8 +19,9 @@ public class MyApp extends Application {
super
.
onCreate
();
SobotCommonApi
.
init
(
this
);
SobotNetLogUtils
.
setShowDebug
(
true
);
SobotLogUtils
.
setShowDebug
(
true
);
SobotCommonApi
.
setShowLogDebug
(
true
);
SobotCommonApi
.
setSwitchMarkStatus
(
SobotMarkConfig
.
LANDSCAPE_SCREEN
,
true
);
SobotCommonApi
.
setSwitchMarkStatus
(
SobotMarkConfig
.
DISPLAY_INNOTCH
,
true
);
}
}
\ No newline at end of file
sobot_common/build.gradle
View file @
c0ae4bc4
...
...
@@ -22,15 +22,15 @@ dependencies {
// api project(':sobot_network')
// api project(':sobot_gson')
// api 'com.sobot.library:utils:1.1'
// api 'com.sobot.library:picture:1.1'
// api 'com.sobot.library:net:1.1'
// api 'com.sobot.library:gson:1.1'
api
'com.sobot.library:utils:1.1'
api
'com.sobot.library:picture
_x
:1.1'
api
'com.sobot.library:net:1.1'
api
'com.sobot.library:picture:1.1'
api
'com.sobot.library:net:1.1
.0
'
api
'com.sobot.library:gson:1.1'
// api 'com.sobot.library:utils:1.1'
// api 'com.sobot.library:picture_x:1.1'
// api 'com.sobot.library:net:1.1.0'
// api 'com.sobot.library:gson:1.1'
}
...
...
sobot_common/sobot-common-publish-mavencentral.gradle
View file @
c0ae4bc4
...
...
@@ -12,8 +12,8 @@ task androidSourcesJar(type: Jar) {
ext
{
PUBLISH_GROUP_ID
=
"com.sobot.library"
//项目包名
PUBLISH_ARTIFACT_ID
=
'sobotcommon'
//项目名
PUBLISH_ARTIFACT_ID
=
'sobotcommon_x'
//项目名
PUBLISH_VERSION
=
'1.0'
//版本号
//
PUBLISH_ARTIFACT_ID = 'sobotcommon_x' //项目名
PUBLISH_VERSION
=
'1.0
.1
'
//版本号
}
...
...
sobot_common/src/main/java/com/sobot/common/ui/base/SobotBaseActivity.java
View file @
c0ae4bc4
...
...
@@ -92,7 +92,7 @@ public abstract class SobotBaseActivity extends FragmentActivity {
setUpToolBarRightMenu
();
}
try
{
initBundleData
(
savedInstanceState
);
//
initBundleData(savedInstanceState);
initView
();
initData
();
}
catch
(
Exception
e
)
{
...
...
@@ -270,7 +270,7 @@ public abstract class SobotBaseActivity extends FragmentActivity {
@Override
protected
void
onDestroy
()
{
SobotGlobalContext
.
getInstance
(
getSobotBaseActivity
()).
finish
Activity
(
this
);
SobotGlobalContext
.
getInstance
(
getSobotBaseActivity
()).
remove
Activity
(
this
);
super
.
onDestroy
();
}
...
...
sobot_common/src/main/java/com/sobot/common/utils/SobotGlobalContext.java
View file @
c0ae4bc4
...
...
@@ -176,6 +176,28 @@ public class SobotGlobalContext {
}
}
/**
* 移除指定的Activity
*
* @param activity 指定的activity实例
*/
public
void
removeActivity
(
Activity
activity
)
{
if
(
activity
!=
null
)
{
for
(
Iterator
<
WeakReference
<
Activity
>>
it
=
mActivityStack
.
iterator
();
it
.
hasNext
();
)
{
WeakReference
<
Activity
>
activityReference
=
it
.
next
();
Activity
temp
=
activityReference
.
get
();
if
(
temp
==
null
)
{
// 清理掉已经释放的activity
it
.
remove
();
continue
;
}
if
(
temp
==
activity
)
{
it
.
remove
();
}
}
}
}
/**
* 结束指定类名的所有Activity
*
...
...
sobot_network/build.gradle
View file @
c0ae4bc4
...
...
@@ -9,19 +9,19 @@ android {
}
//这里就是打jar包
//
task makeJar(type: Copy) {
//
//删除旧的jar包
// delete 'build/libs/sobot_net_
1.0.jar'
//
//原地址
//
from('build/intermediates/packaged-classes/release/')
//
//导出jar包的地址
//
into('build/libs/')
//
//包含的jar包
//
include('classes.jar')
//
//重命名jar包为mysdk
// rename ('classes.jar', 'sobot_net_
1.0.jar')
//
}
//
makeJar.dependsOn(build)
task
makeJar
(
type:
Copy
)
{
//删除旧的jar包
delete
'build/libs/sobot_net_1.
1.0.jar'
//原地址
from
(
'build/intermediates/packaged-classes/release/'
)
//导出jar包的地址
into
(
'build/libs/'
)
//包含的jar包
include
(
'classes.jar'
)
//重命名jar包为mysdk
rename
(
'classes.jar'
,
'sobot_net_1.
1.0.jar'
)
}
makeJar
.
dependsOn
(
build
)
}
...
...
sobot_network/sobot-network-publish-mavencentral.gradle
View file @
c0ae4bc4
...
...
@@ -12,7 +12,7 @@ task androidSourcesJar(type: Jar) {
ext
{
PUBLISH_GROUP_ID
=
"com.sobot.library"
//项目包名
PUBLISH_ARTIFACT_ID
=
'net'
//项目名
PUBLISH_VERSION
=
'1.1'
//版本号
PUBLISH_VERSION
=
'1.1
.0
'
//版本号
}
...
...
sobot_network/src/main/java/com/sobot/network/apiUtils/SobotBaseUrl.java
deleted
100644 → 0
View file @
b0b74922
package
com
.
sobot
.
network
.
apiUtils
;
import
android.text.TextUtils
;
/**
* @author Created by jinxl on 2018/4/9.
*/
public
class
SobotBaseUrl
{
public
static
final
String
defaultHostname
=
"api.sobot.com"
;
private
static
final
String
baseHost
=
"https://"
+
defaultHostname
+
"/"
;
private
static
String
api_host
;
public
static
void
setApi_Host
(
String
apiHost
)
{
if
(!
TextUtils
.
isEmpty
(
apiHost
))
{
if
(!
apiHost
.
endsWith
(
"/"
))
{
api_host
=
apiHost
+
"/"
;
}
else
{
api_host
=
apiHost
;
}
}
}
public
static
String
getApi_Host
()
{
if
(!
TextUtils
.
isEmpty
(
api_host
))
{
return
api_host
;
}
return
baseHost
;
}
public
static
String
getBaseIp
()
{
return
getApi_Host
()
+
"/chat/sdk/admin/v1/"
;
}
}
sobot_network/src/main/java/com/sobot/network/http/OkHttpUtils.java
deleted
100644 → 0
View file @
b0b74922
package
com
.
sobot
.
network
.
http
;
import
android.annotation.SuppressLint
;
import
android.os.Handler
;
import
android.os.Looper
;
import
com.sobot.network.apiUtils.SobotBaseUrl
;
import
com.sobot.network.http.builder.GetBuilder
;
import
com.sobot.network.http.builder.HeadBuilder
;
import
com.sobot.network.http.builder.OtherRequestBuilder
;
import
com.sobot.network.http.builder.PostFileBuilder
;
import
com.sobot.network.http.builder.PostFormBuilder
;
import
com.sobot.network.http.builder.PostStringBuilder
;
import
com.sobot.network.http.callback.Callback
;
import
com.sobot.network.http.callback.FileCallBack
;
import
com.sobot.network.http.log.SobotNetLogUtils
;
import
com.sobot.network.http.request.RequestCall
;
import
java.io.IOException
;
import
java.security.KeyStore
;
import
java.security.SecureRandom
;
import
java.util.Arrays
;
import
java.util.concurrent.TimeUnit
;
import
javax.net.ssl.HostnameVerifier
;
import
javax.net.ssl.HttpsURLConnection
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLSession
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.net.ssl.TrustManager
;
import
javax.net.ssl.TrustManagerFactory
;
import
javax.net.ssl.X509TrustManager
;
import
okhttp3.Call
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Response
;
public
class
OkHttpUtils
{
public
static
final
long
DEFAULT_MILLISECONDS
=
10000
;
private
static
OkHttpUtils
mInstance
;
private
OkHttpClient
mOkHttpClient
;
private
Handler
mDelivery
;
public
OkHttpUtils
(
OkHttpClient
okHttpClient
)
{
if
(
okHttpClient
==
null
)
{
OkHttpClient
.
Builder
okHttpClientBuilder
=
new
OkHttpClient
.
Builder
();
okHttpClientBuilder
.
addInterceptor
(
new
SobotInternetPermissionExceptionInterceptor
());
mDelivery
=
new
Handler
(
Looper
.
getMainLooper
());
okHttpClientBuilder
.
hostnameVerifier
(
new
HostnameVerifier
()
{
@Override
public
boolean
verify
(
String
hostname
,
SSLSession
session
)
{
if
(
SobotBaseUrl
.
getApi_Host
().
contains
(
hostname
))
{
return
true
;
}
else
{
HostnameVerifier
hv
=
HttpsURLConnection
.
getDefaultHostnameVerifier
();
return
hv
.
verify
(
hostname
,
session
);
}
}
});
try
{
//优化X509TrustManager安全警告问题
TrustManagerFactory
trustManagerFactory
=
TrustManagerFactory
.
getInstance
(
TrustManagerFactory
.
getDefaultAlgorithm
());
trustManagerFactory
.
init
((
KeyStore
)
null
);
TrustManager
[]
trustManagers
=
trustManagerFactory
.
getTrustManagers
();
if
(
trustManagers
.
length
!=
1
||
!(
trustManagers
[
0
]
instanceof
X509TrustManager
))
{
SobotNetLogUtils
.
e
(
"Unexpected default trust managers:"
+
Arrays
.
toString
(
trustManagers
));
}
X509TrustManager
manager
=
(
X509TrustManager
)
trustManagers
[
0
];
okHttpClientBuilder
.
sslSocketFactory
(
createSSLSocketFactory
(
manager
),
manager
);
mOkHttpClient
=
okHttpClientBuilder
.
build
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
else
{
mOkHttpClient
=
okHttpClient
;
}
}
public
static
OkHttpUtils
getInstance
(
OkHttpClient
okHttpClient
)
{
if
(
mInstance
==
null
)
{
synchronized
(
OkHttpUtils
.
class
)
{
if
(
mInstance
==
null
)
{
mInstance
=
new
OkHttpUtils
(
okHttpClient
);
}
}
}
return
mInstance
;
}
public
static
OkHttpUtils
getInstance
()
{
if
(
mInstance
==
null
)
{
synchronized
(
OkHttpUtils
.
class
)
{
if
(
mInstance
==
null
)
{
mInstance
=
new
OkHttpUtils
(
null
);
}
}
}
return
mInstance
;
}
public
void
setOkHttpClient
(
OkHttpClient
client
)
{
mOkHttpClient
=
client
;
}
public
Handler
getDelivery
()
{
return
mDelivery
;
}
public
OkHttpClient
getOkHttpClient
()
{
return
mOkHttpClient
;
}
public
static
GetBuilder
get
()
{
return
new
GetBuilder
();
}
public
static
PostStringBuilder
postString
()
{
return
new
PostStringBuilder
();
}
public
static
PostFileBuilder
postFile
()
{
return
new
PostFileBuilder
();
}
public
static
PostFormBuilder
post
()
{
return
new
PostFormBuilder
();
}
public
static
OtherRequestBuilder
put
()
{
return
new
OtherRequestBuilder
(
METHOD
.
PUT
);
}
public
static
HeadBuilder
head
()
{
return
new
HeadBuilder
();
}
public
static
OtherRequestBuilder
delete
()
{
return
new
OtherRequestBuilder
(
METHOD
.
DELETE
);
}
public
static
OtherRequestBuilder
patch
()
{
return
new
OtherRequestBuilder
(
METHOD
.
PATCH
);
}
@SuppressWarnings
(
"rawtypes"
)
public
void
execute
(
final
RequestCall
requestCall
,
Callback
callback
)
{
if
(
callback
==
null
)
callback
=
Callback
.
CALLBACK_DEFAULT
;
final
Callback
finalCallback
=
callback
;
requestCall
.
getCall
().
enqueue
(
new
okhttp3
.
Callback
()
{
@Override
public
void
onFailure
(
Call
call
,
final
IOException
e
)
{
sendFailResultCallback
(
call
,
e
,
finalCallback
);
}
@Override
public
void
onResponse
(
final
Call
call
,
final
Response
response
)
{
if
(!
response
.
isSuccessful
())
{
try
{
sendFailResultCallback
(
call
,
new
RuntimeException
(
response
.
body
().
string
()),
finalCallback
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
;
}
try
{
Object
o
=
finalCallback
.
parseNetworkResponse
(
response
);
sendSuccessResultCallback
(
o
,
finalCallback
);
}
catch
(
Exception
e
)
{
sendFailResultCallback
(
call
,
e
,
finalCallback
);
}
}
});
}
@SuppressWarnings
(
"rawtypes"
)
public
void
sendFailResultCallback
(
final
Call
call
,
final
Exception
e
,
final
Callback
callback
)
{
if
(
callback
==
null
||
call
.
isCanceled
())
return
;
mDelivery
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
callback
.
onError
(
call
,
e
);
callback
.
onAfter
();
}
});
}
@SuppressWarnings
(
"rawtypes"
)
public
void
sendSuccessResultCallback
(
final
Object
object
,
final
Callback
callback
)
{
if
(
callback
==
null
)
return
;
mDelivery
.
post
(
new
Runnable
()
{
@SuppressWarnings
(
"unchecked"
)
@Override
public
void
run
()
{
callback
.
onResponse
(
object
);
callback
.
onAfter
();
}
});
}
public
static
void
runOnUiThread
(
Runnable
runnable
)
{
OkHttpUtils
.
getInstance
().
mDelivery
.
post
(
runnable
);
}
public
void
cancelTag
(
Object
tag
)
{
for
(
Call
call
:
mOkHttpClient
.
dispatcher
().
queuedCalls
())
{
if
(
tag
.
equals
(
call
.
request
().
tag
()))
{
call
.
cancel
();
}
}
for
(
Call
call
:
mOkHttpClient
.
dispatcher
().
runningCalls
())
{
if
(
tag
.
equals
(
call
.
request
().
tag
()))
{
call
.
cancel
();
}
}
}
/*public void cancelAll()
{
for (Call call : mOkHttpClient.dispatcher().queuedCalls())
{
call.cancel();
}
for (Call call : mOkHttpClient.dispatcher().runningCalls())
{
call.cancel();
}
}*/
public
void
setHostNameVerifier
(
HostnameVerifier
hostNameVerifier
)
{
mOkHttpClient
=
getOkHttpClient
().
newBuilder
()
.
hostnameVerifier
(
hostNameVerifier
)
.
build
();
}
public
void
setConnectTimeout
(
int
timeout
,
TimeUnit
units
)
{
mOkHttpClient
=
getOkHttpClient
().
newBuilder
()
.
connectTimeout
(
timeout
,
units
)
.
build
();
}
public
void
setReadTimeout
(
int
timeout
,
TimeUnit
units
)
{
mOkHttpClient
=
getOkHttpClient
().
newBuilder
()
.
readTimeout
(
timeout
,
units
)
.
build
();
}
public
void
setWriteTimeout
(
int
timeout
,
TimeUnit
units
)
{
mOkHttpClient
=
getOkHttpClient
().
newBuilder
()
.
writeTimeout
(
timeout
,
units
)
.
build
();
}
public
static
void
download
(
String
url
,
FileCallBack
fileCallBack
)
{
OkHttpUtils
//
.
get
()
//
.
url
(
url
)
//
.
build
()
//
.
execute
(
fileCallBack
);
}
public
static
class
METHOD
{
public
static
final
String
HEAD
=
"HEAD"
;
public
static
final
String
DELETE
=
"DELETE"
;
public
static
final
String
PUT
=
"PUT"
;
public
static
final
String
PATCH
=
"PATCH"
;
}
/**
* 默认信任所有的证书
* @return
*/
@SuppressLint
(
"TrulyRandom"
)
private
static
SSLSocketFactory
createSSLSocketFactory
(
X509TrustManager
manager
)
{
SSLSocketFactory
sSLSocketFactory
=
null
;
try
{
SSLContext
sc
=
SSLContext
.
getInstance
(
"TLS"
);
sc
.
init
(
null
,
new
TrustManager
[]{
manager
},
new
SecureRandom
());
sSLSocketFactory
=
sc
.
getSocketFactory
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
sSLSocketFactory
;
}
}
\ No newline at end of file
sobot_network/src/main/java/com/sobot/network/http/SobotOkHttpUtils.java
View file @
c0ae4bc4
...
...
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint;
import
android.os.Handler
;
import
android.os.Looper
;
import
com.sobot.network.apiUtils.SobotBaseUrl
;
import
com.sobot.network.http.builder.GetBuilder
;
import
com.sobot.network.http.builder.HeadBuilder
;
import
com.sobot.network.http.builder.OtherRequestBuilder
;
...
...
@@ -53,12 +52,7 @@ public class SobotOkHttpUtils {
okHttpClientBuilder
.
hostnameVerifier
(
new
HostnameVerifier
()
{
@Override
public
boolean
verify
(
String
hostname
,
SSLSession
session
)
{
if
(
SobotBaseUrl
.
getApi_Host
().
contains
(
hostname
))
{
return
true
;
}
else
{
HostnameVerifier
hv
=
HttpsURLConnection
.
getDefaultHostnameVerifier
();
return
hv
.
verify
(
hostname
,
session
);
}
return
true
;
}
});
try
{
...
...
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