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;
29 private SharedPreferences pref;
30 void setPref(SharedPreferences pref) {
34 SaveTransactionTask(TaskCallback callback) {
35 task_callback = callback;
37 private boolean send_ok() throws IOException {
38 HttpURLConnection http = NetworkUtil.prepare_connection(pref, "add");
39 http.setRequestMethod("POST");
40 http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
41 http.setRequestProperty("Accept", "*/*");
42 if ((session != null) && !session.isEmpty()) {
43 http.setRequestProperty("Cookie", String.format("_SESSION=%s", session));
45 http.setDoOutput(true);
46 http.setDoInput(true);
48 UrlEncodedFormData params = new UrlEncodedFormData();
49 params.add_pair("_formid", "identify-add");
50 if (token != null) params.add_pair("_token", token);
51 params.add_pair("date", ltr.getDate());
52 params.add_pair("description", ltr.getDescription());
54 Iterator<LedgerTransactionItem> items = ltr.getItemsIterator();
55 while (items.hasNext()) {
56 LedgerTransactionItem item = items.next();
57 params.add_pair("account", item.get_account_name());
58 if (item.is_amount_set())
59 params.add_pair("amount", String.format(Locale.US, "%1.2f", item.get_amount()));
60 else params.add_pair("amount", "");
64 String body = params.toString();
65 http.addRequestProperty("Content-Length", String.valueOf(body.length()));
67 Log.d("network", "request header: " + http.getRequestProperties().toString());
69 try (OutputStream req = http.getOutputStream()) {
70 Log.d("network", "Request body: " + body);
71 req.write(body.getBytes("ASCII"));
73 try (InputStream resp = http.getInputStream()) {
74 Log.d("update_accounts", String.valueOf(http.getResponseCode()));
75 if (http.getResponseCode() == 303) {
78 } else if (http.getResponseCode() == 200) {
81 Pattern sess_cookie_re = Pattern.compile("_SESSION=([^;]+);.*");
83 Map<String, List<String>> header = http.getHeaderFields();
84 List<String> cookie_header = header.get("Set-Cookie");
85 if (cookie_header != null) {
86 String cookie = cookie_header.get(0);
87 Matcher m = sess_cookie_re.matcher(cookie);
90 Log.d("network", "new session is " + session);
92 Log.d("network", "set-cookie: " + cookie);
93 Log.w("network", "Response Set-Cookie headers is not a _SESSION one");
96 Log.w("network", "Response has no Set-Cookie header");
99 // the token needs to be updated
100 BufferedReader reader = new BufferedReader(new InputStreamReader(resp));
101 Pattern re = Pattern.compile("<input type=\"hidden\" name=\"_token\" value=\"([^\"]+)\">");
103 while ((line = reader.readLine()) != null) {
104 //Log.d("dump", line);
105 Matcher m = re.matcher(line);
108 Log.d("save-transaction", line);
109 Log.d("save-transaction", "Token=" + token);
110 return false; // retry
113 throw new IOException("Can't find _token string");
115 throw new IOException(String.format("Error response code %d", http.getResponseCode()));
122 protected Void doInBackground(LedgerTransaction... ledgerTransactions) {
123 backend_url = pref.getString("backend_url", "");
124 ltr = ledgerTransactions[0];
127 while (! send_ok() ) {
131 throw new IOException(String.format("aborting after %d tries", tried));
133 } catch (InterruptedException e) {
138 catch (IOException e) {
146 protected void onPostExecute(Void aVoid) {
147 super.onPostExecute(aVoid);
148 task_callback.done();