<commit_before>package org.commcare.network;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import org.commcare.CommCareApplication;
import org.commcare.interfaces.HttpResponseProcessor;
import org.commcare.interfaces.ResponseStreamAccessor;
import org.commcare.utils.AndroidStreamUtil;
import org.commcare.utils.GlobalConstants;
import org.commcare.utils.SessionUnavailableException;
import org.commcare.utils.bitcache.BitCache;
import org.commcare.utils.bitcache.BitCacheFactory;
import org.javarosa.core.model.User;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * Make http get/post requests with query params encoded in get url or post
 * body. Delegates response to appropriate response processor callback
 *
 * @author <NAME> (<EMAIL>)
 */
public class ModernHttpRequester implements ResponseStreamAccessor {
    private static final String TAG = ModernHttpRequester.class.getSimpleName();
    private final boolean isPostRequest;
    private final Context context;
    private HttpResponseProcessor responseProcessor;
    protected final URL url;
    private final HashMap<String, String> params;
    private HttpURLConnection httpConnection;

    public ModernHttpRequester(Context context, URL url,
                               HashMap<String, String> params,
                               boolean isAuthenticatedRequest,
                               boolean isPostRequest) {
        this.isPostRequest = isPostRequest;
        this.context = context;
        this.params = params;
        this.url = url;

        setupAuthentication(isAuthenticatedRequest);
    }

    public void setResponseProcessor(HttpResponseProcessor responseProcessor) {
        this.responseProcessor = responseProcessor;
    }

    private void setupAuthentication(boolean isAuth) {
        if (isAuth) {
            User u = getCurrentUser();
            final String username = u.getUsername();
            final String password = u.getCachedPwd();
            if (username == null || password == null || User.TYPE_DEMO.equals(u.getUserType())) {
                String message =
                        "Trying to make authenticated http request without proper credentials";
                throw new RuntimeException(message);
            } else if (!"https".equals(url.getProtocol())) {
                throw new PlainTextPasswordException();
            } else {
                // make authenticated requests
                Authenticator.setDefault(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(
                                HttpRequestGenerator.buildDomainUser(username),
                                password.toCharArray());
                    }
                });
            }
        } else {
            // clear any prior set authenticator to make unauthed requests
            Authenticator.setDefault(null);
        }
    }

    public static class PlainTextPasswordException extends RuntimeException {
    }

    private static User getCurrentUser() {
        try {
            return CommCareApplication._().getSession().getLoggedInUser();
        } catch (SessionUnavailableException sue) {
            throw new RuntimeException("Can't find user to make authenticated http request.");
        }
    }

    public void request() {
        try {
            httpConnection = setupConnection(buildUrl());
            processResponse();
        } catch (IOException e) {
            e.printStackTrace();
            responseProcessor.handleIOException(e);
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }
        }
    }

    private URL buildUrl() throws IOException {
        if (isPostRequest) {
            return url;
        } else {
            return buildUrlWithParams();
        }
    }

    protected HttpURLConnection setupConnection(URL builtUrl) throws IOException {
        Log.d(TAG, builtUrl.toString());
        HttpURLConnection httpConnection = (HttpURLConnection)builtUrl.openConnection();
        if (isPostRequest) {
            setupConnectionInner(httpConnection);
            httpConnection.setRequestMethod("POST");
            httpConnection.setDoOutput(true);
            buildPostPayload(httpConnection);
        } else {
            setupConnectionInner(httpConnection);
            httpConnection.setRequestMethod("GET");
        }

        return httpConnection;
    }

    private static void setupConnectionInner(HttpURLConnection httpConnection) {
        httpConnection.setConnectTimeout(GlobalConstants.CONNECTION_TIMEOUT);
        httpConnection.setReadTimeout(GlobalConstants.CONNECTION_SO_TIMEOUT);
        httpConnection.setDoInput(true);
        httpConnection.setInstanceFollowRedirects(true);
    }

    private void buildPostPayload(HttpURLConnection httpConnection) throws IOException {
        String paramsString = buildUrlWithParams().getQuery();
        Log.d(TAG, paramsString);
        int bodySize = paramsString.length();
        httpConnection.setFixedLengthStreamingMode(bodySize);
        httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        httpConnection.setRequestProperty("Content-Length", bodySize + "");
        // write to connection
        OutputStream os = httpConnection.getOutputStream();
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(os, "UTF-8"));
        writer.write(paramsString);<commit_msg>Remove streaming to allow request retry<commit_after>package org.commcare.network;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import org.commcare.CommCareApplication;
import org.commcare.interfaces.HttpResponseProcessor;
import org.commcare.interfaces.ResponseStreamAccessor;
import org.commcare.utils.AndroidStreamUtil;
import org.commcare.utils.GlobalConstants;
import org.commcare.utils.SessionUnavailableException;
import org.commcare.utils.bitcache.BitCache;
import org.commcare.utils.bitcache.BitCacheFactory;
import org.javarosa.core.model.User;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * Make http get/post requests with query params encoded in get url or post
 * body. Delegates response to appropriate response processor callback
 *
 * @author <NAME> (<EMAIL>)
 */
public class ModernHttpRequester implements ResponseStreamAccessor {
    private static final String TAG = ModernHttpRequester.class.getSimpleName();
    private final boolean isPostRequest;
    private final Context context;
    private HttpResponseProcessor responseProcessor;
    protected final URL url;
    private final HashMap<String, String> params;
    private HttpURLConnection httpConnection;

    public ModernHttpRequester(Context context, URL url,
                               HashMap<String, String> params,
                               boolean isAuthenticatedRequest,
                               boolean isPostRequest) {
        this.isPostRequest = isPostRequest;
        this.context = context;
        this.params = params;
        this.url = url;

        setupAuthentication(isAuthenticatedRequest);
    }

    public void setResponseProcessor(HttpResponseProcessor responseProcessor) {
        this.responseProcessor = responseProcessor;
    }

    private void setupAuthentication(boolean isAuth) {
        if (isAuth) {
            User u = getCurrentUser();
            final String username = u.getUsername();
            final String password = <PASSWORD>();
            if (username == null || password == null || User.TYPE_DEMO.equals(u.getUserType())) {
                String message =
                        "Trying to make authenticated http request without proper credentials";
                throw new RuntimeException(message);
            } else if (!"https".equals(url.getProtocol())) {
                throw new PlainTextPasswordException();
            } else {
                // make authenticated requests
                Authenticator.setDefault(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(
                                HttpRequestGenerator.buildDomainUser(username),
                                password.toCharArray());
                    }
                });
            }
        } else {
            // clear any prior set authenticator to make unauthed requests
            Authenticator.setDefault(null);
        }
    }

    public static class PlainTextPasswordException extends RuntimeException {
    }

    private static User getCurrentUser() {
        try {
            return CommCareApplication._().getSession().getLoggedInUser();
        } catch (SessionUnavailableException sue) {
            throw new RuntimeException("Can't find user to make authenticated http request.");
        }
    }

    public void request() {
        try {
            httpConnection = setupConnection(buildUrl());
            processResponse();
        } catch (IOException e) {
            e.printStackTrace();
            responseProcessor.handleIOException(e);
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }
        }
    }

    private URL buildUrl() throws IOException {
        if (isPostRequest) {
            return url;
        } else {
            return buildUrlWithParams();
        }
    }

    protected HttpURLConnection setupConnection(URL builtUrl) throws IOException {
        Log.d(TAG, builtUrl.toString());
        HttpURLConnection httpConnection = (HttpURLConnection)builtUrl.openConnection();
        if (isPostRequest) {
            setupConnectionInner(httpConnection);
            httpConnection.setRequestMethod("POST");
            httpConnection.setDoOutput(true);
            buildPostPayload(httpConnection);
        } else {
            setupConnectionInner(httpConnection);
            httpConnection.setRequestMethod("GET");
        }

        return httpConnection;
    }

    private static void setupConnectionInner(HttpURLConnection httpConnection) {
        httpConnection.setConnectTimeout(GlobalConstants.CONNECTION_TIMEOUT);
        httpConnection.setReadTimeout(GlobalConstants.CONNECTION_SO_TIMEOUT);
        httpConnection.setDoInput(true);
        httpConnection.setInstanceFollowRedirects(true);
    }

    private void buildPostPayload(HttpURLConnection httpConnection) throws IOException {
        String paramsString = buildUrlWithParams().getQuery();
        Log.d(TAG, paramsString);
        int bodySize = paramsString.length();
        httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        httpConnection.setRequestProperty("Content-Length", bodySize + "");
        // write to connection
        OutputStream os = httpConnection.getOutputStream();
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(os, "UTF-8"));
        writer.write(paramsString);
{'fraction_non_alphanumeric': 0.08065059834822182, 'fraction_numerical': 0.00016854879487611664, 'mean_word_length': 2.5776303889056376, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6197774', 'n_tokens_mistral': 2796, 'n_tokens_neox': 2732, 'n_words': 649}