Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
cordova-custom
Cordova Plugin Advanced Http
Commits
09c88efe
Commit
09c88efe
authored
Mar 26, 2024
by
Chok
Browse files
chok: init commit
parent
02cfb854
Pipeline
#18
failed with stages
in 0 seconds
Changes
74
Pipelines
2
Expand all
Hide whitespace changes
Inline
Side-by-side
src/android/com/silkimen/cordovahttp/CordovaHttpOperation.java
0 → 100644
View file @
09c88efe
package
com.silkimen.cordovahttp
;
import
javax.net.ssl.HostnameVerifier
;
import
javax.net.ssl.SSLSocketFactory
;
import
com.silkimen.http.TLSConfiguration
;
import
org.json.JSONObject
;
class
CordovaHttpOperation
extends
CordovaHttpBase
{
public
CordovaHttpOperation
(
String
method
,
String
url
,
String
serializer
,
Object
data
,
JSONObject
headers
,
int
connectTimeout
,
int
readTimeout
,
boolean
followRedirects
,
String
responseType
,
TLSConfiguration
tlsConfiguration
,
CordovaObservableCallbackContext
callbackContext
)
{
super
(
method
,
url
,
serializer
,
data
,
headers
,
connectTimeout
,
readTimeout
,
followRedirects
,
responseType
,
tlsConfiguration
,
callbackContext
);
}
public
CordovaHttpOperation
(
String
method
,
String
url
,
JSONObject
headers
,
int
connectTimeout
,
int
readTimeout
,
boolean
followRedirects
,
String
responseType
,
TLSConfiguration
tlsConfiguration
,
CordovaObservableCallbackContext
callbackContext
)
{
super
(
method
,
url
,
headers
,
connectTimeout
,
readTimeout
,
followRedirects
,
responseType
,
tlsConfiguration
,
callbackContext
);
}
}
src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java
0 → 100644
View file @
09c88efe
package
com.silkimen.cordovahttp
;
import
java.security.KeyStore
;
import
java.util.HashMap
;
import
java.util.Observable
;
import
java.util.Observer
;
import
java.util.concurrent.Future
;
import
com.silkimen.http.TLSConfiguration
;
import
org.apache.cordova.CallbackContext
;
import
org.apache.cordova.CordovaInterface
;
import
org.apache.cordova.CordovaPlugin
;
import
org.apache.cordova.CordovaWebView
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
android.content.Context
;
import
android.net.ConnectivityManager
;
import
android.net.NetworkInfo
;
import
android.util.Log
;
import
android.util.Base64
;
import
javax.net.ssl.TrustManagerFactory
;
public
class
CordovaHttpPlugin
extends
CordovaPlugin
implements
Observer
{
private
static
final
String
TAG
=
"Cordova-Plugin-HTTP"
;
private
TLSConfiguration
tlsConfiguration
;
private
HashMap
<
Integer
,
Future
<?>>
reqMap
;
private
final
Object
reqMapLock
=
new
Object
();
@Override
public
void
initialize
(
CordovaInterface
cordova
,
CordovaWebView
webView
)
{
super
.
initialize
(
cordova
,
webView
);
this
.
tlsConfiguration
=
new
TLSConfiguration
();
this
.
reqMap
=
new
HashMap
<
Integer
,
Future
<?>>();
try
{
KeyStore
store
=
KeyStore
.
getInstance
(
"AndroidCAStore"
);
String
tmfAlgorithm
=
TrustManagerFactory
.
getDefaultAlgorithm
();
TrustManagerFactory
tmf
=
TrustManagerFactory
.
getInstance
(
tmfAlgorithm
);
store
.
load
(
null
);
tmf
.
init
(
store
);
this
.
tlsConfiguration
.
setHostnameVerifier
(
null
);
this
.
tlsConfiguration
.
setTrustManagers
(
tmf
.
getTrustManagers
());
if
(
this
.
preferences
.
contains
(
"androidblacklistsecuresocketprotocols"
))
{
this
.
tlsConfiguration
.
setBlacklistedProtocols
(
this
.
preferences
.
getString
(
"androidblacklistsecuresocketprotocols"
,
""
).
split
(
","
)
);
}
}
catch
(
Exception
e
)
{
Log
.
e
(
TAG
,
"An error occured while loading system's CA certificates"
,
e
);
}
}
@Override
public
boolean
execute
(
String
action
,
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
if
(
action
==
null
)
{
return
false
;
}
if
(
"setServerTrustMode"
.
equals
(
action
))
{
return
this
.
setServerTrustMode
(
args
,
callbackContext
);
}
else
if
(
"setClientAuthMode"
.
equals
(
action
))
{
return
this
.
setClientAuthMode
(
args
,
callbackContext
);
}
else
if
(
"abort"
.
equals
(
action
))
{
return
this
.
abort
(
args
,
callbackContext
);
}
if
(!
isNetworkAvailable
())
{
CordovaHttpResponse
response
=
new
CordovaHttpResponse
();
response
.
setStatus
(-
6
);
response
.
setErrorMessage
(
"No network connection available"
);
callbackContext
.
error
(
response
.
toJSON
());
return
true
;
}
if
(
"get"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithoutData
(
action
,
args
,
callbackContext
);
}
else
if
(
"head"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithoutData
(
action
,
args
,
callbackContext
);
}
else
if
(
"delete"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithoutData
(
action
,
args
,
callbackContext
);
}
else
if
(
"options"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithoutData
(
action
,
args
,
callbackContext
);
}
else
if
(
"post"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithData
(
action
,
args
,
callbackContext
);
}
else
if
(
"put"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithData
(
action
,
args
,
callbackContext
);
}
else
if
(
"patch"
.
equals
(
action
))
{
return
this
.
executeHttpRequestWithData
(
action
,
args
,
callbackContext
);
}
else
if
(
"uploadFiles"
.
equals
(
action
))
{
return
this
.
uploadFiles
(
args
,
callbackContext
);
}
else
if
(
"downloadFile"
.
equals
(
action
))
{
return
this
.
downloadFile
(
args
,
callbackContext
);
}
else
{
return
false
;
}
}
private
boolean
executeHttpRequestWithoutData
(
final
String
method
,
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
String
url
=
args
.
getString
(
0
);
JSONObject
headers
=
args
.
getJSONObject
(
1
);
int
connectTimeout
=
args
.
getInt
(
2
)
*
1000
;
int
readTimeout
=
args
.
getInt
(
3
)
*
1000
;
boolean
followRedirect
=
args
.
getBoolean
(
4
);
String
responseType
=
args
.
getString
(
5
);
Integer
reqId
=
args
.
getInt
(
6
);
CordovaObservableCallbackContext
observableCallbackContext
=
new
CordovaObservableCallbackContext
(
callbackContext
,
reqId
);
CordovaHttpOperation
request
=
new
CordovaHttpOperation
(
method
.
toUpperCase
(),
url
,
headers
,
connectTimeout
,
readTimeout
,
followRedirect
,
responseType
,
this
.
tlsConfiguration
,
observableCallbackContext
);
startRequest
(
reqId
,
observableCallbackContext
,
request
);
return
true
;
}
private
boolean
executeHttpRequestWithData
(
final
String
method
,
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
String
url
=
args
.
getString
(
0
);
Object
data
=
args
.
get
(
1
);
String
serializer
=
args
.
getString
(
2
);
JSONObject
headers
=
args
.
getJSONObject
(
3
);
int
connectTimeout
=
args
.
getInt
(
4
)
*
1000
;
int
readTimeout
=
args
.
getInt
(
5
)
*
1000
;
boolean
followRedirect
=
args
.
getBoolean
(
6
);
String
responseType
=
args
.
getString
(
7
);
Integer
reqId
=
args
.
getInt
(
8
);
CordovaObservableCallbackContext
observableCallbackContext
=
new
CordovaObservableCallbackContext
(
callbackContext
,
reqId
);
CordovaHttpOperation
request
=
new
CordovaHttpOperation
(
method
.
toUpperCase
(),
url
,
serializer
,
data
,
headers
,
connectTimeout
,
readTimeout
,
followRedirect
,
responseType
,
this
.
tlsConfiguration
,
observableCallbackContext
);
startRequest
(
reqId
,
observableCallbackContext
,
request
);
return
true
;
}
private
boolean
uploadFiles
(
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
String
url
=
args
.
getString
(
0
);
JSONObject
headers
=
args
.
getJSONObject
(
1
);
JSONArray
filePaths
=
args
.
getJSONArray
(
2
);
JSONArray
uploadNames
=
args
.
getJSONArray
(
3
);
int
connectTimeout
=
args
.
getInt
(
4
)
*
1000
;
int
readTimeout
=
args
.
getInt
(
5
)
*
1000
;
boolean
followRedirect
=
args
.
getBoolean
(
6
);
String
responseType
=
args
.
getString
(
7
);
Integer
reqId
=
args
.
getInt
(
8
);
CordovaObservableCallbackContext
observableCallbackContext
=
new
CordovaObservableCallbackContext
(
callbackContext
,
reqId
);
CordovaHttpUpload
upload
=
new
CordovaHttpUpload
(
url
,
headers
,
filePaths
,
uploadNames
,
connectTimeout
,
readTimeout
,
followRedirect
,
responseType
,
this
.
tlsConfiguration
,
this
.
cordova
.
getActivity
().
getApplicationContext
(),
observableCallbackContext
);
startRequest
(
reqId
,
observableCallbackContext
,
upload
);
return
true
;
}
private
boolean
downloadFile
(
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
String
url
=
args
.
getString
(
0
);
JSONObject
headers
=
args
.
getJSONObject
(
1
);
String
filePath
=
args
.
getString
(
2
);
int
connectTimeout
=
args
.
getInt
(
3
)
*
1000
;
int
readTimeout
=
args
.
getInt
(
4
)
*
1000
;
boolean
followRedirect
=
args
.
getBoolean
(
5
);
Integer
reqId
=
args
.
getInt
(
6
);
CordovaObservableCallbackContext
observableCallbackContext
=
new
CordovaObservableCallbackContext
(
callbackContext
,
reqId
);
CordovaHttpDownload
download
=
new
CordovaHttpDownload
(
url
,
headers
,
filePath
,
connectTimeout
,
readTimeout
,
followRedirect
,
this
.
tlsConfiguration
,
observableCallbackContext
);
startRequest
(
reqId
,
observableCallbackContext
,
download
);
return
true
;
}
private
void
startRequest
(
Integer
reqId
,
CordovaObservableCallbackContext
observableCallbackContext
,
CordovaHttpBase
request
)
{
synchronized
(
reqMapLock
)
{
observableCallbackContext
.
setObserver
(
this
);
Future
<?>
task
=
cordova
.
getThreadPool
().
submit
(
request
);
this
.
addReq
(
reqId
,
task
,
observableCallbackContext
);
}
}
private
boolean
setServerTrustMode
(
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
CordovaServerTrust
runnable
=
new
CordovaServerTrust
(
args
.
getString
(
0
),
this
.
cordova
.
getActivity
(),
this
.
tlsConfiguration
,
callbackContext
);
cordova
.
getThreadPool
().
execute
(
runnable
);
return
true
;
}
private
boolean
setClientAuthMode
(
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
byte
[]
pkcs
=
args
.
isNull
(
2
)
?
null
:
Base64
.
decode
(
args
.
getString
(
2
),
Base64
.
DEFAULT
);
CordovaClientAuth
runnable
=
new
CordovaClientAuth
(
args
.
getString
(
0
),
args
.
isNull
(
1
)
?
null
:
args
.
getString
(
1
),
pkcs
,
args
.
getString
(
3
),
this
.
cordova
.
getActivity
(),
this
.
cordova
.
getActivity
().
getApplicationContext
(),
this
.
tlsConfiguration
,
callbackContext
);
cordova
.
getThreadPool
().
execute
(
runnable
);
return
true
;
}
private
boolean
abort
(
final
JSONArray
args
,
final
CallbackContext
callbackContext
)
throws
JSONException
{
int
reqId
=
args
.
getInt
(
0
);
boolean
result
=
false
;
// NOTE no synchronized (reqMapLock), since even if the req was already removed from reqMap,
// the worst that would happen calling task.cancel(true) is a result of false
// (i.e. same result as locking & not finding the req in reqMap)
Future
<?>
task
=
this
.
reqMap
.
get
(
reqId
);
if
(
task
!=
null
&&
!
task
.
isDone
())
{
result
=
task
.
cancel
(
true
);
}
callbackContext
.
success
(
new
JSONObject
().
put
(
"aborted"
,
result
));
return
true
;
}
private
void
addReq
(
final
Integer
reqId
,
final
Future
<?>
task
,
final
CordovaObservableCallbackContext
observableCallbackContext
)
{
synchronized
(
reqMapLock
)
{
if
(!
task
.
isDone
()){
this
.
reqMap
.
put
(
reqId
,
task
);
}
}
}
private
void
removeReq
(
final
Integer
reqId
)
{
synchronized
(
reqMapLock
)
{
this
.
reqMap
.
remove
(
reqId
);
}
}
@Override
public
void
update
(
Observable
o
,
Object
arg
)
{
synchronized
(
reqMapLock
)
{
CordovaObservableCallbackContext
c
=
(
CordovaObservableCallbackContext
)
arg
;
if
(
c
.
getCallbackContext
().
isFinished
())
{
removeReq
(
c
.
getRequestId
());
}
}
}
private
boolean
isNetworkAvailable
()
{
ConnectivityManager
connectivityManager
=
(
ConnectivityManager
)
cordova
.
getContext
().
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
);
NetworkInfo
activeNetworkInfo
=
connectivityManager
.
getActiveNetworkInfo
();
return
activeNetworkInfo
!=
null
&&
activeNetworkInfo
.
isConnected
();
}
}
src/android/com/silkimen/cordovahttp/CordovaHttpResponse.java
0 → 100644
View file @
09c88efe
package
com.silkimen.cordovahttp
;
import
java.nio.ByteBuffer
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
android.util.Base64
;
class
CordovaHttpResponse
{
private
int
status
;
private
String
url
;
private
Map
<
String
,
List
<
String
>>
headers
;
private
String
body
;
private
byte
[]
rawData
;
private
JSONObject
fileEntry
;
private
boolean
hasFailed
;
private
boolean
isFileOperation
;
private
boolean
isRawResponse
;
private
String
error
;
public
void
setStatus
(
int
status
)
{
this
.
status
=
status
;
}
public
void
setUrl
(
String
url
)
{
this
.
url
=
url
;
}
public
void
setHeaders
(
Map
<
String
,
List
<
String
>>
headers
)
{
this
.
headers
=
headers
;
}
public
void
setBody
(
String
body
)
{
this
.
body
=
body
;
}
public
void
setData
(
byte
[]
rawData
)
{
this
.
isRawResponse
=
true
;
this
.
rawData
=
rawData
;
}
public
void
setFileEntry
(
JSONObject
entry
)
{
this
.
isFileOperation
=
true
;
this
.
fileEntry
=
entry
;
}
public
void
setErrorMessage
(
String
message
)
{
this
.
hasFailed
=
true
;
this
.
error
=
message
;
}
public
boolean
hasFailed
()
{
return
this
.
hasFailed
;
}
public
JSONObject
toJSON
()
throws
JSONException
{
JSONObject
json
=
new
JSONObject
();
json
.
put
(
"status"
,
this
.
status
);
json
.
put
(
"url"
,
this
.
url
);
if
(
this
.
headers
!=
null
&&
!
this
.
headers
.
isEmpty
())
{
json
.
put
(
"headers"
,
new
JSONObject
(
getFilteredHeaders
()));
}
if
(
this
.
hasFailed
)
{
json
.
put
(
"error"
,
this
.
error
);
}
else
if
(
this
.
isFileOperation
)
{
json
.
put
(
"file"
,
this
.
fileEntry
);
}
else
if
(
this
.
isRawResponse
)
{
json
.
put
(
"data"
,
Base64
.
encodeToString
(
this
.
rawData
,
Base64
.
DEFAULT
));
}
else
{
json
.
put
(
"data"
,
this
.
body
);
}
return
json
;
}
private
Map
<
String
,
String
>
getFilteredHeaders
()
throws
JSONException
{
Map
<
String
,
String
>
filteredHeaders
=
new
HashMap
<
String
,
String
>();
for
(
Map
.
Entry
<
String
,
List
<
String
>>
entry
:
this
.
headers
.
entrySet
())
{
String
key
=
entry
.
getKey
();
List
<
String
>
value
=
entry
.
getValue
();
if
((
key
!=
null
)
&&
(!
value
.
isEmpty
()))
{
filteredHeaders
.
put
(
key
.
toLowerCase
(),
TextUtils
.
join
(
", "
,
value
));
}
}
return
filteredHeaders
;
}
}
src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java
0 → 100644
View file @
09c88efe
package
com.silkimen.cordovahttp
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.provider.OpenableColumns
;
import
android.webkit.MimeTypeMap
;
import
com.silkimen.http.HttpRequest
;
import
com.silkimen.http.TLSConfiguration
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.InputStream
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
javax.net.ssl.HostnameVerifier
;
import
javax.net.ssl.SSLSocketFactory
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
class
CordovaHttpUpload
extends
CordovaHttpBase
{
private
JSONArray
filePaths
;
private
JSONArray
uploadNames
;
private
Context
applicationContext
;
public
CordovaHttpUpload
(
String
url
,
JSONObject
headers
,
JSONArray
filePaths
,
JSONArray
uploadNames
,
int
connectTimeout
,
int
readTimeout
,
boolean
followRedirects
,
String
responseType
,
TLSConfiguration
tlsConfiguration
,
Context
applicationContext
,
CordovaObservableCallbackContext
callbackContext
)
{
super
(
"POST"
,
url
,
headers
,
connectTimeout
,
readTimeout
,
followRedirects
,
responseType
,
tlsConfiguration
,
callbackContext
);
this
.
filePaths
=
filePaths
;
this
.
uploadNames
=
uploadNames
;
this
.
applicationContext
=
applicationContext
;
}
@Override
protected
void
sendBody
(
HttpRequest
request
)
throws
JSONException
,
URISyntaxException
,
FileNotFoundException
{
for
(
int
i
=
0
;
i
<
this
.
filePaths
.
length
();
++
i
)
{
String
uploadName
=
this
.
uploadNames
.
getString
(
i
);
String
filePath
=
this
.
filePaths
.
getString
(
i
);
Uri
fileUri
=
Uri
.
parse
(
filePath
);
// File Scheme
if
(
ContentResolver
.
SCHEME_FILE
.
equals
(
fileUri
.
getScheme
()))
{
File
file
=
new
File
(
new
URI
(
filePath
));
String
fileName
=
file
.
getName
().
trim
();
String
mimeType
=
this
.
getMimeTypeFromFileName
(
fileName
);
request
.
part
(
uploadName
,
fileName
,
mimeType
,
file
);
}
// Content Scheme
if
(
ContentResolver
.
SCHEME_CONTENT
.
equals
(
fileUri
.
getScheme
()))
{
InputStream
inputStream
=
this
.
applicationContext
.
getContentResolver
().
openInputStream
(
fileUri
);
String
fileName
=
this
.
getFileNameFromContentScheme
(
fileUri
,
this
.
applicationContext
).
trim
();
String
mimeType
=
this
.
getMimeTypeFromFileName
(
fileName
);
request
.
part
(
uploadName
,
fileName
,
mimeType
,
inputStream
);
}
}
}
private
String
getFileNameFromContentScheme
(
Uri
contentSchemeUri
,
Context
applicationContext
)
{
Cursor
returnCursor
=
applicationContext
.
getContentResolver
().
query
(
contentSchemeUri
,
null
,
null
,
null
,
null
);
if
(
returnCursor
==
null
||
!
returnCursor
.
moveToFirst
())
{
return
null
;
}
int
nameIndex
=
returnCursor
.
getColumnIndex
(
OpenableColumns
.
DISPLAY_NAME
);
String
fileName
=
returnCursor
.
getString
(
nameIndex
);
returnCursor
.
close
();
return
fileName
;
}
private
String
getMimeTypeFromFileName
(
String
fileName
)
{
if
(
fileName
==
null
||
!
fileName
.
contains
(
"."
))
{
return
null
;
}
MimeTypeMap
mimeTypeMap
=
MimeTypeMap
.
getSingleton
();
int
extIndex
=
fileName
.
lastIndexOf
(
'.'
)
+
1
;
String
extension
=
fileName
.
substring
(
extIndex
).
toLowerCase
();
return
mimeTypeMap
.
getMimeTypeFromExtension
(
extension
);
}
}
src/android/com/silkimen/cordovahttp/CordovaObservableCallbackContext.java
0 → 100644
View file @
09c88efe
package
com.silkimen.cordovahttp
;
import
org.apache.cordova.CallbackContext
;
import
org.json.JSONObject
;
import
java.util.Observer
;
public
class
CordovaObservableCallbackContext
{
private
CallbackContext
callbackContext
;
private
Integer
requestId
;
private
Observer
observer
;
public
CordovaObservableCallbackContext
(
CallbackContext
callbackContext
,
Integer
requestId
)
{
this
.
callbackContext
=
callbackContext
;
this
.
requestId
=
requestId
;
}
public
void
success
(
JSONObject
message
)
{
this
.
callbackContext
.
success
(
message
);
this
.
notifyObserver
();
}
public
void
error
(
JSONObject
message
)
{
this
.
callbackContext
.
error
(
message
);
this
.
notifyObserver
();
}
public
Integer
getRequestId
()
{
return
this
.
requestId
;
}
public
CallbackContext
getCallbackContext
()
{
return
callbackContext
;
}
public
Observer
getObserver
()
{
return
observer
;
}
protected
void
notifyObserver
()
{
if
(
this
.
observer
!=
null
){
this
.
observer
.
update
(
null
,
this
);
}
}
/**
* Set an observer that is notified, when {@link #success(JSONObject)}
* or {@link #error(JSONObject)} are called.
*
* NOTE the observer is notified with
* <pre>observer.update(null, cordovaObservableCallbackContext)</pre>
* @param observer
*/
public
void
setObserver
(
Observer
observer
)
{
this
.
observer
=
observer
;
}
}
src/android/com/silkimen/cordovahttp/CordovaServerTrust.java
0 → 100644
View file @
09c88efe
package
com.silkimen.cordovahttp
;
import
java.io.IOException
;
import
java.security.GeneralSecurityException
;
import
java.security.KeyStore
;
import
java.security.cert.CertificateFactory
;
import
java.security.cert.X509Certificate
;
import
com.silkimen.http.TLSConfiguration
;
import
org.apache.cordova.CallbackContext
;
import
android.app.Activity
;
import
android.util.Log
;
import
android.content.res.AssetManager
;
import
javax.net.ssl.HostnameVerifier
;
import
javax.net.ssl.SSLSession
;
import
javax.net.ssl.TrustManager
;
import
javax.net.ssl.TrustManagerFactory
;
import
javax.net.ssl.X509TrustManager
;
class
CordovaServerTrust
implements
Runnable
{
private
static
final
String
TAG
=
"Cordova-Plugin-HTTP"
;
private
final
TrustManager
[]
noOpTrustManagers
;
private
String
mode
;
private
Activity
activity
;
private
TLSConfiguration
tlsConfiguration
;
private
CallbackContext
callbackContext
;
public
CordovaServerTrust
(
final
String
mode
,
final
Activity
activity
,
final
TLSConfiguration
configContainer
,
final
CallbackContext
callbackContext
)
{
this
.
mode
=
mode
;
this
.
activity
=
activity
;
this
.
tlsConfiguration
=
configContainer
;
this
.
callbackContext
=
callbackContext
;
this
.
noOpTrustManagers
=
new
TrustManager
[]
{
new
X509TrustManager
()
{
public
X509Certificate
[]
getAcceptedIssuers
()
{
return
new
X509Certificate
[
0
];
}
public
void
checkClientTrusted
(
X509Certificate
[]
chain
,
String
authType
)
{
// intentionally left blank
}
public
void
checkServerTrusted
(
X509Certificate
[]
chain
,
String
authType
)
{
// intentionally left blank
}
}
};
}
@Override
public
void
run
()
{
try
{
if
(
"legacy"
.
equals
(
this
.
mode
))
{
this
.
tlsConfiguration
.
setHostnameVerifier
(
null
);
this
.
tlsConfiguration
.
setTrustManagers
(
null
);
}
else
if
(
"nocheck"
.
equals
(
this
.
mode
))
{
this
.
tlsConfiguration
.
setHostnameVerifier
(
null
);
this
.
tlsConfiguration
.
setTrustManagers
(
this
.
noOpTrustManagers
);
}
else
if
(
"pinned"
.
equals
(
this
.
mode
))
{
this
.
tlsConfiguration
.
setHostnameVerifier
(
null
);
this
.
tlsConfiguration
.
setTrustManagers
(
this
.
getTrustManagers
(
this
.
getCertsFromBundle
(
"www/certificates"
)));
}
else
{
this
.
tlsConfiguration
.
setHostnameVerifier
(
null
);
this
.
tlsConfiguration
.
setTrustManagers
(
this
.
getTrustManagers
(
this
.
getCertsFromKeyStore
(
"AndroidCAStore"
)));
}
callbackContext
.
success
();
}
catch
(
Exception
e
)
{
Log
.
e
(
TAG
,
"An error occured while configuring SSL cert mode"
,
e
);
callbackContext
.
error
(
"An error occured while configuring SSL cert mode"
);
}
}
private
TrustManager
[]
getTrustManagers
(
KeyStore
store
)
throws
GeneralSecurityException
{
String
tmfAlgorithm
=
TrustManagerFactory
.
getDefaultAlgorithm
();
TrustManagerFactory
tmf
=
TrustManagerFactory
.
getInstance
(
tmfAlgorithm
);
tmf
.
init
(
store
);
return
tmf
.
getTrustManagers
();
}
private
KeyStore
getCertsFromBundle
(
String
path
)
throws
GeneralSecurityException
,
IOException
{
AssetManager
assetManager
=
this
.
activity
.
getAssets
();
String
[]
files
=
assetManager
.
list
(
path
);
CertificateFactory
cf
=
CertificateFactory
.
getInstance
(
"X.509"
);
String
keyStoreType
=
KeyStore
.
getDefaultType
();
KeyStore
keyStore
=
KeyStore
.
getInstance
(
keyStoreType
);
keyStore
.
load
(
null
,
null
);
for
(
int
i
=
0
;
i
<
files
.
length
;
i
++)
{
int
index
=
files
[
i
].
lastIndexOf
(
'.'
);
if
(
index
==
-
1
||
!
files
[
i
].
substring
(
index
).
equals
(
".cer"
))
{
continue
;
}
keyStore
.
setCertificateEntry
(
"CA"
+
i
,
cf
.
generateCertificate
(
assetManager
.
open
(
path
+
"/"
+
files
[
i
])));
}
return
keyStore
;
}
private
KeyStore
getCertsFromKeyStore
(
String
storeType
)
throws
GeneralSecurityException
,
IOException
{
KeyStore
store
=
KeyStore
.
getInstance
(
storeType
);
store
.
load
(
null
);
return
store
;
}
}
src/android/com/silkimen/http/HttpBodyDecoder.java
0 → 100644
View file @
09c88efe
package
com.silkimen.http
;
import
java.nio.ByteBuffer
;
import
java.nio.charset.CharacterCodingException
;
import
java.nio.charset.Charset
;
import
java.nio.charset.CharsetDecoder
;
import
java.nio.charset.CodingErrorAction
;
import
java.nio.charset.MalformedInputException
;
public
class
HttpBodyDecoder
{
private
static
final
String
[]
ACCEPTED_CHARSETS
=
new
String
[]
{
"UTF-8"
,
"ISO-8859-1"
};
public
static
String
decodeBody
(
byte
[]
body
,
String
charsetName
)
throws
CharacterCodingException
,
MalformedInputException
{
return
decodeBody
(
ByteBuffer
.
wrap
(
body
),
charsetName
);
}
public
static
String
decodeBody
(
ByteBuffer
body
,
String
charsetName
)
throws
CharacterCodingException
,
MalformedInputException
{
if
(
charsetName
==
null
)
{
return
tryDecodeByteBuffer
(
body
);
}
else
{
return
decodeByteBuffer
(
body
,
charsetName
);
}
}
private
static
String
tryDecodeByteBuffer
(
ByteBuffer
buffer
)
throws
CharacterCodingException
,
MalformedInputException
{
for
(
int
i
=
0
;
i
<
ACCEPTED_CHARSETS
.
length
-
1
;
i
++)
{
try
{
return
decodeByteBuffer
(
buffer
,
ACCEPTED_CHARSETS
[
i
]);
}
catch
(
MalformedInputException
e
)
{
continue
;
}
catch
(
CharacterCodingException
e
)
{
continue
;
}
}
return
decodeBody
(
buffer
,
ACCEPTED_CHARSETS
[
ACCEPTED_CHARSETS
.
length
-
1
]);
}
private
static
String
decodeByteBuffer
(
ByteBuffer
buffer
,
String
charsetName
)
throws
CharacterCodingException
,
MalformedInputException
{
return
createCharsetDecoder
(
charsetName
).
decode
(
buffer
).
toString
();
}
private
static
CharsetDecoder
createCharsetDecoder
(
String
charsetName
)
{
return
Charset
.
forName
(
charsetName
).
newDecoder
().
onMalformedInput
(
CodingErrorAction
.
REPORT
)
.
onUnmappableCharacter
(
CodingErrorAction
.
REPORT
);
}
}
src/android/com/silkimen/http/HttpRequest.java
0 → 100644
View file @
09c88efe
This diff is collapsed.
Click to expand it.
src/android/com/silkimen/http/JsonUtils.java
0 → 100644
View file @
09c88efe
package
com.silkimen.http
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
public
class
JsonUtils
{
public
static
HashMap
<
String
,
String
>
getStringMap
(
JSONObject
object
)
throws
JSONException
{
HashMap
<
String
,
String
>
map
=
new
HashMap
<
String
,
String
>();
if
(
object
==
null
)
{
return
map
;
}
Iterator
<?>
i
=
object
.
keys
();
while
(
i
.
hasNext
())
{
String
key
=
(
String
)
i
.
next
();
map
.
put
(
key
,
object
.
getString
(
key
));
}
return
map
;
}
public
static
HashMap
<
String
,
Object
>
getObjectMap
(
JSONObject
object
)
throws
JSONException
{
HashMap
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
if
(
object
==
null
)
{
return
map
;
}
Iterator
<?>
i
=
object
.
keys
();
while
(
i
.
hasNext
())
{
String
key
=
(
String
)
i
.
next
();
Object
value
=
object
.
get
(
key
);
if
(
value
instanceof
JSONArray
)
{
map
.
put
(
key
,
getObjectList
((
JSONArray
)
value
));
}
else
{
map
.
put
(
key
,
object
.
get
(
key
));
}
}
return
map
;
}
public
static
ArrayList
<
Object
>
getObjectList
(
JSONArray
array
)
throws
JSONException
{
ArrayList
<
Object
>
list
=
new
ArrayList
<
Object
>();
for
(
int
i
=
0
;
i
<
array
.
length
();
i
++)
{
list
.
add
(
array
.
get
(
i
));
}
return
list
;
}
}
src/android/com/silkimen/http/KeyChainKeyManager.java
0 → 100644
View file @
09c88efe
package
com.silkimen.http
;
import
android.content.Context
;
import
android.security.KeyChain
;
import
java.net.Socket
;
import
java.security.Principal
;
import
java.security.PrivateKey
;
import
java.security.cert.CertificateException
;
import
java.security.cert.X509Certificate
;
import
javax.net.ssl.X509ExtendedKeyManager
;
public
class
KeyChainKeyManager
extends
X509ExtendedKeyManager
{
private
final
String
alias
;
private
final
X509Certificate
[]
chain
;
private
final
PrivateKey
key
;
public
KeyChainKeyManager
(
String
alias
,
PrivateKey
key
,
X509Certificate
[]
chain
)
{
this
.
alias
=
alias
;
this
.
key
=
key
;
this
.
chain
=
chain
;
}
@Override
public
String
chooseClientAlias
(
String
[]
keyTypes
,
Principal
[]
issuers
,
Socket
socket
)
{
return
this
.
alias
;
}
@Override
public
X509Certificate
[]
getCertificateChain
(
String
alias
)
{
return
chain
;
}
@Override
public
PrivateKey
getPrivateKey
(
String
alias
)
{
return
key
;
}
@Override
public
final
String
chooseServerAlias
(
String
keyType
,
Principal
[]
issuers
,
Socket
socket
)
{
// not a client SSLSocket callback
throw
new
UnsupportedOperationException
();
}
@Override
public
final
String
[]
getClientAliases
(
String
keyType
,
Principal
[]
issuers
)
{
// not a client SSLSocket callback
throw
new
UnsupportedOperationException
();
}
@Override
public
final
String
[]
getServerAliases
(
String
keyType
,
Principal
[]
issuers
)
{
// not a client SSLSocket callback
throw
new
UnsupportedOperationException
();
}
}
src/android/com/silkimen/http/TLSConfiguration.java
0 → 100644
View file @
09c88efe
package
com.silkimen.http
;
import
java.io.IOException
;
import
java.security.GeneralSecurityException
;
import
java.security.SecureRandom
;
import
javax.net.ssl.HostnameVerifier
;
import
javax.net.ssl.KeyManager
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.net.ssl.TrustManager
;
import
com.silkimen.http.TLSSocketFactory
;
public
class
TLSConfiguration
{
private
TrustManager
[]
trustManagers
=
null
;
private
KeyManager
[]
keyManagers
=
null
;
private
HostnameVerifier
hostnameVerifier
=
null
;
private
String
[]
blacklistedProtocols
=
{};
private
SSLSocketFactory
socketFactory
;
public
void
setHostnameVerifier
(
HostnameVerifier
hostnameVerifier
)
{
this
.
hostnameVerifier
=
hostnameVerifier
;
}
public
void
setKeyManagers
(
KeyManager
[]
keyManagers
)
{
this
.
keyManagers
=
keyManagers
;
this
.
socketFactory
=
null
;
}
public
void
setTrustManagers
(
TrustManager
[]
trustManagers
)
{
this
.
trustManagers
=
trustManagers
;
this
.
socketFactory
=
null
;
}
public
void
setBlacklistedProtocols
(
String
[]
protocols
)
{
this
.
blacklistedProtocols
=
protocols
;
this
.
socketFactory
=
null
;
}
public
HostnameVerifier
getHostnameVerifier
()
{
return
this
.
hostnameVerifier
;
}
public
SSLSocketFactory
getTLSSocketFactory
()
throws
IOException
{
if
(
this
.
socketFactory
!=
null
)
{
return
this
.
socketFactory
;
}
try
{
SSLContext
context
=
SSLContext
.
getInstance
(
"TLSv1.2"
);
context
.
init
(
this
.
keyManagers
,
this
.
trustManagers
,
new
SecureRandom
());
this
.
socketFactory
=
new
TLSSocketFactory
(
context
,
this
.
blacklistedProtocols
);
return
this
.
socketFactory
;
}
catch
(
GeneralSecurityException
e
)
{
IOException
ioException
=
new
IOException
(
"Security exception occured while configuring TLS context"
);
ioException
.
initCause
(
e
);
throw
ioException
;
}
}
}
src/android/com/silkimen/http/TLSSocketFactory.java
0 → 100644
View file @
09c88efe
package
com.silkimen.http
;
import
java.io.IOException
;
import
java.net.InetAddress
;
import
java.net.Socket
;
import
java.net.UnknownHostException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLSocket
;
import
javax.net.ssl.SSLSocketFactory
;
public
class
TLSSocketFactory
extends
SSLSocketFactory
{
private
SSLSocketFactory
delegate
;
private
List
<
String
>
blacklistedProtocols
;
public
TLSSocketFactory
(
SSLContext
context
,
String
[]
blacklistedProtocols
)
{
this
.
delegate
=
context
.
getSocketFactory
();
this
.
blacklistedProtocols
=
new
ArrayList
();
for
(
int
i
=
0
;
i
<
blacklistedProtocols
.
length
;
++
i
)
{
this
.
blacklistedProtocols
.
add
(
blacklistedProtocols
[
i
].
trim
());
}
}
@Override
public
String
[]
getDefaultCipherSuites
()
{
return
delegate
.
getDefaultCipherSuites
();
}
@Override
public
String
[]
getSupportedCipherSuites
()
{
return
delegate
.
getSupportedCipherSuites
();
}
@Override
public
Socket
createSocket
(
Socket
socket
,
String
host
,
int
port
,
boolean
autoClose
)
throws
IOException
{
return
enableTLSOnSocket
(
delegate
.
createSocket
(
socket
,
host
,
port
,
autoClose
));
}
@Override
public
Socket
createSocket
(
String
host
,
int
port
)
throws
IOException
,
UnknownHostException
{
return
enableTLSOnSocket
(
delegate
.
createSocket
(
host
,
port
));
}
@Override
public
Socket
createSocket
(
String
host
,
int
port
,
InetAddress
localHost
,
int
localPort
)
throws
IOException
,
UnknownHostException
{
return
enableTLSOnSocket
(
delegate
.
createSocket
(
host
,
port
,
localHost
,
localPort
));
}
@Override
public
Socket
createSocket
(
InetAddress
host
,
int
port
)
throws
IOException
{
return
enableTLSOnSocket
(
delegate
.
createSocket
(
host
,
port
));
}
@Override
public
Socket
createSocket
(
InetAddress
address
,
int
port
,
InetAddress
localAddress
,
int
localPort
)
throws
IOException
{
return
enableTLSOnSocket
(
delegate
.
createSocket
(
address
,
port
,
localAddress
,
localPort
));
}
private
Socket
enableTLSOnSocket
(
Socket
socket
)
{
if
(
socket
==
null
||
!(
socket
instanceof
SSLSocket
))
{
return
socket
;
}
String
[]
supported
=
((
SSLSocket
)
socket
).
getSupportedProtocols
();
List
<
String
>
filtered
=
new
ArrayList
();
for
(
int
i
=
0
;
i
<
supported
.
length
;
++
i
)
{
if
(!
this
.
blacklistedProtocols
.
contains
(
supported
[
i
]))
{
filtered
.
add
(
supported
[
i
]);
}
}
((
SSLSocket
)
socket
).
setEnabledProtocols
(
filtered
.
toArray
(
new
String
[
0
]));
return
socket
;
}
}
src/browser/cordova-http-plugin.js
0 → 100644
View file @
09c88efe
var
pluginId
=
module
.
id
.
slice
(
0
,
module
.
id
.
lastIndexOf
(
'
.
'
));
var
cordovaProxy
=
require
(
'
cordova/exec/proxy
'
);
var
jsUtil
=
require
(
pluginId
+
'
.js-util
'
);
var
reqMap
=
{};
function
serializeJsonData
(
data
)
{
try
{
return
JSON
.
stringify
(
data
);
}
catch
(
err
)
{
return
null
;
}
}
function
serializePrimitive
(
key
,
value
)
{
if
(
value
===
null
||
value
===
undefined
)
{
return
encodeURIComponent
(
key
)
+
'
=
'
;
}
return
encodeURIComponent
(
key
)
+
'
=
'
+
encodeURIComponent
(
value
);
}
function
serializeArray
(
key
,
values
)
{
return
values
.
map
(
function
(
value
)
{
return
encodeURIComponent
(
key
)
+
'
[]=
'
+
encodeURIComponent
(
value
);
}).
join
(
'
&
'
);
}
function
serializeParams
(
params
)
{
if
(
params
===
null
)
return
''
;
return
Object
.
keys
(
params
).
map
(
function
(
key
)
{
if
(
jsUtil
.
getTypeOf
(
params
[
key
])
===
'
Array
'
)
{
return
serializeArray
(
key
,
params
[
key
]);
}
return
serializePrimitive
(
key
,
params
[
key
]);
}).
join
(
'
&
'
);
}
function
decodeB64
(
dataString
)
{
var
binaryString
=
atob
(
dataString
);
var
bytes
=
new
Uint8Array
(
binaryString
.
length
);
for
(
var
i
=
0
;
i
<
binaryString
.
length
;
++
i
)
{
bytes
[
i
]
=
binaryString
.
charCodeAt
(
i
);
}
return
bytes
.
buffer
;
}
function
processMultipartData
(
data
)
{
if
(
!
data
)
return
null
;
var
fd
=
new
FormData
();
for
(
var
i
=
0
;
i
<
data
.
buffers
.
length
;
++
i
)
{
var
buffer
=
data
.
buffers
[
i
];
var
name
=
data
.
names
[
i
];
var
fileName
=
data
.
fileNames
[
i
];
var
type
=
data
.
types
[
i
];
if
(
fileName
)
{
fd
.
append
(
name
,
new
Blob
([
decodeB64
(
buffer
)],
{
type
:
type
}),
fileName
);
}
else
{
// we assume it's plain text if no filename was given
fd
.
append
(
name
,
atob
(
buffer
));
}
}
return
fd
;
}
function
deserializeResponseHeaders
(
headers
)
{
var
headerMap
=
{};
var
arr
=
headers
.
trim
().
split
(
/
[\r\n]
+/
);
arr
.
forEach
(
function
(
line
)
{
var
parts
=
line
.
split
(
'
:
'
);
var
header
=
parts
.
shift
().
toLowerCase
();
var
value
=
parts
.
join
(
'
:
'
);
headerMap
[
header
]
=
value
;
});
return
headerMap
;
}
function
getResponseData
(
xhr
)
{
if
(
xhr
.
responseType
!==
'
text
'
||
jsUtil
.
getTypeOf
(
xhr
.
responseText
)
!==
'
String
'
)
{
return
xhr
.
response
;
}
return
xhr
.
responseText
;
}
function
createXhrSuccessObject
(
xhr
)
{
return
{
url
:
xhr
.
responseURL
,
status
:
xhr
.
status
,
data
:
getResponseData
(
xhr
),
headers
:
deserializeResponseHeaders
(
xhr
.
getAllResponseHeaders
())
};
}
function
createXhrFailureObject
(
xhr
)
{
var
obj
=
{};
obj
.
headers
=
xhr
.
getAllResponseHeaders
();
obj
.
error
=
getResponseData
(
xhr
);
obj
.
error
=
obj
.
error
||
'
advanced-http: please check browser console for error messages
'
;
if
(
xhr
.
responseURL
)
obj
.
url
=
xhr
.
responseURL
;
if
(
xhr
.
status
)
obj
.
status
=
xhr
.
status
;
return
obj
;
}
function
injectRequestIdHandler
(
reqId
,
cb
)
{
return
function
(
response
)
{
delete
reqMap
[
reqId
];
cb
(
response
);
}
}
function
getHeaderValue
(
headers
,
headerName
)
{
let
result
=
null
;
Object
.
keys
(
headers
).
forEach
(
function
(
key
)
{
if
(
key
.
toLowerCase
()
===
headerName
.
toLowerCase
())
{
result
=
headers
[
key
];
}
});
return
result
;
}
function
setDefaultContentType
(
headers
,
contentType
)
{
if
(
getHeaderValue
(
headers
,
'
Content-Type
'
)
===
null
)
{
headers
[
'
Content-Type
'
]
=
contentType
;
}
}
function
setHeaders
(
xhr
,
headers
)
{
Object
.
keys
(
headers
).
forEach
(
function
(
key
)
{
if
(
key
.
toLowerCase
()
===
'
cookie
'
)
return
;
xhr
.
setRequestHeader
(
key
,
headers
[
key
]);
});
}
function
sendRequest
(
method
,
withData
,
opts
,
success
,
failure
)
{
var
data
,
serializer
,
headers
,
readTimeout
,
followRedirect
,
responseType
,
reqId
;
var
url
=
opts
[
0
];
if
(
withData
)
{
data
=
opts
[
1
];
serializer
=
opts
[
2
];
headers
=
opts
[
3
];
// connect timeout not applied
// connectTimeout = opts[4];
readTimeout
=
opts
[
5
];
followRedirect
=
opts
[
6
];
responseType
=
opts
[
7
];
reqId
=
opts
[
8
];
}
else
{
headers
=
opts
[
1
];
// connect timeout not applied
// connectTimeout = opts[2];
readTimeout
=
opts
[
3
];
followRedirect
=
opts
[
4
];
responseType
=
opts
[
5
];
reqId
=
opts
[
6
];
}
var
onSuccess
=
injectRequestIdHandler
(
reqId
,
success
);
var
onFail
=
injectRequestIdHandler
(
reqId
,
failure
);
var
processedData
=
null
;
var
xhr
=
new
XMLHttpRequest
();
reqMap
[
reqId
]
=
xhr
;
xhr
.
open
(
method
,
url
);
if
(
headers
.
Cookie
&&
headers
.
Cookie
.
length
>
0
)
{
return
onFail
(
'
advanced-http: custom cookies not supported on browser platform
'
);
}
if
(
!
followRedirect
)
{
return
onFail
(
'
advanced-http: disabling follow redirect not supported on browser platform
'
);
}
switch
(
serializer
)
{
case
'
json
'
:
setDefaultContentType
(
headers
,
'
application/json; charset=utf8
'
);
processedData
=
serializeJsonData
(
data
);
if
(
processedData
===
null
)
{
return
onFail
(
'
advanced-http: failed serializing data
'
);
}
break
;
case
'
utf8
'
:
setDefaultContentType
(
headers
,
'
text/plain; charset=utf8
'
);
processedData
=
data
.
text
;
break
;
case
'
urlencoded
'
:
setDefaultContentType
(
headers
,
'
application/x-www-form-urlencoded
'
);
processedData
=
serializeParams
(
data
);
break
;
case
'
multipart
'
:
const
contentType
=
getHeaderValue
(
headers
,
'
Content-Type
'
);
// intentionally don't set a default content type
// it's set by the browser together with the content disposition string
if
(
contentType
)
{
headers
[
'
Content-Type
'
]
=
contentType
;
}
processedData
=
processMultipartData
(
data
);
break
;
case
'
raw
'
:
setDefaultContentType
(
headers
,
'
application/octet-stream
'
);
processedData
=
data
;
break
;
}
// requesting text instead of JSON because it's parsed in the response handler
xhr
.
responseType
=
responseType
===
'
json
'
?
'
text
'
:
responseType
;
// we can't set connect timeout and read timeout separately on browser platform
xhr
.
timeout
=
readTimeout
*
1000
;
try
{
setHeaders
(
xhr
,
headers
);
}
catch
(
error
)
{
return
onFail
({
status
:
-
1
,
error
:
error
,
url
:
url
,
headers
:
headers
});
}
xhr
.
onerror
=
function
()
{
return
onFail
(
createXhrFailureObject
(
xhr
));
};
xhr
.
onabort
=
function
()
{
return
onFail
({
status
:
-
8
,
error
:
'
Request was aborted
'
,
url
:
url
,
headers
:
{}
});
};
xhr
.
ontimeout
=
function
()
{
return
onFail
({
status
:
-
4
,
error
:
'
Request timed out
'
,
url
:
url
,
headers
:
{}
});
};
xhr
.
onload
=
function
()
{
if
(
xhr
.
readyState
!==
xhr
.
DONE
)
return
;
if
(
xhr
.
status
<
200
||
xhr
.
status
>
299
)
{
return
onFail
(
createXhrFailureObject
(
xhr
));
}
return
onSuccess
(
createXhrSuccessObject
(
xhr
));
};
xhr
.
send
(
processedData
);
}
function
abort
(
opts
,
success
,
failure
)
{
var
reqId
=
opts
[
0
];
var
result
=
false
;
var
xhr
=
reqMap
[
reqId
];
if
(
xhr
&&
xhr
.
readyState
!==
xhr
.
DONE
){
xhr
.
abort
();
result
=
true
;
}
success
({
aborted
:
result
});
}
var
browserInterface
=
{
get
:
function
(
success
,
failure
,
opts
)
{
return
sendRequest
(
'
get
'
,
false
,
opts
,
success
,
failure
);
},
head
:
function
(
success
,
failure
,
opts
)
{
return
sendRequest
(
'
head
'
,
false
,
opts
,
success
,
failure
);
},
delete
:
function
(
success
,
failure
,
opts
)
{
return
sendRequest
(
'
delete
'
,
false
,
opts
,
success
,
failure
);
},
post
:
function
(
success
,
failure
,
opts
)
{
return
sendRequest
(
'
post
'
,
true
,
opts
,
success
,
failure
);
},
put
:
function
(
success
,
failure
,
opts
)
{
return
sendRequest
(
'
put
'
,
true
,
opts
,
success
,
failure
);
},
patch
:
function
(
success
,
failure
,
opts
)
{
return
sendRequest
(
'
patch
'
,
true
,
opts
,
success
,
failure
);
},
abort
:
function
(
success
,
failure
,
opts
)
{
return
abort
(
opts
,
success
,
failure
);
},
uploadFile
:
function
(
success
,
failure
,
opts
)
{
return
failure
(
'
advanced-http: function "uploadFile" not supported on browser platform
'
);
},
uploadFiles
:
function
(
success
,
failure
,
opts
)
{
return
failure
(
'
advanced-http: function "uploadFiles" not supported on browser platform
'
);
},
downloadFile
:
function
(
success
,
failure
,
opts
)
{
return
failure
(
'
advanced-http: function "downloadFile" not supported on browser platform
'
);
},
setServerTrustMode
:
function
(
success
,
failure
,
opts
)
{
return
failure
(
'
advanced-http: function "setServerTrustMode" not supported on browser platform
'
);
},
setClientAuthMode
:
function
(
success
,
failure
,
opts
)
{
return
failure
(
'
advanced-http: function "setClientAuthMode" not supported on browser platform
'
);
}
};
module
.
exports
=
browserInterface
;
cordovaProxy
.
add
(
'
CordovaHttpPlugin
'
,
browserInterface
);
src/ios/BinaryRequestSerializer.h
0 → 100644
View file @
09c88efe
#import <Foundation/Foundation.h>
#import "SM_AFURLRequestSerialization.h"
@interface
BinaryRequestSerializer
:
SM_AFHTTPRequestSerializer
+
(
instancetype
)
serializer
;
@end
src/ios/BinaryRequestSerializer.m
0 → 100644
View file @
09c88efe
#import "BinaryRequestSerializer.h"
@implementation
BinaryRequestSerializer
+
(
instancetype
)
serializer
{
BinaryRequestSerializer
*
serializer
=
[[
self
alloc
]
init
];
return
serializer
;
}
#pragma mark - SM_AFURLRequestSerialization
-
(
NSURLRequest
*
)
requestBySerializingRequest
:(
NSURLRequest
*
)
request
withParameters
:(
id
)
parameters
error
:(
NSError
*
__autoreleasing
*
)
error
{
NSParameterAssert
(
request
);
if
([
self
.
HTTPMethodsEncodingParametersInURI
containsObject
:[[
request
HTTPMethod
]
uppercaseString
]])
{
return
[
super
requestBySerializingRequest
:
request
withParameters
:
parameters
error
:
error
];
}
NSMutableURLRequest
*
mutableRequest
=
[
request
mutableCopy
];
[
self
.
HTTPRequestHeaders
enumerateKeysAndObjectsUsingBlock
:
^
(
id
field
,
id
value
,
BOOL
*
__unused
stop
)
{
if
(
!
[
request
valueForHTTPHeaderField
:
field
])
{
[
mutableRequest
setValue
:
value
forHTTPHeaderField
:
field
];
}
}];
if
(
parameters
)
{
if
(
!
[
mutableRequest
valueForHTTPHeaderField
:
@"Content-Type"
])
{
[
mutableRequest
setValue
:
@"application/octet-stream"
forHTTPHeaderField
:
@"Content-Type"
];
}
[
mutableRequest
setHTTPBody
:
parameters
];
}
return
mutableRequest
;
}
#pragma mark - NSSecureCoding
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
decoder
{
self
=
[
super
initWithCoder
:
decoder
];
if
(
!
self
)
{
return
nil
;
}
return
self
;
}
@end
src/ios/BinaryResponseSerializer.h
0 → 100644
View file @
09c88efe
#import <Foundation/Foundation.h>
#import "SM_AFURLResponseSerialization.h"
@interface
BinaryResponseSerializer
:
SM_AFHTTPResponseSerializer
+
(
instancetype
)
serializer
;
@end
src/ios/BinaryResponseSerializer.m
0 → 100644
View file @
09c88efe
#import "BinaryResponseSerializer.h"
static
NSError
*
AFErrorWithUnderlyingError
(
NSError
*
error
,
NSError
*
underlyingError
)
{
if
(
!
error
)
{
return
underlyingError
;
}
if
(
!
underlyingError
||
error
.
userInfo
[
NSUnderlyingErrorKey
])
{
return
error
;
}
NSMutableDictionary
*
mutableUserInfo
=
[
error
.
userInfo
mutableCopy
];
mutableUserInfo
[
NSUnderlyingErrorKey
]
=
underlyingError
;
return
[[
NSError
alloc
]
initWithDomain
:
error
.
domain
code
:
error
.
code
userInfo
:
mutableUserInfo
];
}
static
BOOL
AFErrorOrUnderlyingErrorHasCodeInDomain
(
NSError
*
error
,
NSInteger
code
,
NSString
*
domain
)
{
if
([
error
.
domain
isEqualToString
:
domain
]
&&
error
.
code
==
code
)
{
return
YES
;
}
else
if
(
error
.
userInfo
[
NSUnderlyingErrorKey
])
{
return
AFErrorOrUnderlyingErrorHasCodeInDomain
(
error
.
userInfo
[
NSUnderlyingErrorKey
],
code
,
domain
);
}
return
NO
;
}
@implementation
BinaryResponseSerializer
+
(
instancetype
)
serializer
{
BinaryResponseSerializer
*
serializer
=
[[
self
alloc
]
init
];
return
serializer
;
}
-
(
instancetype
)
init
{
self
=
[
super
init
];
if
(
!
self
)
{
return
nil
;
}
self
.
acceptableContentTypes
=
nil
;
return
self
;
}
-
(
NSString
*
)
decodeResponseData
:(
NSData
*
)
rawResponseData
withEncoding
:(
CFStringEncoding
)
cfEncoding
{
NSStringEncoding
nsEncoding
;
NSString
*
decoded
=
nil
;
if
(
cfEncoding
!=
kCFStringEncodingInvalidId
)
{
nsEncoding
=
CFStringConvertEncodingToNSStringEncoding
(
cfEncoding
);
}
NSStringEncoding
supportedEncodings
[
6
]
=
{
NSUTF8StringEncoding
,
NSWindowsCP1252StringEncoding
,
NSISOLatin1StringEncoding
,
NSISOLatin2StringEncoding
,
NSASCIIStringEncoding
,
NSUnicodeStringEncoding
};
for
(
int
i
=
0
;
i
<
sizeof
(
supportedEncodings
)
/
sizeof
(
NSStringEncoding
)
&&
!
decoded
;
++
i
)
{
if
(
cfEncoding
==
kCFStringEncodingInvalidId
||
nsEncoding
==
supportedEncodings
[
i
])
{
decoded
=
[[
NSString
alloc
]
initWithData
:
rawResponseData
encoding
:
supportedEncodings
[
i
]];
}
}
return
decoded
;
}
-
(
CFStringEncoding
)
getEncoding
:(
NSURLResponse
*
)
response
{
CFStringEncoding
encoding
=
kCFStringEncodingInvalidId
;
if
(
response
.
textEncodingName
)
{
encoding
=
CFStringConvertIANACharSetNameToEncoding
((
CFStringRef
)
response
.
textEncodingName
);
}
return
encoding
;
}
#pragma mark -
-
(
BOOL
)
validateResponse
:(
NSHTTPURLResponse
*
)
response
data
:(
NSData
*
)
data
error
:(
NSError
*
__autoreleasing
*
)
error
{
if
(
response
&&
[
response
isKindOfClass
:[
NSHTTPURLResponse
class
]])
{
if
(
self
.
acceptableStatusCodes
&&
!
[
self
.
acceptableStatusCodes
containsIndex
:(
NSUInteger
)
response
.
statusCode
]
&&
[
response
URL
])
{
NSMutableDictionary
*
mutableUserInfo
=
[@{
NSLocalizedDescriptionKey:
[
NSString
stringWithFormat
:
NSLocalizedStringFromTable
(
@"Request failed: %@ (%ld)"
,
@"SM_AFNetworking"
,
nil
),
[
NSHTTPURLResponse
localizedStringForStatusCode
:
response
.
statusCode
],
(
long
)
response
.
statusCode
],
NSURLErrorFailingURLErrorKey:
[
response
URL
],
SM_AFNetworkingOperationFailingURLResponseErrorKey:
response
,
}
mutableCopy
];
if
(
data
)
{
mutableUserInfo
[
SM_AFNetworkingOperationFailingURLResponseDataErrorKey
]
=
data
;
// trying to decode error message in body
mutableUserInfo
[
SM_AFNetworkingOperationFailingURLResponseBodyErrorKey
]
=
[
self
decodeResponseData
:
data
withEncoding
:[
self
getEncoding
:
response
]];
}
if
(
error
)
{
*
error
=
[
NSError
errorWithDomain
:
SM_AFURLResponseSerializationErrorDomain
code
:
NSURLErrorBadServerResponse
userInfo
:
mutableUserInfo
];
}
return
NO
;
}
}
return
YES
;
}
#pragma mark - SM_AFURLResponseSerialization
-
(
id
)
responseObjectForResponse
:(
NSURLResponse
*
)
response
data
:(
NSData
*
)
data
error
:(
NSError
*
__autoreleasing
*
)
error
{
if
(
!
[
self
validateResponse
:(
NSHTTPURLResponse
*
)
response
data
:
data
error
:
error
])
{
if
(
!
error
||
AFErrorOrUnderlyingErrorHasCodeInDomain
(
*
error
,
NSURLErrorCannotDecodeContentData
,
SM_AFURLResponseSerializationErrorDomain
))
{
return
nil
;
}
}
return
[
data
base64EncodedStringWithOptions
:
0
];
}
@end
src/ios/CordovaHttpPlugin.h
0 → 100644
View file @
09c88efe
#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>
@interface
CordovaHttpPlugin
:
CDVPlugin
-
(
void
)
setServerTrustMode
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
setClientAuthMode
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
post
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
put
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
patch
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
get
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
delete
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
head
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
options
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
uploadFiles
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
downloadFile
:(
CDVInvokedUrlCommand
*
)
command
;
-
(
void
)
abort
:(
CDVInvokedUrlCommand
*
)
command
;
@end
src/ios/CordovaHttpPlugin.m
0 → 100644
View file @
09c88efe
This diff is collapsed.
Click to expand it.
src/ios/SDNetworkActivityIndicator/LICENSE
0 → 100644
View file @
09c88efe
Copyright (c) 2010 Olivier Poitrey <rs@dailymotion.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Prev
1
2
3
4
Next
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment