Convert everything to HTTPS
[fonbot.git] / src / ro / ieval / fonbot / HttpCallExecutableRunnable.java
CommitLineData
8dfb76c9
MG
1package ro.ieval.fonbot;
2
3import static ro.ieval.fonbot.R.string.*;
8dfb76c9
MG
4import static ro.ieval.fonbot.Utils.toNonNull;
5
2e5049c9 6import java.io.InputStream;
8dfb76c9 7import java.io.OutputStream;
8dfb76c9 8import java.net.URL;
9717b83e
MG
9import java.security.cert.CertificateException;
10import java.security.cert.X509Certificate;
8dfb76c9
MG
11import java.util.Collection;
12
9717b83e
MG
13import javax.net.ssl.HttpsURLConnection;
14import javax.net.ssl.SSLContext;
15import javax.net.ssl.SSLSocketFactory;
16import javax.net.ssl.X509TrustManager;
17
8dfb76c9
MG
18import org.eclipse.jdt.annotation.Nullable;
19
20import android.content.Context;
d13f1533
MG
21import android.preference.PreferenceManager;
22import android.util.Base64;
8dfb76c9
MG
23import android.util.Log;
24
8bfdcf7a
MG
25import com.google.android.gcm.GCMRegistrar;
26
8dfb76c9
MG
27/*
28 * Copyright © 2013 Marius Gavrilescu
29 *
30 * This file is part of FonBot.
31 *
32 * FonBot is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, either version 3 of the License, or
35 * (at your option) any later version.
36 *
37 * FonBot is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 * GNU General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License
43 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
44 */
45
46/**
9717b83e 47 * ExecutableRunnable that makes a HTTPS call to the server and hands the response to a callback
8dfb76c9
MG
48 *
49 * @author Marius Gavrilescu <marius@ieval.ro>
50 */
2e5049c9 51public final class HttpCallExecutableRunnable extends ExecutableRunnable{
9717b83e
MG
52 /**
53 * X509TrustManager that trusts any certificate
54 *
55 * @author Marius Gavrilescu
56 */
57 private static final class TotallyInsecureTrustManager implements X509TrustManager {
58 @Override
59 public @Nullable X509Certificate[] getAcceptedIssuers() {
60 return new X509Certificate[0];
61 }
62
63 @Override
64 public void checkServerTrusted(final @Nullable X509Certificate[] chain, final @Nullable String authType)
65 throws CertificateException {
66 //do nothing
67 }
68
69 @Override
70 public void checkClientTrusted(final @Nullable X509Certificate[] chain, final @Nullable String authType)
71 throws CertificateException {
72 //do nothing
73 }
74 }
75
8dfb76c9 76 /**
2e5049c9
MG
77 * Callback which is run after a HTTP call.
78 *
79 * @author Marius Gavrilescu
8dfb76c9 80 */
2e5049c9
MG
81 public static interface ResultCallback{
82 /**
83 * Callback invoked if the HTTP call is successful.
84 *
85 * @param responseCode HTTP response code
86 * @param responseMessage HTTP response message
87 * @param inputStream HTTP content InputStream
88 */
89 public void onResult(final int responseCode, final String responseMessage, final InputStream inputStream);
90 /**
91 * Callback invoked if the HTTP call is unsuccessful.
92 *
93 * @param error localized error message
94 */
95 public void onError(final String error);
96 }
8dfb76c9 97
9717b83e
MG
98 /** SSLSocketFactory that uses {@link TotallyInsecureTrustManager} */
99 private static final SSLSocketFactory DEFAULT_SOCKET_FACTORY;
100 static{
101 try{
102 final SSLContext sslcontext=SSLContext.getInstance("TLS");
103 sslcontext.init(null, new X509TrustManager[]{new TotallyInsecureTrustManager()}, null);
104 DEFAULT_SOCKET_FACTORY=sslcontext.getSocketFactory();
105 } catch(final Exception e){
106 Log.wtf("HttpCallExecutableRunnable", "Cannot create SSLSocketFactory", e);
107 throw new AssertionError("Log.wtf did not terminate the process");
108 }
109 }
110
8dfb76c9
MG
111 /**
112 * List of extra request headers.
113 */
114 private final Collection<Header> headers;
8dfb76c9
MG
115 /**
116 * Context instance used by this class
117 */
118 private final Context context;
119 /**
120 * Data to send to the server
121 */
122 private final byte[] data;
d13f1533
MG
123 /**
124 * Server URL path
125 */
126 private final String path;
8dfb76c9 127 /**
2e5049c9 128 * Callback to run after the request returns
8dfb76c9 129 */
2e5049c9 130 private final ResultCallback callback;
8dfb76c9
MG
131
132 /**
2e5049c9 133 * Constructs a SendHttpMessageAsyncTask which sends a binary message.
8dfb76c9 134 *
d13f1533 135 * @param path URL path
8dfb76c9
MG
136 * @param headers the extra headers
137 * @param context the context instance
2e5049c9 138 * @param resultCallback {@link ResultCallback} instance
8dfb76c9
MG
139 * @param data the message to send
140 */
2e5049c9 141 public HttpCallExecutableRunnable(final String path, final @Nullable Collection<Header> headers, final Context context, final @Nullable ResultCallback resultCallback, final byte[] data){//NOPMD array is supposed to be immutable.
d13f1533 142 this.path=path;
8dfb76c9 143 this.headers=headers;
8dfb76c9 144 this.context=context;
2e5049c9 145 this.callback=resultCallback;
8dfb76c9
MG
146 this.data=data;
147 }
148
149 /**
2e5049c9 150 * Constructs a SendHttpMessageAsyncTask which sends a text message.
8dfb76c9 151 *
d13f1533 152 * @param path URL path
8dfb76c9 153 * @param headers the extra headers
8dfb76c9 154 * @param context the context instance
2e5049c9
MG
155 * @param resultCallback {@link ResultCallback} instance
156 * @param message message to send
8dfb76c9 157 */
2e5049c9 158 public HttpCallExecutableRunnable(final String path, final @Nullable Collection<Header> headers, final Context context, final @Nullable ResultCallback resultCallback, final String... message){
d13f1533 159 this.path=path;
8dfb76c9 160 this.headers=headers;
8dfb76c9 161 this.context=context;
2e5049c9
MG
162 this.callback=resultCallback;
163 if(message.length == 0)
164 this.data=null;//NOPMD final field
165 else
166 this.data=Utils.join(" ", message).getBytes();
8dfb76c9
MG
167 }
168
169 @Override
2e5049c9 170 public void run() {
8dfb76c9 171 try {
d13f1533 172 final URL url=Utils.getServerURL(toNonNull(context),toNonNull(path));
9717b83e
MG
173 final HttpsURLConnection conn=(HttpsURLConnection) url.openConnection();
174 conn.setSSLSocketFactory(DEFAULT_SOCKET_FACTORY);
2e5049c9 175 if(data!=null){
d13f1533 176 conn.setDoOutput(true);
2e5049c9 177 conn.setFixedLengthStreamingMode(data.length);
d13f1533 178 }
8bfdcf7a 179 conn.setRequestProperty("X-ID", GCMRegistrar.getRegistrationId(context));
d13f1533
MG
180 final String user=PreferenceManager.getDefaultSharedPreferences(context).getString("username", null);
181 final String password=PreferenceManager.getDefaultSharedPreferences(context).getString("password", null);
2e5049c9
MG
182 if(user == null || password == null){
183 if(callback!=null)
184 callback.onError(toNonNull(context.getString(user_or_password_not_set)));
185 return;
186 }
d13f1533
MG
187
188 conn.setRequestProperty("Authorization", "Basic "+Base64.encodeToString(
189 (user+':'+password).getBytes(), Base64.NO_WRAP));
2e5049c9
MG
190 if(headers != null)
191 for (final Header header : headers)
192 conn.setRequestProperty(header.name, header.value);
8dfb76c9 193 conn.connect();
2e5049c9 194 if(data!=null){
d13f1533 195 final OutputStream stream=conn.getOutputStream();
2e5049c9 196 stream.write(data);
d13f1533
MG
197 stream.close();
198 }
8dfb76c9 199 Log.d(getClass().getName(),"HTTP Response: "+conn.getResponseCode()+" "+conn.getResponseMessage());
8dfb76c9 200 final String message=conn.getResponseMessage();
2e5049c9
MG
201 if(message==null && callback != null)
202 callback.onError(toNonNull(context.getString(no_response_returned_from_server)));
203 else if(message != null && callback != null)
204 callback.onResult(conn.getResponseCode(), Utils.parseHttpMessage(message),
205 toNonNull(conn.getInputStream()));
206 conn.disconnect();
8dfb76c9 207 } catch (Exception e) {
a97d31fb 208 e.printStackTrace();
c33b4990
MG
209 if(callback != null)
210 callback.onError(toNonNull(context.getString(connection_error)));
8dfb76c9
MG
211 }
212 }
213}
This page took 0.025033 seconds and 4 git commands to generate.