do cherry
[andGMXsms.git] / connectors / gmx / src / de / ub0r / android / websms / connector / gmx / ConnectorGMX.java
blobacfcdbc4ad86207ed3edfadd3473ce1d6d9fdc8d
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 Log.d(TAG, "skip bootstrap");
140 return;
142 inBootstrap = true;
143 StringBuilder packetData = openBuffer(context, "GET_CUSTOMER", "1.10",
144 false);
145 final SharedPreferences p = PreferenceManager
146 .getDefaultSharedPreferences(context);
147 writePair(packetData, "email_address", p.getString(
148 Preferences.PREFS_MAIL, ""));
149 writePair(packetData, "password", p.getString(
150 Preferences.PREFS_PASSWORD, ""));
151 writePair(packetData, "gmx", "1");
152 this.sendData(context, closeBuffer(packetData));
156 * {@inheritDoc}
158 @Override
159 protected final void doUpdate(final Context context, final Intent intent)
160 throws WebSMSException {
161 Log.d(TAG, "update");
162 this.doBootstrap(context, intent);
164 this.sendData(context, closeBuffer(openBuffer(context,
165 "GET_SMS_CREDITS", "1.00", true)));
169 * {@inheritDoc}
171 @Override
172 protected final void doSend(final Context context, final Intent intent)
173 throws WebSMSException {
174 Log.d(TAG, "send");
175 this.doBootstrap(context, intent);
177 ConnectorCommand command = new ConnectorCommand(intent);
178 StringBuilder packetData = openBuffer(context, "SEND_SMS", "1.01", true);
179 // fill buffer
180 writePair(packetData, "sms_text", command.getText());
181 StringBuilder recipients = new StringBuilder();
182 // table: <id>, <name>, <number>
183 int j = 0;
184 String[] to = command.getRecipients();
185 for (int i = 0; i < to.length; i++) {
186 if (to[i] != null && to[i].length() > 1) {
187 recipients.append(++j);
188 recipients.append("\\;null\\;");
189 recipients.append(Utils.getRecipientsNumber(to[i]));
190 recipients.append("\\;");
193 recipients.append("</TBL>");
194 String recipientsString = "<TBL ROWS=\"" + j + "\" COLS=\"3\">"
195 + "receiver_id\\;receiver_name\\;receiver_number\\;"
196 + recipients.toString();
197 recipients = null;
198 writePair(packetData, "receivers", recipientsString);
199 writePair(packetData, "send_option", "sms");
200 final String customSender = command.getCustomSender();
201 if (customSender != null && customSender.length() > 0) {
202 writePair(packetData, "sms_sender", customSender);
203 } else {
204 writePair(packetData, "sms_sender", command.getDefSender());
206 final long sendLater = command.getSendLater();
207 if (sendLater > 0) {
208 writePair(packetData, "send_date", DateFormat.format(DATEFORMAT,
209 sendLater).toString());
211 // push data
212 this.sendData(context, closeBuffer(packetData));
216 * Write key,value to StringBuilder.
218 * @param buffer
219 * buffer
220 * @param key
221 * key
222 * @param value
223 * value
225 private static void writePair(final StringBuilder buffer, final String key,
226 final String value) {
227 buffer.append(key);
228 buffer.append('=');
229 buffer.append(value.replace("\\", "\\\\").replace(">", "\\>").replace(
230 "<", "\\<"));
231 buffer.append("\\p");
235 * Create default data hashtable.
237 * @param context
238 * {@link Context}
239 * @param packetName
240 * packetName
241 * @param packetVersion
242 * packetVersion
243 * @param addCustomer
244 * add customer id/password
245 * @return Hashtable filled with customer_id and password.
247 private static StringBuilder openBuffer(final Context context,
248 final String packetName, final String packetVersion,
249 final boolean addCustomer) {
250 StringBuilder ret = new StringBuilder();
251 ret.append("<WR TYPE=\"RQST\" NAME=\"");
252 ret.append(packetName);
253 ret.append("\" VER=\"");
254 ret.append(packetVersion);
255 ret.append("\" PROGVER=\"");
256 ret.append(TARGET_PROTOVERSION);
257 ret.append("\">");
258 if (addCustomer) {
259 SharedPreferences p = PreferenceManager
260 .getDefaultSharedPreferences(context);
261 writePair(ret, "customer_id", p.getString(Preferences.PREFS_USER,
262 ""));
263 writePair(ret, "password", p.getString(Preferences.PREFS_PASSWORD,
264 ""));
266 return ret;
270 * Close Buffer.
272 * @param buffer
273 * buffer
274 * @return buffer
276 private static StringBuilder closeBuffer(final StringBuilder buffer) {
277 buffer.append("</WR>");
278 return buffer;
282 * Parse returned packet. Search for name=(.*)\n and return (.*)
284 * @param packet
285 * packet
286 * @param name
287 * parma's name
288 * @return param's value
290 private static String getParam(final String packet, final String name) {
291 int i = packet.indexOf(name + '=');
292 if (i < 0) {
293 return null;
295 int j = packet.indexOf("\n", i);
296 if (j < 0) {
297 return packet.substring(i + name.length() + 1);
298 } else {
299 return packet.substring(i + name.length() + 1, j);
304 * Send data.
306 * @param context
307 * {@link Context}
308 * @param packetData
309 * packetData
310 * @return successful?
311 * @throws WebSMSException
312 * WebSMSException
314 private void sendData(final Context context, final StringBuilder packetData)
315 throws WebSMSException {
316 try {
317 // check connection:
318 // get cluster side
319 SharedPreferences sp = PreferenceManager
320 .getDefaultSharedPreferences(context);
321 int gmxHost = sp.getInt(Preferences.PREFS_GMX_HOST, 0);
322 HttpURLConnection c = (HttpURLConnection) (new URL("http://"
323 + TARGET_HOST[gmxHost] + TARGET_PATH)).openConnection();
324 // set prefs
325 c.setRequestProperty("User-Agent", TARGET_AGENT);
326 c.setRequestProperty("Content-Encoding", TARGET_ENCODING);
327 c.setRequestProperty("Content-Type", TARGET_CONTENT);
328 int resp = c.getResponseCode();
329 if (resp == Utils.HTTP_SERVICE_UNAVAILABLE) {
330 // switch hostname
331 gmxHost = (gmxHost + 1) % 2;
332 sp.edit().putInt(Preferences.PREFS_GMX_HOST, gmxHost).commit();
335 // get Connection
336 c = (HttpURLConnection) (new URL("http://" + TARGET_HOST[gmxHost]
337 + TARGET_PATH)).openConnection();
338 // set prefs
339 c.setRequestProperty("User-Agent", TARGET_AGENT);
340 c.setRequestProperty("Content-Encoding", TARGET_ENCODING);
341 c.setRequestProperty("Content-Type", TARGET_CONTENT);
342 c.setRequestMethod("POST");
343 c.setDoOutput(true);
344 // push post data
345 OutputStream os = c.getOutputStream();
346 os.write(packetData.toString().getBytes("ISO-8859-15"));
347 os.close();
348 os = null;
349 Log.d(TAG, "--HTTP POST--");
350 Log.d(TAG, packetData.toString());
351 Log.d(TAG, "--HTTP POST--");
353 // send data
354 resp = c.getResponseCode();
355 if (resp != HttpURLConnection.HTTP_OK) {
356 if (resp == Utils.HTTP_SERVICE_UNAVAILABLE) {
357 throw new WebSMSException(context, R.string.error_service,
358 "" + resp);
359 } else {
360 throw new WebSMSException(context, R.string.error_http, ""
361 + resp);
364 // read received data
365 int bufsize = c.getHeaderFieldInt("Content-Length", -1);
366 if (bufsize > 0) {
367 String resultString = Utils.stream2str(c.getInputStream());
368 if (resultString.startsWith("The truth")) {
369 // wrong data sent!
370 throw new WebSMSException(context, R.string.error_server,
371 "" + resultString);
373 Log.d(TAG, "--HTTP RESPONSE--");
374 Log.d(TAG, resultString);
375 Log.d(TAG, "--HTTP RESPONSE--");
377 // strip packet
378 int resultIndex = resultString.indexOf("rslt=");
379 String outp = resultString.substring(resultIndex).replace(
380 "\\p", "\n");
381 outp = outp.replace("</WR>", "");
383 // get result code
384 String resultValue = getParam(outp, "rslt");
385 int rslt;
386 try {
387 rslt = Integer.parseInt(resultValue);
388 } catch (Exception e) {
389 Log.e(TAG, null, e);
390 throw new WebSMSException(e.toString());
392 switch (rslt) {
393 case RSLT_OK: // ok
394 // fetch additional info
395 String p = getParam(outp, "free_rem_month");
396 if (p != null) {
397 String b = p;
398 p = getParam(outp, "free_max_month");
399 if (p != null) {
400 b += "/" + p;
402 this.getSpecs(context).setBalance(b);
404 p = getParam(outp, "customer_id");
405 if (p != null) {
406 Editor e = PreferenceManager
407 .getDefaultSharedPreferences(context).edit();
408 e.putString(Preferences.PREFS_USER, p);
409 e.commit();
410 inBootstrap = false;
412 return;
413 case RSLT_WRONG_CUSTOMER: // wrong user/pw
414 throw new WebSMSException(context, R.string.error_pw);
415 case RSLT_WRONG_MAIL: // wrong mail/pw
416 inBootstrap = false;
417 throw new WebSMSException(context, R.string.error_mail);
418 case RSLT_WRONG_SENDER: // wrong sender
419 throw new WebSMSException(context, R.string.error_sender);
420 case RSLT_UNREGISTERED_SENDER: // unregistered sender
421 throw new WebSMSException(context,
422 R.string.error_sender_unregistered);
423 default:
424 throw new WebSMSException(outp + " #" + rslt);
426 } else {
427 throw new WebSMSException(context,
428 R.string.error_http_header_missing);
430 } catch (IOException e) {
431 Log.e(TAG, null, e);
432 throw new WebSMSException(e);