summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java
blob: cc875c79e205131685a9aeabcb12608fbf8d5e9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
 * Copyright (c) 2018 LEAP Encryption Access Project and contributers
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package se.leap.bitmaskclient.providersetup;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import android.util.Pair;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;

import javax.net.ssl.SSLHandshakeException;

import de.blinkt.openvpn.core.NativeUtils;
import de.blinkt.openvpn.core.VpnStatus;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by cyberta on 08.01.18.
 */

public class ProviderApiConnector {

    public interface ProviderApiConnectorInterface {
        boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException;
        boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException;
        String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException;

    }

    public static class DefaultProviderApiCpnnector implements ProviderApiConnectorInterface {

        @Override
        public boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
            try {
                Request.Builder requestBuilder = new Request.Builder()
                        .url(deleteUrl)
                        .delete();
                Request request = requestBuilder.build();

                Response response = okHttpClient.newCall(request).execute();
                //response code 401: already logged out
                if (response.isSuccessful() || response.code() == 401) {
                    return true;
                }
            }  catch (IOException | RuntimeException e) {
                return false;
            }

            return false;
        }

        @Override
        public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
            Request.Builder requestBuilder = new Request.Builder()
                    .url(url)
                    .method("GET", null);
            Request request = requestBuilder.build();

            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                VpnStatus.logWarning("[API] API request failed canConnect(): " + url);
            }
            return response.isSuccessful();
        }

        @Override
        public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
            RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null;
            Request.Builder requestBuilder = new Request.Builder()
                    .url(url)
                    .method(requestMethod, jsonBody);
            for (Pair<String, String> keyValPair : headerArgs) {
                requestBuilder.addHeader(keyValPair.first, keyValPair.second);
            }

            //TODO: move to getHeaderArgs()?
            String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry();
            requestBuilder.addHeader("Accept-Language", locale);
            Request request = requestBuilder.build();

            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                VpnStatus.logWarning("[API] API request failed: " + url);
            }

            if (response.body() != null) {
                InputStream inputStream = response.body().byteStream();
                Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
                if (scanner.hasNext()) {
                    String result = scanner.next();
                    response.body().close();
                    return result;
                }
            }
            return null;
        }
    }
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static ProviderApiConnectorInterface instance = new DefaultProviderApiCpnnector();

    @VisibleForTesting
    public ProviderApiConnector(ProviderApiConnectorInterface connectorInterface) {
        if (!NativeUtils.isUnitTest()) {
            throw new IllegalStateException("ProviderApiConnector injected with ProviderApiConnectorInterface outside of an unit test");
        }
        instance = connectorInterface;
    }


    public static boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
      return instance.delete(okHttpClient, deleteUrl);
    }

    public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
       return instance.canConnect(okHttpClient, url);

    }

    public static String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
        return instance.requestStringFromServer(url, requestMethod, jsonString, headerArgs, okHttpClient);
    }
}