0
0
mirror of https://github.com/TrianguloY/UrlChecker.git synced 2024-09-19 20:02:16 +02:00

new 'Uri parts' module. Deprecates 'Queries Remover'

resolves #169
This commit is contained in:
TrianguloY 2023-04-15 20:44:31 +02:00
parent 5ea02273c3
commit 230f04b45f
6 changed files with 260 additions and 2 deletions

View File

@ -14,6 +14,7 @@ import com.trianguloy.urlchecker.modules.list.RemoveQueriesModule;
import com.trianguloy.urlchecker.modules.list.StatusModule;
import com.trianguloy.urlchecker.modules.list.TextInputModule;
import com.trianguloy.urlchecker.modules.list.UnshortenModule;
import com.trianguloy.urlchecker.modules.list.UriPartsModule;
import com.trianguloy.urlchecker.modules.list.VirusTotalModule;
import com.trianguloy.urlchecker.utilities.GenericPref;
@ -41,6 +42,7 @@ public class ModuleManager {
modules.add(new VirusTotalModule());
modules.add(new ClearUrlModule());
modules.add(new RemoveQueriesModule());
modules.add(new UriPartsModule());
modules.add(new PatternModule());
modules.add(new HostsModule());
// new modules should preferably be added directly above this line

View File

@ -37,6 +37,11 @@ public class RemoveQueriesModule extends AModuleData {
return R.string.mRemove_name;
}
@Override
public boolean isEnabledByDefault() {
return false;
}
@Override
public AModuleDialog getDialog(MainDialog cntx) {
return new RemoveQueriesDialog(cntx);

View File

@ -0,0 +1,199 @@
package com.trianguloy.urlchecker.modules.list;
import android.net.Uri;
import android.util.Pair;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.activities.ModulesActivity;
import com.trianguloy.urlchecker.dialogs.MainDialog;
import com.trianguloy.urlchecker.modules.AModuleConfig;
import com.trianguloy.urlchecker.modules.AModuleData;
import com.trianguloy.urlchecker.modules.AModuleDialog;
import com.trianguloy.urlchecker.modules.DescriptionConfig;
import com.trianguloy.urlchecker.url.UrlData;
import com.trianguloy.urlchecker.utilities.AndroidUtils;
import com.trianguloy.urlchecker.utilities.Inflater;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* This module shows all parts of the url decoded
*/
public class UriPartsModule extends AModuleData {
@Override
public String getId() {
return "uriparts";
}
@Override
public int getName() {
return R.string.mParts_name;
}
@Override
public AModuleDialog getDialog(MainDialog cntx) {
return new UriPartsDialog(cntx);
}
@Override
public AModuleConfig getConfig(ModulesActivity cntx) {
return new DescriptionConfig(R.string.mParts_desc);
}
}
class UriPartsDialog extends AModuleDialog {
private LinearLayout box;
public UriPartsDialog(MainDialog dialog) {
super(dialog);
}
@Override
public int getLayoutId() {
return R.layout.dialog_parts;
}
@Override
public void onInitialize(View views) {
box = views.findViewById(R.id.box);
}
@Override
public void onDisplayUrl(UrlData urlData) {
// clear
box.removeAllViews();
// parse
var uri = Uri.parse(urlData.url);
// domain elements
if (uri.getAuthority() != null || uri.getScheme() != null) {
var domain = addGroup("Domain", null);
addPart("scheme", uri.getScheme(), domain, null);
addPart("user info", uri.getUserInfo(), domain, null);
addPart("host", uri.getHost(), domain, null);
addPart("port", uri.getPort() != -1 ? String.valueOf(uri.getPort()) : null, domain, null);
}
// paths
var pathSegments = uri.getPathSegments();
if (pathSegments.size() > 0) {
var paths = addGroup("Paths (" + pathSegments.size() + ")", uri.buildUpon().path(null));
for (var i = 0; i < pathSegments.size(); i++) {
var pathSegment = pathSegments.get(i);
var builder = uri.buildUpon();
builder.path(null);
for (int newI = 0; newI < pathSegments.size(); newI++) {
if (newI != i) builder.appendPath(pathSegments.get(newI));
}
addPart("/", pathSegment, paths, builder);
}
}
// queries
var queryParts = getQueryParts(uri);
if (queryParts.size() > 0) {
var queries = addGroup("Queries (" + queryParts.size() + ")", uri.buildUpon().query(null));
for (var queryPart : queryParts) {
var builder = uri.buildUpon();
builder.query(null);
for (var newQuerypart : queryParts) {
if (!Objects.equals(newQuerypart, queryPart))
builder.appendQueryParameter(newQuerypart.first, newQuerypart.second);
}
addPart(queryPart.first, queryPart.second, queries, builder);
}
}
// fragment
if (uri.getFragment() != null) {
var fragment = addGroup("Fragment", uri.buildUpon().fragment(null));
addPart("#", uri.getFragment(), fragment, null);
}
setVisibility(box.getChildCount() > 0);
}
/**
* Adds a collapsible group, removes it
*/
private LinearLayout addGroup(String name, Uri.Builder onDelete) {
var title = Inflater.inflate(R.layout.uri_part, box);
title.findViewById(R.id.key).setVisibility(View.GONE);
var name_view = title.<TextView>findViewById(R.id.value);
name_view.setText(name);
AndroidUtils.setAsClickable(name_view);
var delete_view = title.<Button>findViewById(R.id.delete);
if (onDelete == null) delete_view.setVisibility(View.GONE);
else delete_view.setOnClickListener(v -> setUrl(onDelete.build().toString()));
var group = Inflater.<LinearLayout>inflate(R.layout.dialog_parts, box);
group.setVisibility(View.GONE);
AndroidUtils.toggleableListener(
title,
v -> group.setVisibility(group.getVisibility() == View.GONE ? View.VISIBLE : View.GONE),
v -> AndroidUtils.setStartDrawables(name_view,
group.getVisibility() != View.GONE ? R.drawable.arrow_down : R.drawable.arrow_right
)
);
return group;
}
/**
* Adds a part
*/
private void addPart(String name, String value, LinearLayout container, Uri.Builder onDelete) {
if (value == null) return;
var part = Inflater.inflate(R.layout.uri_part, container);
part.<TextView>findViewById(R.id.key).setText(name);
var value_view = part.<TextView>findViewById(R.id.value);
value_view.setText(value);
AndroidUtils.setAsClickable(value_view);
value_view.setOnClickListener(v -> setUrl(value));
var delete_view = part.<Button>findViewById(R.id.delete);
if (onDelete != null) {
try {
var newUrl = onDelete.build().toString();
delete_view.setOnClickListener(v -> setUrl(newUrl));
} catch (UnsupportedOperationException ignored) {
delete_view.setVisibility(View.GONE);
}
} else {
delete_view.setVisibility(View.GONE);
}
}
/**
* Gets the queries, in order (except for same-name ones)
*/
private List<Pair<String, String>> getQueryParts(Uri uri) {
try {
var queries = new ArrayList<Pair<String, String>>();
for (var name : uri.getQueryParameterNames()) {
for (var value : uri.getQueryParameters(name)) {
queries.add(Pair.create(name, value));
}
}
return queries;
} catch (UnsupportedOperationException e) {
return Collections.emptyList();
}
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
android:id="@+id/box"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="25dp">
<TextView
android:id="@+id/key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingLeft="20dp" />
<TextView
android:id="@+id/value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTint="?android:attr/colorAccent" />
<Button
android:id="@+id/delete"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="40dp"
android:layout_height="match_parent"
android:padding="0dp"
android:scaleType="center"
android:text="X" />
</LinearLayout>

View File

@ -250,9 +250,11 @@ Tap on Intent or UrlData to copy to the clipboard. Hold to copy everything."</st
Note that any modification to the parent object 'providers' will be overwritten if the catalog is updated automatically or manually from the updater dialog. To have personal rules set them in a different parent object (any name)."</string>
<!-- -->
<string name="mRemove_name">Queries Remover</string>
<string name="mRemove_desc">"With this module you can remove queries from the URL.
<string name="mRemove_desc">"[DEPRECATED] With this module you can remove queries from the URL.
Press the button to remove them all or press the arrow to remove one at a time.
Thanks to PabloOQ for the idea and original implementation!"</string>
Thanks to PabloOQ for the idea and original implementation!
This module has been deprecated in favor of the 'Uri parts' module"</string>
<string name="mRemove_found1">1 query found</string>
<string name="mRemove_found">%d queries found</string>
<string name="mRemove_noQueries">No queries</string>
@ -312,5 +314,11 @@ Their api is rate limited to 10 requests per hour for new checks. The module res
\nWith the button below you can edit the default state and the visibility of the flags."</string>
<string name="mFlag_flagHint">Flag name</string>
<string name="mFlag_editFlags">Edit default flag values</string>
<!-- -->
<string name="mParts_name">Uri parts</string>
<string name="mParts_desc">"This module shows all parts of the url decoded: scheme, authority, paths, queries and fragment.
By clicking a part it will be set as the new url, useful for example if one of the queries or paths was an encoded redirection url.
You can also click the 'X' button to remove some of them.
This is an advanced version of the 'Queries Remover' module."</string>
</resources>