1 package net.ktnx.mobileledger;
3 import android.content.SharedPreferences;
4 import android.os.AsyncTask;
5 import android.util.Log;
7 import java.io.BufferedReader;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.InputStreamReader;
11 import java.io.OutputStream;
12 import java.net.HttpURLConnection;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Locale;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import static java.lang.Thread.sleep;
22 class SaveTransactionTask extends AsyncTask<LedgerTransaction, Void, Void> {
23 private final TaskCallback task_callback;
25 private String session;
26 private String backend_url;
27 private LedgerTransaction ltr;
28 protected String error;
30 private SharedPreferences pref;
31 void setPref(SharedPreferences pref) {
35 SaveTransactionTask(TaskCallback callback) {
36 task_callback = callback;
38 private boolean send_ok() throws IOException {
39 HttpURLConnection http = NetworkUtil.prepare_connection(pref, "add");
40 http.setRequestMethod("POST");
41 http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
42 http.setRequestProperty("Accept", "*/*");
43 if ((session != null) && !session.isEmpty()) {
44 http.setRequestProperty("Cookie", String.format("_SESSION=%s", session));
46 http.setDoOutput(true);
47 http.setDoInput(true);
49 UrlEncodedFormData params = new UrlEncodedFormData();
50 params.add_pair("_formid", "identify-add");
51 if (token != null) params.add_pair("_token", token);
52 params.add_pair("date", ltr.getDate());
53 params.add_pair("description", ltr.getDescription());
55 Iterator<LedgerTransactionItem> items = ltr.getItemsIterator();
56 while (items.hasNext()) {
57 LedgerTransactionItem item = items.next();
58 params.add_pair("account", item.get_account_name());
59 if (item.is_amount_set())
60 params.add_pair("amount", String.format(Locale.US, "%1.2f", item.get_amount()));
61 else params.add_pair("amount", "");
65 String body = params.toString();
66 http.addRequestProperty("Content-Length", String.valueOf(body.length()));
68 Log.d("network", "request header: " + http.getRequestProperties().toString());
70 try (OutputStream req = http.getOutputStream()) {
71 Log.d("network", "Request body: " + body);
72 req.write(body.getBytes("ASCII"));
74 try (InputStream resp = http.getInputStream()) {
75 Log.d("update_accounts", String.valueOf(http.getResponseCode()));
76 if (http.getResponseCode() == 303) {
79 } else if (http.getResponseCode() == 200) {
82 Pattern sess_cookie_re = Pattern.compile("_SESSION=([^;]+);.*");
84 Map<String, List<String>> header = http.getHeaderFields();
85 List<String> cookie_header = header.get("Set-Cookie");
86 if (cookie_header != null) {
87 String cookie = cookie_header.get(0);
88 Matcher m = sess_cookie_re.matcher(cookie);
91 Log.d("network", "new session is " + session);
93 Log.d("network", "set-cookie: " + cookie);
94 Log.w("network", "Response Set-Cookie headers is not a _SESSION one");
97 Log.w("network", "Response has no Set-Cookie header");
100 // the token needs to be updated
101 BufferedReader reader = new BufferedReader(new InputStreamReader(resp));
102 Pattern re = Pattern.compile("<input type=\"hidden\" name=\"_token\" value=\"([^\"]+)\">");
104 while ((line = reader.readLine()) != null) {
105 //Log.d("dump", line);
106 Matcher m = re.matcher(line);
109 Log.d("save-transaction", line);
110 Log.d("save-transaction", "Token=" + token);
111 return false; // retry
114 throw new IOException("Can't find _token string");
116 throw new IOException(String.format("Error response code %d", http.getResponseCode()));
123 protected Void doInBackground(LedgerTransaction... ledgerTransactions) {
126 backend_url = pref.getString("backend_url", "");
127 ltr = ledgerTransactions[0];
134 throw new IOException(String.format("aborting after %d tries", tried));
137 catch (InterruptedException e) {
142 catch (Exception e) {
144 error = e.getMessage();
151 protected void onPostExecute(Void aVoid) {
152 super.onPostExecute(aVoid);
153 task_callback.done(error);