|  | @@ -24,13 +24,13 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 24 | 24 |    _readyState : number = UNSENT;
 | 
	
		
			
			| 25 | 25 |    _response : any = '';
 | 
	
		
			
			| 26 | 26 |    _responseText : any = '';
 | 
	
		
			
			| 27 |  | -  _responseHeaders : any = '';
 | 
	
		
			
			|  | 27 | +  _responseHeaders : any = {};
 | 
	
		
			
			| 28 | 28 |    _responseType : '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' = '';
 | 
	
		
			
			| 29 | 29 |    // TODO : not suppoted for now
 | 
	
		
			
			| 30 | 30 |    _responseURL : null = '';
 | 
	
		
			
			| 31 | 31 |    _responseXML : null = '';
 | 
	
		
			
			| 32 |  | -  _status : number;
 | 
	
		
			
			| 33 |  | -  _statusText : string;
 | 
	
		
			
			|  | 32 | +  _status : number = 0;
 | 
	
		
			
			|  | 33 | +  _statusText : string = '';
 | 
	
		
			
			| 34 | 34 |    _timeout : number = 0;
 | 
	
		
			
			| 35 | 35 |    _upload : XMLHttpRequestEventTarget;
 | 
	
		
			
			| 36 | 36 |    _sendFlag : boolean = false;
 | 
	
	
		
			
			|  | @@ -74,11 +74,21 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 74 | 74 |      this._headers = {}
 | 
	
		
			
			| 75 | 75 |    }
 | 
	
		
			
			| 76 | 76 |  
 | 
	
		
			
			| 77 |  | -  // XMLHttpRequest.open, always async, user and password not supported.
 | 
	
		
			
			|  | 77 | +
 | 
	
		
			
			|  | 78 | +  /**
 | 
	
		
			
			|  | 79 | +   * XMLHttpRequest.open, always async, user and password not supported. When
 | 
	
		
			
			|  | 80 | +   * this method invoked, headers should becomes empty again.
 | 
	
		
			
			|  | 81 | +   * @param  {string} method Request method
 | 
	
		
			
			|  | 82 | +   * @param  {string} url Request URL
 | 
	
		
			
			|  | 83 | +   * @param  {true} async Always async
 | 
	
		
			
			|  | 84 | +   * @param  {any} user NOT SUPPORTED
 | 
	
		
			
			|  | 85 | +   * @param  {any} password NOT SUPPORTED
 | 
	
		
			
			|  | 86 | +   */
 | 
	
		
			
			| 78 | 87 |    open(method:string, url:string, async:true, user:any, password:any) {
 | 
	
		
			
			| 79 | 88 |      log.verbose('XMLHttpRequest open ', method, url, async, user, password)
 | 
	
		
			
			| 80 | 89 |      this._method = method
 | 
	
		
			
			| 81 | 90 |      this._url = url
 | 
	
		
			
			|  | 91 | +    this._headers = {}
 | 
	
		
			
			| 82 | 92 |      this.readyState = XMLHttpRequest.OPENED
 | 
	
		
			
			| 83 | 93 |    }
 | 
	
		
			
			| 84 | 94 |  
 | 
	
	
		
			
			|  | @@ -87,6 +97,10 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 87 | 97 |     * @param  {any} body Body in RNfetchblob flavor
 | 
	
		
			
			| 88 | 98 |     */
 | 
	
		
			
			| 89 | 99 |    send(body) {
 | 
	
		
			
			|  | 100 | +
 | 
	
		
			
			|  | 101 | +    if(this._readyState !== XMLHttpRequest.OPENED)
 | 
	
		
			
			|  | 102 | +      throw 'InvalidStateError : XMLHttpRequest is not opened yet.'
 | 
	
		
			
			|  | 103 | +
 | 
	
		
			
			| 90 | 104 |      this._sendFlag = true
 | 
	
		
			
			| 91 | 105 |      log.verbose('XMLHttpRequest send ', body)
 | 
	
		
			
			| 92 | 106 |      let {_method, _url, _headers } = this
 | 
	
	
		
			
			|  | @@ -123,8 +137,19 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 123 | 137 |      if(this._readyState !== OPENED && this._sendFlag) {
 | 
	
		
			
			| 124 | 138 |        throw `InvalidStateError : Calling setRequestHeader in wrong state  ${this._readyState}`
 | 
	
		
			
			| 125 | 139 |      }
 | 
	
		
			
			| 126 |  | -    if(/[^\u0000-\u00ff]/.test(name) || typeof name !== 'string') {
 | 
	
		
			
			| 127 |  | -      throw `TypeError : Invalid header field name ${name}`
 | 
	
		
			
			|  | 140 | +    // UNICODE SHOULD NOT PASS
 | 
	
		
			
			|  | 141 | +    if(typeof name !== 'string' || /[^\u0000-\u00ff]/.test(name)) {
 | 
	
		
			
			|  | 142 | +      throw 'TypeError : header field name should be a string'
 | 
	
		
			
			|  | 143 | +    }
 | 
	
		
			
			|  | 144 | +    //
 | 
	
		
			
			|  | 145 | +    let invalidPatterns = [
 | 
	
		
			
			|  | 146 | +      /[\(\)\>\<\@\,\:\\\/\[\]\?\=\}\{\s\ \u007f\;\t\0\v\r]/,
 | 
	
		
			
			|  | 147 | +      /tt/
 | 
	
		
			
			|  | 148 | +    ]
 | 
	
		
			
			|  | 149 | +    for(let i in invalidPatterns) {
 | 
	
		
			
			|  | 150 | +      if(invalidPatterns[i].test(name) || typeof name !== 'string') {
 | 
	
		
			
			|  | 151 | +        throw `SyntaxError : Invalid header field name ${name}`
 | 
	
		
			
			|  | 152 | +      }
 | 
	
		
			
			| 128 | 153 |      }
 | 
	
		
			
			| 129 | 154 |      this._headers[name] = value
 | 
	
		
			
			| 130 | 155 |    }
 | 
	
	
		
			
			|  | @@ -160,9 +185,9 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 160 | 185 |    }
 | 
	
		
			
			| 161 | 186 |  
 | 
	
		
			
			| 162 | 187 |    getAllResponseHeaders():string | null {
 | 
	
		
			
			| 163 |  | -    log.verbose('XMLHttpRequest get all headers',this._task.taskId, this._responseHeaders)
 | 
	
		
			
			|  | 188 | +    log.verbose('XMLHttpRequest get all headers', this._responseHeaders)
 | 
	
		
			
			| 164 | 189 |      if(!this._responseHeaders)
 | 
	
		
			
			| 165 |  | -      return null
 | 
	
		
			
			|  | 190 | +      return ''
 | 
	
		
			
			| 166 | 191 |      let result = ''
 | 
	
		
			
			| 167 | 192 |      let respHeaders = this.responseHeaders
 | 
	
		
			
			| 168 | 193 |      for(let i in respHeaders) {
 | 
	
	
		
			
			|  | @@ -202,10 +227,10 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 202 | 227 |  
 | 
	
		
			
			| 203 | 228 |    _onError(err) {
 | 
	
		
			
			| 204 | 229 |      log.verbose('XMLHttpRequest error', err)
 | 
	
		
			
			| 205 |  | -    this.statusText = err
 | 
	
		
			
			| 206 |  | -    this.status = String(err).match(/\d+/)
 | 
	
		
			
			| 207 |  | -    this.status = this.status ? Math.floor(this.status) : 404
 | 
	
		
			
			| 208 |  | -    this.readyState = XMLHttpRequest.DONE
 | 
	
		
			
			|  | 230 | +    this._statusText = err
 | 
	
		
			
			|  | 231 | +    this._status = String(err).match(/\d+/)
 | 
	
		
			
			|  | 232 | +    this._status = this._status ? Math.floor(this.status) : 404
 | 
	
		
			
			|  | 233 | +    this._readyState = XMLHttpRequest.DONE
 | 
	
		
			
			| 209 | 234 |      if(String(err).match('timeout') !== null) {
 | 
	
		
			
			| 210 | 235 |        this.dispatchEvent('timeout')
 | 
	
		
			
			| 211 | 236 |        if(this.ontimeout)
 | 
	
	
		
			
			|  | @@ -223,7 +248,6 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 223 | 248 |    _onDone(resp) {
 | 
	
		
			
			| 224 | 249 |      log.verbose('XMLHttpRequest done', this._task.taskId, this)
 | 
	
		
			
			| 225 | 250 |      this.statusText = '200 OK'
 | 
	
		
			
			| 226 |  | -    this._status = 200
 | 
	
		
			
			| 227 | 251 |      switch(resp.type) {
 | 
	
		
			
			| 228 | 252 |        case 'base64' :
 | 
	
		
			
			| 229 | 253 |          if(this.responseType === 'json') {
 | 
	
	
		
			
			|  | @@ -306,7 +330,7 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
 | 
	
		
			
			| 306 | 330 |    }
 | 
	
		
			
			| 307 | 331 |  
 | 
	
		
			
			| 308 | 332 |    get responseHeaders() {
 | 
	
		
			
			| 309 |  | -    log.verbose('get responseHeaders', this._task.taskId, this._responseHeaders)
 | 
	
		
			
			|  | 333 | +    log.verbose('get responseHeaders', this._responseHeaders)
 | 
	
		
			
			| 310 | 334 |      return this._responseHeaders
 | 
	
		
			
			| 311 | 335 |    }
 | 
	
		
			
			| 312 | 336 |  
 |