From 5df3cad93f5ccb2ced128693720d5df712ae7df3 Mon Sep 17 00:00:00 2001 From: M66B Date: Tue, 3 Oct 2023 16:11:42 +0200 Subject: [PATCH] Improved rule URL action --- .../java/eu/faircode/email/EntityRule.java | 34 +++++++++++++++++-- .../java/eu/faircode/email/FragmentRule.java | 26 ++++++++++++++ app/src/main/res/layout/fragment_rule.xml | 25 ++++++++++++-- app/src/main/res/values/strings.xml | 10 +++++- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index 678efbf0be..9e3c9b14f9 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -43,14 +43,15 @@ import androidx.room.PrimaryKey; import org.json.JSONException; import org.json.JSONObject; +import org.jsoup.HttpStatusException; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.text.DateFormat; @@ -1401,6 +1402,10 @@ public class EntityRule { private boolean onActionUrl(Context context, EntityMessage message, JSONObject jargs, String html) throws JSONException, IOException { String url = jargs.getString("url"); + String method = jargs.optString("method"); + + if (TextUtils.isEmpty(method)) + method = "GET"; InternetAddress iaddr = (message.from == null || message.from.length == 0 @@ -1418,18 +1423,41 @@ public class EntityRule { url = url.replace("$" + EXTRA_SUBJECT + "$", Uri.encode(message.subject == null ? "" : message.subject)); url = url.replace("$" + EXTRA_RECEIVED + "$", Uri.encode(DTF.format(message.received))); + String body = null; + if ("POST".equals(method) || "PUT".equals(method)) { + Uri u = Uri.parse(url); + body = u.getQuery(); + url = u.buildUpon().clearQuery().build().toString(); + } + Log.i("GET " + url); HttpURLConnection connection = null; try { connection = (HttpURLConnection) new URL(url).openConnection(); - connection.setRequestMethod("GET"); - connection.setDoOutput(false); + connection.setRequestMethod(method); + connection.setDoOutput(body != null); connection.setReadTimeout(URL_TIMEOUT); connection.setConnectTimeout(URL_TIMEOUT); connection.setInstanceFollowRedirects(true); ConnectionHelper.setUserAgent(context, connection); connection.connect(); + + if (body != null) + connection.getOutputStream().write(body.getBytes()); + + int status = connection.getResponseCode(); + if (status < 200 || status > 299) { + String error = "Error " + status + ": " + connection.getResponseMessage(); + try { + InputStream is = connection.getErrorStream(); + if (is != null) + error += "\n" + Helper.readStream(is); + } catch (Throwable ex) { + Log.w(ex); + } + throw new HttpStatusException(error, status, url); + } } finally { if (connection != null) connection.disconnect(); diff --git a/app/src/main/java/eu/faircode/email/FragmentRule.java b/app/src/main/java/eu/faircode/email/FragmentRule.java index 6968bbc876..60449ee6e7 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRule.java +++ b/app/src/main/java/eu/faircode/email/FragmentRule.java @@ -172,7 +172,9 @@ public class FragmentRule extends FragmentBase { private EditText etNotes; private ViewButtonColor btnColorNotes; + private Spinner spUrlMethod; private EditText etUrl; + private TextView tvUrlHint; private BottomNavigationView bottom_navigation; private ContentLoadingProgressBar pbWait; @@ -365,7 +367,9 @@ public class FragmentRule extends FragmentBase { etNotes = view.findViewById(R.id.etNotes); btnColorNotes = view.findViewById(R.id.btnColorNotes); + spUrlMethod = view.findViewById(R.id.spUrlMethod); etUrl = view.findViewById(R.id.etUrl); + tvUrlHint = view.findViewById(R.id.tvUrlHint); bottom_navigation = view.findViewById(R.id.bottom_navigation); @@ -820,6 +824,15 @@ public class FragmentRule extends FragmentBase { } }); + tvUrlHint.setText(getString(R.string.title_rule_url_hint, + TextUtils.join(", ", new String[]{ + "$" + EntityRule.EXTRA_RULE + "$", + "$" + EntityRule.EXTRA_SENDER + "$", + "$" + EntityRule.EXTRA_NAME + "$", + "$" + EntityRule.EXTRA_SUBJECT + "$", + "$" + EntityRule.EXTRA_RECEIVED + "$", + }))); + bottom_navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { @@ -1369,6 +1382,13 @@ public class FragmentRule extends FragmentBase { case EntityRule.TYPE_URL: etUrl.setText(jaction.getString("url")); + String method = jaction.optString("method"); + if (TextUtils.isEmpty(method)) + method = "GET"; + int pos = Arrays.asList(getResources().getStringArray(R.array.httpMethodNames)) + .indexOf(method); + if (pos >= 0) + spUrlMethod.setSelection(pos); break; } @@ -1779,6 +1799,12 @@ public class FragmentRule extends FragmentBase { case EntityRule.TYPE_URL: jaction.put("url", etUrl.getText().toString().trim()); + int pos = spUrlMethod.getSelectedItemPosition(); + String[] methods = getResources().getStringArray(R.array.httpMethodNames); + if (pos >= 0 && pos < methods.length) + jaction.put("method", methods[pos]); + else + jaction.put("method", "GET"); break; } } diff --git a/app/src/main/res/layout/fragment_rule.xml b/app/src/main/res/layout/fragment_rule.xml index 743b1e8ca6..2c93f2d64b 100644 --- a/app/src/main/res/layout/fragment_rule.xml +++ b/app/src/main/res/layout/fragment_rule.xml @@ -1291,6 +1291,16 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btnColorNotes" /> + + + app:layout_constraintTop_toBottomOf="@id/spUrlMethod" /> + + + app:constraint_referenced_ids="tvUrl,spUrlMethod,etUrl,tvUrlHint" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 65951ba48e..afc6b80844 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1982,9 +1982,10 @@ Keyword missing This will send the intent \'%1$s\' with the extras \'%2$s\' Local notes missing - URL missing or invalid + URL missing or invalid Permanent deletion is irreversible, so make sure the rule conditions are correct! Try to avoid bridging notifications to other devices, such as smartwatches. Not all devices support this. + You can use the following placeholders: %1$s Edit group … Execute now @@ -2744,6 +2745,13 @@ Mobile + + GET + HEAD + POST + PUT + + 17BA15C1AF55D925F98B99CEA4375D4CDF4C174B 77CD40058858DC3A38523E01C227A39AA019F88B 200D0AA43A8ADBC7BB8237023C1553F4753CA7D2