2 * Copyright (C) 2010 Felix Bechstein
4 * This file is part of WebSMS.
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
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
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
;
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
;
41 * AsyncTask to manage IO to GMX API.
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";
57 private static final String
[] TARGET_HOST
= { "app0.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";
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;
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
);
92 context
.getString(R
.string
.connector_gmx_author
));
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
);
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
, "") // .
118 connectorSpec
.setReady();
120 connectorSpec
.setStatus(ConnectorSpec
.STATUS_ENABLED
);
123 connectorSpec
.setStatus(ConnectorSpec
.STATUS_INACTIVE
);
125 return connectorSpec
;
132 protected final void doBootstrap(final Context context
, final Intent intent
)
133 throws WebSMSException
{
134 Log
.d(TAG
, "bootstrap");
138 if (!Preferences
.needBootstrap(context
)) {
142 StringBuilder packetData
= openBuffer(context
, "GET_CUSTOMER", "1.10",
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
));
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)));
171 protected final void doSend(final Context context
, final Intent intent
)
172 throws WebSMSException
{
174 this.doBootstrap(context
, intent
);
176 ConnectorCommand command
= new ConnectorCommand(intent
);
177 StringBuilder packetData
= openBuffer(context
, "SEND_SMS", "1.01", true);
179 writePair(packetData
, "sms_text", command
.getText());
180 StringBuilder recipients
= new StringBuilder();
181 // table: <id>, <name>, <number>
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();
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
);
203 writePair(packetData
, "sms_sender", command
.getDefSender());
205 final long sendLater
= command
.getSendLater();
207 writePair(packetData
, "send_date", DateFormat
.format(DATEFORMAT
,
208 sendLater
).toString());
211 this.sendData(context
, closeBuffer(packetData
));
215 * Write key,value to StringBuilder.
224 private static void writePair(final StringBuilder buffer
, final String key
,
225 final String value
) {
228 buffer
.append(value
.replace("\\", "\\\\").replace(">", "\\>").replace(
230 buffer
.append("\\p");
234 * Create default data hashtable.
240 * @param packetVersion
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
);
258 SharedPreferences p
= PreferenceManager
259 .getDefaultSharedPreferences(context
);
260 writePair(ret
, "customer_id", p
.getString(Preferences
.PREFS_USER
,
262 writePair(ret
, "password", p
.getString(Preferences
.PREFS_PASSWORD
,
275 private static StringBuilder
closeBuffer(final StringBuilder buffer
) {
276 buffer
.append("</WR>");
281 * Parse returned packet. Search for name=(.*)\n and return (.*)
287 * @return param's value
289 private static String
getParam(final String packet
, final String name
) {
290 int i
= packet
.indexOf(name
+ '=');
294 int j
= packet
.indexOf("\n", i
);
296 return packet
.substring(i
+ name
.length() + 1);
298 return packet
.substring(i
+ name
.length() + 1, j
);
309 * @return successful?
310 * @throws WebSMSException
313 private void sendData(final Context context
, final StringBuilder packetData
)
314 throws WebSMSException
{
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();
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
) {
330 gmxHost
= (gmxHost
+ 1) % 2;
331 sp
.edit().putInt(Preferences
.PREFS_GMX_HOST
, gmxHost
).commit();
335 c
= (HttpURLConnection
) (new URL("http://" + TARGET_HOST
[gmxHost
]
336 + TARGET_PATH
)).openConnection();
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");
344 OutputStream os
= c
.getOutputStream();
345 os
.write(packetData
.toString().getBytes("ISO-8859-15"));
348 Log
.d(TAG
, "--HTTP POST--");
349 Log
.d(TAG
, packetData
.toString());
350 Log
.d(TAG
, "--HTTP POST--");
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
,
359 throw new WebSMSException(context
, R
.string
.error_http
, ""
363 // read received data
364 int bufsize
= c
.getHeaderFieldInt("Content-Length", -1);
366 String resultString
= Utils
.stream2str(c
.getInputStream());
367 if (resultString
.startsWith("The truth")) {
369 throw new WebSMSException(context
, R
.string
.error_server
,
372 Log
.d(TAG
, "--HTTP RESPONSE--");
373 Log
.d(TAG
, resultString
);
374 Log
.d(TAG
, "--HTTP RESPONSE--");
377 int resultIndex
= resultString
.indexOf("rslt=");
378 String outp
= resultString
.substring(resultIndex
).replace(
380 outp
= outp
.replace("</WR>", "");
383 String resultValue
= getParam(outp
, "rslt");
386 rslt
= Integer
.parseInt(resultValue
);
387 } catch (Exception e
) {
389 throw new WebSMSException(e
.toString());
393 // fetch additional info
394 String p
= getParam(outp
, "free_rem_month");
397 p
= getParam(outp
, "free_max_month");
401 this.getSpecs(context
).setBalance(b
);
403 p
= getParam(outp
, "customer_id");
405 Editor e
= PreferenceManager
406 .getDefaultSharedPreferences(context
).edit();
407 e
.putString(Preferences
.PREFS_USER
, p
);
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
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
);
423 throw new WebSMSException(outp
+ " #" + rslt
);
426 throw new WebSMSException(context
,
427 R
.string
.error_http_header_missing
);
429 } catch (IOException e
) {
431 throw new WebSMSException(e
);