fix some code
[andGMXsms.git] / connectors / gmx / src / de / ub0r / android / websms / connector / gmx / ConnectorGMX.java
blobce693a9025932b214f3168c604c4e257b77285f1
1 /*
2 * Copyright (C) 2010 Felix Bechstein
3 *
4 * This file is part of WebSMS.
5 *
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free Software
8 * Foundation; either version 3 of the License, or (at your option) any later
9 * version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program; If not, see <http://www.gnu.org/licenses/>.
19 package de.ub0r.android.websms.connector.gmx;
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.net.HttpURLConnection;
24 import java.net.URL;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.SharedPreferences;
29 import android.content.SharedPreferences.Editor;
30 import android.preference.PreferenceManager;
31 import android.text.format.DateFormat;
32 import android.util.Log;
33 import de.ub0r.android.websms.connector.common.Connector;
34 import de.ub0r.android.websms.connector.common.ConnectorCommand;
35 import de.ub0r.android.websms.connector.common.ConnectorSpec;
36 import de.ub0r.android.websms.connector.common.Utils;
37 import de.ub0r.android.websms.connector.common.WebSMSException;
38 import de.ub0r.android.websms.connector.common.ConnectorSpec.SubConnectorSpec;
40 /**
41 * AsyncTask to manage IO to GMX API.
43 * @author flx
45 public class ConnectorGMX extends Connector {
46 /** Tag for output. */
47 private static final String TAG = "WebSMS.GMX";
49 /** Preferences intent action. */
50 private static final String PREFS_INTENT_ACTION = "de.ub0r.android."
51 + "websms.connectors.gmx.PREFS";
53 /** Custom {@link DateFormat}. */
54 private static final String DATEFORMAT = "yyyy-MM-dd kk-mm-00";
56 /** Target host. */
57 private static final String[] TARGET_HOST = { "app0.wr-gmbh.de",
58 "app5.wr-gmbh.de" };
59 /** Target path on host. */
60 private static final String TARGET_PATH = "/WRServer/WRServer.dll/WR";
61 /** Target mime encoding. */
62 private static final String TARGET_ENCODING = "wr-cs";
63 /** Target mime type. */
64 private static final String TARGET_CONTENT = "text/plain";
65 /** HTTP Useragent. */
66 private static final String TARGET_AGENT = "Mozilla/3.0 (compatible)";
67 /** Target version of protocol. */
68 private static final String TARGET_PROTOVERSION = "1.13.03";
70 /** Result: ok. */
71 private static final int RSLT_OK = 0;
72 /** Result: wrong customerid/password. */
73 private static final int RSLT_WRONG_CUSTOMER = 11;
74 /** Result: wrong mail/password. */
75 private static final int RSLT_WRONG_MAIL = 25;
76 /** Result: wrong sender. */
77 private static final int RSLT_WRONG_SENDER = 8;
78 /** Result: sender is unregistered by gmx. */
79 private static final int RSLT_UNREGISTERED_SENDER = 71;
81 /** Check whether this connector is bootstrapping. */
82 private static boolean inBootstrap = false;
84 /**
85 * {@inheritDoc}
87 @Override
88 public final ConnectorSpec initSpec(final Context context) {
89 final String name = context.getString(R.string.connector_gmx_name);
90 ConnectorSpec c = new ConnectorSpec(TAG, name);
91 c.setAuthor(// .
92 context.getString(R.string.connector_gmx_author));
93 c.setBalance(null);
94 c.setPrefsIntent(PREFS_INTENT_ACTION);
95 c.setPrefsTitle(context.getString(R.string.connector_gmx_preferences));
96 c.setCapabilities(ConnectorSpec.CAPABILITIES_BOOSTRAP
97 | ConnectorSpec.CAPABILITIES_UPDATE
98 | ConnectorSpec.CAPABILITIES_SEND);
99 c.addSubConnector(TAG, c.getName(),
100 SubConnectorSpec.FEATURE_MULTIRECIPIENTS
101 | SubConnectorSpec.FEATURE_CUSTOMSENDER
102 | SubConnectorSpec.FEATURE_SENDLATER);
103 return c;
107 * {@inheritDoc}
109 @Override
110 public final ConnectorSpec updateSpec(final Context context,
111 final ConnectorSpec connectorSpec) {
112 final SharedPreferences p = PreferenceManager
113 .getDefaultSharedPreferences(context);
114 if (p.getBoolean(Preferences.PREFS_ENABLED, false)) {
115 if (p.getString(Preferences.PREFS_MAIL, "").length() > 0
116 && p.getString(Preferences.PREFS_PASSWORD, "") // .
117 .length() > 0) {
118 connectorSpec.setReady();
119 } else {
120 connectorSpec.setStatus(ConnectorSpec.STATUS_ENABLED);
122 } else {
123 connectorSpec.setStatus(ConnectorSpec.STATUS_INACTIVE);
125 return connectorSpec;
129 * {@inheritDoc}
131 @Override
132 protected final void doBootstrap(final Context context, final Intent intent)
133 throws WebSMSException {
134 Log.d(TAG, "bootstrap");
135 if (inBootstrap) {
136 // TODO: fail here
138 if (!Preferences.needBootstrap(context)) {
139 return;
141 inBootstrap = true;
142 StringBuilder packetData = openBuffer(context, "GET_CUSTOMER", "1.10",
143 false);
144 SharedPreferences p = PreferenceManager
145 .getDefaultSharedPreferences(context);
146 writePair(packetData, "email_address", p.getString(
147 Preferences.PREFS_MAIL, ""));
148 writePair(packetData, "password", p.getString(
149 Preferences.PREFS_PASSWORD, ""));
150 writePair(packetData, "gmx", "1");
151 this.sendData(context, closeBuffer(packetData));
155 * {@inheritDoc}
157 @Override
158 protected final void doUpdate(final Context context, final Intent intent)
159 throws WebSMSException {
160 Log.d(TAG, "update");
161 this.doBootstrap(context, intent);
163 this.sendData(context, closeBuffer(openBuffer(context,
164 "GET_SMS_CREDITS", "1.00", true)));
168 * {@inheritDoc}
170 @Override
171 protected final void doSend(final Context context, final Intent intent)
172 throws WebSMSException {
173 Log.d(TAG, "send");
174 this.doBootstrap(context, intent);
176 ConnectorCommand command = new ConnectorCommand(intent);
177 StringBuilder packetData = openBuffer(context, "SEND_SMS", "1.01", true);
178 // fill buffer
179 writePair(packetData, "sms_text", command.getText());
180 StringBuilder recipients = new StringBuilder();
181 // table: <id>, <name>, <number>
182 int j = 0;
183 String[] to = command.getRecipients();
184 for (int i = 0; i < to.length; i++) {
185 if (to[i] != null && to[i].length() > 1) {
186 recipients.append(++j);
187 recipients.append("\\;null\\;");
188 recipients.append(Utils.getRecipientsNumber(to[i]));
189 recipients.append("\\;");
192 recipients.append("</TBL>");
193 String recipientsString = "<TBL ROWS=\"" + j + "\" COLS=\"3\">"
194 + "receiver_id\\;receiver_name\\;receiver_number\\;"
195 + recipients.toString();
196 recipients = null;
197 writePair(packetData, "receivers", recipientsString);
198 writePair(packetData, "send_option", "sms");
199 final String customSender = command.getCustomSender();
200 if (customSender != null && customSender.length() > 0) {
201 writePair(packetData, "sms_sender", customSender);
202 } else {
203 writePair(packetData, "sms_sender", command.getDefSender());
205 final long sendLater = command.getSendLater();
206 if (sendLater > 0) {
207 writePair(packetData, "send_date", DateFormat.format(DATEFORMAT,
208 sendLater).toString());
210 // push data
211 this.sendData(context, closeBuffer(packetData));
215 * Write key,value to StringBuilder.
217 * @param buffer
218 * buffer
219 * @param key
220 * key
221 * @param value
222 * value
224 private static void writePair(final StringBuilder buffer, final String key,
225 final String value) {
226 buffer.append(key);
227 buffer.append('=');
228 buffer.append(value.replace("\\", "\\\\").replace(">", "\\>").replace(
229 "<", "\\<"));
230 buffer.append("\\p");
234 * Create default data hashtable.
236 * @param context
237 * {@link Context}
238 * @param packetName
239 * packetName
240 * @param packetVersion
241 * packetVersion
242 * @param addCustomer
243 * add customer id/password
244 * @return Hashtable filled with customer_id and password.
246 private static StringBuilder openBuffer(final Context context,
247 final String packetName, final String packetVersion,
248 final boolean addCustomer) {
249 StringBuilder ret = new StringBuilder();
250 ret.append("<WR TYPE=\"RQST\" NAME=\"");
251 ret.append(packetName);
252 ret.append("\" VER=\"");
253 ret.append(packetVersion);
254 ret.append("\" PROGVER=\"");
255 ret.append(TARGET_PROTOVERSION);
256 ret.append("\">");
257 if (addCustomer) {
258 SharedPreferences p = PreferenceManager
259 .getDefaultSharedPreferences(context);
260 writePair(ret, "customer_id", p.getString(Preferences.PREFS_USER,
261 ""));
262 writePair(ret, "password", p.getString(Preferences.PREFS_PASSWORD,
263 ""));
265 return ret;
269 * Close Buffer.
271 * @param buffer
272 * buffer
273 * @return buffer
275 private static StringBuilder closeBuffer(final StringBuilder buffer) {
276 buffer.append("</WR>");
277 return buffer;
281 * Parse returned packet. Search for name=(.*)\n and return (.*)
283 * @param packet
284 * packet
285 * @param name
286 * parma's name
287 * @return param's value
289 private static String getParam(final String packet, final String name) {
290 int i = packet.indexOf(name + '=');
291 if (i < 0) {
292 return null;
294 int j = packet.indexOf("\n", i);
295 if (j < 0) {
296 return packet.substring(i + name.length() + 1);
297 } else {
298 return packet.substring(i + name.length() + 1, j);
303 * Send data.
305 * @param context
306 * {@link Context}
307 * @param packetData
308 * packetData
309 * @return successful?
310 * @throws WebSMSException
311 * WebSMSException
313 private void sendData(final Context context, final StringBuilder packetData)
314 throws WebSMSException {
315 try {
316 // check connection:
317 // get cluster side
318 SharedPreferences sp = PreferenceManager
319 .getDefaultSharedPreferences(context);
320 int gmxHost = sp.getInt(Preferences.PREFS_GMX_HOST, 0);
321 HttpURLConnection c = (HttpURLConnection) (new URL("http://"
322 + TARGET_HOST[gmxHost] + TARGET_PATH)).openConnection();
323 // set prefs
324 c.setRequestProperty("User-Agent", TARGET_AGENT);
325 c.setRequestProperty("Content-Encoding", TARGET_ENCODING);
326 c.setRequestProperty("Content-Type", TARGET_CONTENT);
327 int resp = c.getResponseCode();
328 if (resp == Utils.HTTP_SERVICE_UNAVAILABLE) {
329 // switch hostname
330 gmxHost = (gmxHost + 1) % 2;
331 sp.edit().putInt(Preferences.PREFS_GMX_HOST, gmxHost).commit();
334 // get Connection
335 c = (HttpURLConnection) (new URL("http://" + TARGET_HOST[gmxHost]
336 + TARGET_PATH)).openConnection();
337 // set prefs
338 c.setRequestProperty("User-Agent", TARGET_AGENT);
339 c.setRequestProperty("Content-Encoding", TARGET_ENCODING);
340 c.setRequestProperty("Content-Type", TARGET_CONTENT);
341 c.setRequestMethod("POST");
342 c.setDoOutput(true);
343 // push post data
344 OutputStream os = c.getOutputStream();
345 os.write(packetData.toString().getBytes("ISO-8859-15"));
346 os.close();
347 os = null;
348 Log.d(TAG, "--HTTP POST--");
349 Log.d(TAG, packetData.toString());
350 Log.d(TAG, "--HTTP POST--");
352 // send data
353 resp = c.getResponseCode();
354 if (resp != HttpURLConnection.HTTP_OK) {
355 if (resp == Utils.HTTP_SERVICE_UNAVAILABLE) {
356 throw new WebSMSException(context, R.string.error_service,
357 "" + resp);
358 } else {
359 throw new WebSMSException(context, R.string.error_http, ""
360 + resp);
363 // read received data
364 int bufsize = c.getHeaderFieldInt("Content-Length", -1);
365 if (bufsize > 0) {
366 String resultString = Utils.stream2str(c.getInputStream());
367 if (resultString.startsWith("The truth")) {
368 // wrong data sent!
369 throw new WebSMSException(context, R.string.error_server,
370 "" + resultString);
372 Log.d(TAG, "--HTTP RESPONSE--");
373 Log.d(TAG, resultString);
374 Log.d(TAG, "--HTTP RESPONSE--");
376 // strip packet
377 int resultIndex = resultString.indexOf("rslt=");
378 String outp = resultString.substring(resultIndex).replace(
379 "\\p", "\n");
380 outp = outp.replace("</WR>", "");
382 // get result code
383 String resultValue = getParam(outp, "rslt");
384 int rslt;
385 try {
386 rslt = Integer.parseInt(resultValue);
387 } catch (Exception e) {
388 Log.e(TAG, null, e);
389 throw new WebSMSException(e.toString());
391 switch (rslt) {
392 case RSLT_OK: // ok
393 // fetch additional info
394 String p = getParam(outp, "free_rem_month");
395 if (p != null) {
396 String b = p;
397 p = getParam(outp, "free_max_month");
398 if (p != null) {
399 b += "/" + p;
401 this.getSpecs(context).setBalance(b);
403 p = getParam(outp, "customer_id");
404 if (p != null) {
405 Editor e = PreferenceManager
406 .getDefaultSharedPreferences(context).edit();
407 e.putString(Preferences.PREFS_USER, p);
408 e.commit();
409 inBootstrap = false;
411 return;
412 case RSLT_WRONG_CUSTOMER: // wrong user/pw
413 throw new WebSMSException(context, R.string.error_pw);
414 case RSLT_WRONG_MAIL: // wrong mail/pw
415 inBootstrap = false;
416 throw new WebSMSException(context, R.string.error_mail);
417 case RSLT_WRONG_SENDER: // wrong sender
418 throw new WebSMSException(context, R.string.error_sender);
419 case RSLT_UNREGISTERED_SENDER: // unregistered sender
420 throw new WebSMSException(context,
421 R.string.error_sender_unregistered);
422 default:
423 throw new WebSMSException(outp + " #" + rslt);
425 } else {
426 throw new WebSMSException(context,
427 R.string.error_http_header_missing);
429 } catch (IOException e) {
430 Log.e(TAG, null, e);
431 throw new WebSMSException(e);