| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -388,12 +388,8 @@ class LokiAppDotNetServerAPI {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (params) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      url.search = new URLSearchParams(params);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let result;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let ephemeralKey;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let symKey;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let iv;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const fetchOptions = {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const fetchOptions = {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const headers = {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (forceFreshToken) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        await this.getOrRefreshServerToken(true);
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -411,86 +407,85 @@ class LokiAppDotNetServerAPI {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fetchOptions.body = rawBody;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      fetchOptions.headers = new Headers(headers);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      log.info('serverRequest set up error:', JSON.stringify(e));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        window.lokiFeatureFlags.useSnodeProxy &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        (this.baseServerUrl === 'https://file-dev.lokinet.org' ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          this.baseServerUrl === 'https://file.lokinet.org')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      ) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let result;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let response = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let TxtResponse = '';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      window.lokiFeatureFlags.useSnodeProxy &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      (this.baseServerUrl === 'https://file-dev.lokinet.org' ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.baseServerUrl === 'https://file.lokinet.org')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // make temporary key for this request/response
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ephemeralKey = libsignal.Curve.generateKeyPair();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const ephemeralKey = libsignal.Curve.generateKeyPair();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // mix server pub key with our priv key
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        symKey = libsignal.Curve.calculateAgreement(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const symKey = libsignal.Curve.calculateAgreement(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          this.pubKey, // server's pubkey
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          ephemeralKey.privKey // our privkey
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // some randomness
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        iv = libsignal.crypto.getRandomBytes(IV_LENGTH);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const iv = libsignal.crypto.getRandomBytes(IV_LENGTH);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        log.info('Sending a proxy request to', this.baseServerUrl);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result = await this.constructor._sendToProxy(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          { ...fetchOptions, headers },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          fetchOptions,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          endpoint,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          method,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          { ephemeralKey, symKey, iv }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // log.info('sent to proxy')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result = await nodeFetch(url, fetchOptions || undefined);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      log.info(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        'serverRequest nodeFetch/_sendToProxy error:',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        JSON.stringify(e)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let response = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    let TxtResponse = '';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      TxtResponse = await result.text();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      response = JSON.parse(TxtResponse);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      log.warn(`serverRequest json parse ${e} ${TxtResponse}`);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        statusCode: result.status,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      window.lokiFeatureFlags.useSnodeProxy &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      (this.baseServerUrl === 'https://file-dev.lokinet.org' ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.baseServerUrl === 'https://file.lokinet.org')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      // log.info('Got proxy response', response, 'for', method || 'GET', endpoint);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (response.meta && response.meta.code === 200) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const cipherBuffer = dcodeIO.ByteBuffer.wrap(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            response.data,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            'base64'
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          ).toArrayBuffer();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const decryped = await libsignal.crypto.decrypt(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            symKey,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            cipherBuffer,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            iv
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const textDecoder = new TextDecoder();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const json = textDecoder.decode(decryped);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          response = JSON.parse(json);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          // useless with the ephemeralKey and iv
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          log.warn(`serverRequest useSnodeProxy parse ${e} ${TxtResponse}`);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            statusCode: result.status,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        TxtResponse = await result.text();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        response = JSON.parse(TxtResponse);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (response.meta && response.meta.code === 200) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const cipherBuffer = dcodeIO.ByteBuffer.wrap(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              response.data,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              'base64'
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ).toArrayBuffer();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const decryped = await libsignal.crypto.decrypt(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              symKey,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              cipherBuffer,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              iv
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const textDecoder = new TextDecoder();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const json = textDecoder.decode(decryped);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // replace response
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            response = JSON.parse(json);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // useless with the ephemeralKey and iv
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            log.warn(`serverRequest useSnodeProxy parse ${e} ${TxtResponse}`);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              statusCode: result.status,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          log.warn('file server secure_rpc gave an non-200 response');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // log.info('decrypted response', response);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        log.warn('file server secure_rpc gave an non-200 response');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        log.info('serverRequest _sendToProxy error:', e);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result = await nodeFetch(url, fetchOptions || undefined);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        TxtResponse = await result.text();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        response = JSON.parse(TxtResponse);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        log.info('serverRequest nodeFetch error:', JSON.stringify(e));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          err: e,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |