Skip to content

Commit

Permalink
Issue #464 submitting apps to exodus
Browse files Browse the repository at this point in the history
  • Loading branch information
yeriomin committed Jun 29, 2018
1 parent dde6948 commit caddf68
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 84 deletions.
Expand Up @@ -23,7 +23,6 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.TrafficStats;
import android.os.Build;
import android.util.Log;
import android.util.LruCache;
Expand Down
Expand Up @@ -28,7 +28,7 @@
import com.github.yeriomin.yalpstore.YalpStoreActivity;
import com.github.yeriomin.yalpstore.fragment.Abstract;
import com.github.yeriomin.yalpstore.model.App;
import com.github.yeriomin.yalpstore.task.ExodusTask;
import com.github.yeriomin.yalpstore.task.ExodusSearchTask;

public class Exodus extends Abstract {

Expand Down Expand Up @@ -58,7 +58,7 @@ public void onClick(View v) {
}

private void runTask() {
new ExodusTask((TextView) activity.findViewById(R.id.exodus), app.getPackageName()).execute();
new ExodusSearchTask((TextView) activity.findViewById(R.id.exodus), app.getPackageName()).execute();
}

public Exodus(YalpStoreActivity activity, App app) {
Expand Down
Expand Up @@ -21,8 +21,6 @@

import android.content.Context;
import android.content.SharedPreferences;
import android.net.TrafficStats;
import android.os.Build;

import com.github.yeriomin.yalpstore.BuildConfig;
import com.github.yeriomin.yalpstore.NetworkUtil;
Expand Down
@@ -0,0 +1,82 @@
/*
* Yalp Store
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package com.github.yeriomin.yalpstore.task;

import android.text.TextUtils;
import android.widget.TextView;

import com.github.yeriomin.yalpstore.R;
import com.github.yeriomin.yalpstore.view.UriOnClickListener;

import java.net.HttpCookie;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class ExodusCsrfTask extends ExodusTask {

static public final String COOKIE_NAME = "csrftoken";
static public final String FORM_FIELD_NAME = "csrfmiddlewaretoken";

private String middlewareToken;
private String cookie;

public ExodusCsrfTask(TextView view, String packageName) {
super(LINK_WEB_FORM, "GET", view, packageName);
}

@Override
protected void onPreExecute() {
super.onPreExecute();
updateTextView(null, R.string.details_exodus_submitting);
}

@Override
protected String doInBackground(String... strings) {
String result = super.doInBackground(strings);
for (HttpCookie cookie : HttpCookie.parse(connection.getHeaderField("Set-Cookie"))) {
if (cookie.getName().equalsIgnoreCase(COOKIE_NAME)) {
this.cookie = cookie.getValue();
}
}
middlewareToken = getMiddlewareToken(result);
return result;
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (!TextUtils.isEmpty(cookie) && !TextUtils.isEmpty(middlewareToken)) {
ExodusSubmitTask task = new ExodusSubmitTask(viewRef.get(), packageName);
task.setCookie(cookie);
task.setMiddlewareToken(middlewareToken);
task.execute();
} else {
updateTextView(new UriOnClickListener(viewRef.get().getContext(), LINK_WEB_FORM), R.string.submit);
}
}

private String getMiddlewareToken(String page) {
Matcher matcher = Pattern.compile("<input type='hidden' name='" + FORM_FIELD_NAME + "' value='(.*?)' />").matcher(page);
if (matcher.find()) {
return matcher.group(1);
}
return "";
}
}
@@ -0,0 +1,108 @@
/*
* Yalp Store
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package com.github.yeriomin.yalpstore.task;

import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.github.yeriomin.yalpstore.R;
import com.github.yeriomin.yalpstore.view.UriOnClickListener;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ExodusSearchTask extends ExodusTask {

static private final String LINK_API = BASE_URL + "/api/search/";

private int trackers;
private int reportId;

public ExodusSearchTask(TextView view, String packageName) {
super(LINK_API + packageName, "GET", view, packageName);
}

@Override
protected void onPreExecute() {
super.onPreExecute();
updateTextView(null, R.string.details_exodus_searching);
}

@Override
protected String doInBackground(String... strings) {
if (null == viewRef.get()) {
return null;
}
addHeader("Content-Type", "application/json");
addHeader("Accept", "application/json");
addHeader("Authorization", "Token " + viewRef.get().getContext().getString(R.string.exodus_api_key));
String result = super.doInBackground(strings);
if (TextUtils.isEmpty(result)) {
return result;
}
try {
JSONObject jsonObject = new JSONObject(result);
if (!jsonObject.has(packageName)) {
return result;
}
JSONObject response = jsonObject.getJSONObject(packageName);
if (!response.has("reports") || response.getJSONArray("reports").length() == 0) {
return result;
}
JSONArray reports = response.getJSONArray("reports");
JSONObject latestReport = null;
for (int i = 0; i < reports.length(); i++) {
JSONObject report = reports.getJSONObject(i);
if (null == latestReport || latestReport.getInt("version_code") < report.getInt("version_code")) {
latestReport = report;
}
}
trackers = latestReport.getJSONArray("trackers").length();
reportId = latestReport.getInt("id");
} catch (JSONException e) {
Log.e(getClass().getSimpleName(), "Could not parse JSON for " + packageName + " : " + e.getMessage());
}
return result;
}

@Override
protected void onPostExecute(String s) {
if (null == viewRef.get()) {
return;
}
super.onPostExecute(s);
if (reportId > 0) {
updateTextView(new UriOnClickListener(viewRef.get().getContext(), LINK_WEB_REPORT + reportId + "/"), R.string.details_exodus_found, trackers);
} else {
updateTextView(
new View.OnClickListener() {
@Override
public void onClick(View v) {
new ExodusCsrfTask((TextView) v, packageName).execute();
}
},
R.string.details_exodus_view
);
}
}
}
@@ -0,0 +1,84 @@
/*
* Yalp Store
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package com.github.yeriomin.yalpstore.task;

import android.text.TextUtils;
import android.widget.TextView;

import com.github.yeriomin.yalpstore.R;
import com.github.yeriomin.yalpstore.view.UriOnClickListener;

public class ExodusSubmitTask extends ExodusTask {

static private final String REDIRECT_LOCATION_PREFIX = "/analysis/";
static private final String LINK_ANALYSIS = BASE_URL + REDIRECT_LOCATION_PREFIX;

private String cookie;
private String middlewareToken;
private int reportId;

public void setCookie(String cookie) {
this.cookie = cookie;
}

public void setMiddlewareToken(String middlewareToken) {
this.middlewareToken = middlewareToken;
}

public ExodusSubmitTask(TextView view, String packageName) {
super(LINK_WEB_FORM, "POST", view, packageName);
}

@Override
protected void onPreExecute() {
super.onPreExecute();
updateTextView(null, R.string.details_exodus_submitting);
}

@Override
protected String doInBackground(String... strings) {
connection.setInstanceFollowRedirects(false);
addHeader("Referer", LINK_WEB_FORM);
addHeader("Cookie", ExodusCsrfTask.COOKIE_NAME + "=" + cookie);
addFormField(ExodusCsrfTask.FORM_FIELD_NAME, middlewareToken);
addFormField("handle", packageName);
String result = super.doInBackground(strings);
String location = connection.getHeaderField("location");
if (returnCode == 302 && !TextUtils.isEmpty(location) && location.startsWith(REDIRECT_LOCATION_PREFIX)) {
reportId = Integer.parseInt(location.substring(REDIRECT_LOCATION_PREFIX.length()));
}
return result;
}

@Override
protected void onPostExecute(String s) {
if (null == viewRef.get()) {
return;
}
super.onPostExecute(s);
if (reportId > 0) {
UriOnClickListener listener = new UriOnClickListener(viewRef.get().getContext(), LINK_ANALYSIS + reportId);
updateTextView(listener, R.string.details_exodus_view);
listener.onClick(viewRef.get());
} else {
updateTextView(new UriOnClickListener(viewRef.get().getContext(), LINK_WEB_FORM), R.string.submit);
}
}
}

0 comments on commit caddf68

Please sign in to comment.