mirror of
https://github.com/oxen-io/session-android.git
synced 2025-03-28 16:52:15 +00:00
Make libpaste a source dependency.
This commit is contained in:
parent
1028da116f
commit
b7d83c7a1f
@ -76,9 +76,6 @@ dependencies {
|
|||||||
|
|
||||||
compile 'com.google.android.exoplayer:exoplayer:r2.3.1'
|
compile 'com.google.android.exoplayer:exoplayer:r2.3.1'
|
||||||
|
|
||||||
compile('org.whispersystems:libpastelog:1.1.2') {
|
|
||||||
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
|
|
||||||
}
|
|
||||||
compile 'org.whispersystems:signal-service-android:2.7.6'
|
compile 'org.whispersystems:signal-service-android:2.7.6'
|
||||||
compile 'org.whispersystems:webrtc-android:M68'
|
compile 'org.whispersystems:webrtc-android:M68'
|
||||||
|
|
||||||
@ -172,7 +169,6 @@ dependencyVerification {
|
|||||||
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
|
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
|
||||||
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
|
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
|
||||||
'com.google.android.exoplayer:exoplayer:955085aa611a8f7cf6c61b88ae03d1a392f4ad94c9bfbc153f3dedb9ffb14718',
|
'com.google.android.exoplayer:exoplayer:955085aa611a8f7cf6c61b88ae03d1a392f4ad94c9bfbc153f3dedb9ffb14718',
|
||||||
'org.whispersystems:libpastelog:fe56b4db9ec743c8b565e3e4caa9228fafe132dc0bf82000d6e359b97a81177c',
|
|
||||||
'org.whispersystems:signal-service-android:823eed29e64fb0aa30d2078cb5ec0245e2a0713a4028121329c5c28788ef27f8',
|
'org.whispersystems:signal-service-android:823eed29e64fb0aa30d2078cb5ec0245e2a0713a4028121329c5c28788ef27f8',
|
||||||
'org.whispersystems:webrtc-android:66cb312eb024eaf6aa93e662d37d0c46632e049d47a2dcc9c291207589ee7a43',
|
'org.whispersystems:webrtc-android:66cb312eb024eaf6aa93e662d37d0c46632e049d47a2dcc9c291207589ee7a43',
|
||||||
'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774',
|
'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774',
|
||||||
|
81
res/layout/fragment_submit_log.xml
Normal file
81
res/layout/fragment_submit_log.xml
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ /**
|
||||||
|
~ * Copyright (C) 2014 Whisper Systems
|
||||||
|
~ *
|
||||||
|
~ * 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
~ */
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ScrollView android:id="@+id/log_preview_container"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="2">
|
||||||
|
|
||||||
|
<LinearLayout android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView android:id="@+id/log_submit_confirmation"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:text="@string/log_submit_activity__this_log_will_be_posted_online"
|
||||||
|
android:paddingLeft="15dp"
|
||||||
|
android:paddingRight="15dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:background="@color/logsubmit_confirmation_background"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
tools:ignore="UnusedAttribute"/>
|
||||||
|
|
||||||
|
<EditText android:id="@+id/log_preview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="?android:attr/textViewStyle"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:hint=""
|
||||||
|
android:scrollHorizontally="true"
|
||||||
|
android:inputType="textImeMultiLine|textNoSuggestions|textMultiLine"
|
||||||
|
android:textSize="10sp"
|
||||||
|
tools:ignore="UnusedAttribute,SmallSp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
<Button android:id="@+id/cancel"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/log_submit_activity__button_dont_submit"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
<Button android:id="@+id/ok"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/log_submit_activity__button_submit"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
30
res/layout/share_intent_list.xml
Executable file
30
res/layout/share_intent_list.xml
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ /**
|
||||||
|
~ * Copyright (C) 2014 Whisper Systems
|
||||||
|
~ *
|
||||||
|
~ * 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
~ */
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ListView android:id="@+id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
41
res/layout/share_intent_row.xml
Executable file
41
res/layout/share_intent_row.xml
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ /**
|
||||||
|
~ * Copyright (C) 2014 Whisper Systems
|
||||||
|
~ *
|
||||||
|
~ * 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
~ */
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/share_intent_row"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="68dp"
|
||||||
|
android:baselineAligned="false" >
|
||||||
|
|
||||||
|
<ImageView android:id="@+id/share_intent_image"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="70dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_vertical"/>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/share_intent_label"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:gravity="center_vertical|left"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -60,4 +60,6 @@
|
|||||||
|
|
||||||
<color name="MediaOverview_Media_selected_overlay">#88000000</color>
|
<color name="MediaOverview_Media_selected_overlay">#88000000</color>
|
||||||
|
|
||||||
|
<color name="logsubmit_confirmation_background">#44ff2d00</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -875,6 +875,19 @@
|
|||||||
<string name="log_submit_activity__thanks">Thanks for your help!</string>
|
<string name="log_submit_activity__thanks">Thanks for your help!</string>
|
||||||
<string name="log_submit_activity__submitting">Submitting</string>
|
<string name="log_submit_activity__submitting">Submitting</string>
|
||||||
<string name="log_submit_activity__no_browser_installed">No browser installed</string>
|
<string name="log_submit_activity__no_browser_installed">No browser installed</string>
|
||||||
|
<string name="log_submit_activity__button_dont_submit">Don\'t submit</string>
|
||||||
|
<string name="log_submit_activity__button_submit">Submit</string>
|
||||||
|
<string name="log_submit_activity__button_got_it">Got it</string>
|
||||||
|
<string name="log_submit_activity__button_compose_email">Compose email</string>
|
||||||
|
<string name="log_submit_activity__this_log_will_be_posted_online">This log will be posted publicly online for contributors to view, you may examine and edit it before submitting.</string>
|
||||||
|
<string name="log_submit_activity__loading_logs">Loading logs…</string>
|
||||||
|
<string name="log_submit_activity__uploading_logs">Uploading logs…</string>
|
||||||
|
<string name="log_submit_activity__success">Success!</string>
|
||||||
|
<string name="log_submit_activity__copy_this_url_and_add_it_to_your_issue">Copy this URL and add it to your issue report or support email:\n\n<b>%1$s</b>\n</string>
|
||||||
|
<string name="log_submit_activity__copied_to_clipboard">Copied to clipboard</string>
|
||||||
|
<string name="log_submit_activity__choose_email_app">Choose email app</string>
|
||||||
|
<string name="log_submit_activity__please_review_this_log_from_my_app">Please review this log from my app: %1$s</string>
|
||||||
|
<string name="log_submit_activity__network_failure">Network failure. Please try again.</string>
|
||||||
|
|
||||||
<!-- database_migration_activity -->
|
<!-- database_migration_activity -->
|
||||||
<string name="database_migration_activity__would_you_like_to_import_your_existing_text_messages">Would you like to import your existing text messages into Signal\'s encrypted database?</string>
|
<string name="database_migration_activity__would_you_like_to_import_your_existing_text_messages">Would you like to import your existing text messages into Signal\'s encrypted database?</string>
|
||||||
|
@ -8,8 +8,8 @@ import android.util.Log;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.logsubmit.SubmitLogFragment;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.whispersystems.libpastelog.SubmitLogFragment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity for submitting logcat logs to a pastebin service.
|
* Activity for submitting logcat logs to a pastebin service.
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2014 Open Whisper Systems
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
* /
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.logsubmit;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rhodey
|
||||||
|
*/
|
||||||
|
public class ShareIntentListAdapter extends ArrayAdapter<ResolveInfo> {
|
||||||
|
|
||||||
|
public static ShareIntentListAdapter getAdapterForIntent(Context context, Intent shareIntent) {
|
||||||
|
List<ResolveInfo> activities = context.getPackageManager().queryIntentActivities(shareIntent, 0);
|
||||||
|
return new ShareIntentListAdapter(context, activities.toArray(new ResolveInfo[activities.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareIntentListAdapter(Context context, ResolveInfo[] items) {
|
||||||
|
super(context, R.layout.share_intent_list, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
View rowView = inflater.inflate(R.layout.share_intent_row, parent, false);
|
||||||
|
ImageView intentImage = (ImageView) rowView.findViewById(R.id.share_intent_image);
|
||||||
|
TextView intentLabel = (TextView) rowView.findViewById(R.id.share_intent_label);
|
||||||
|
|
||||||
|
ApplicationInfo intentInfo = getItem(position).activityInfo.applicationInfo;
|
||||||
|
|
||||||
|
intentImage.setImageDrawable(intentInfo.loadIcon(getContext().getPackageManager()));
|
||||||
|
intentLabel.setText(intentInfo.loadLabel(getContext().getPackageManager()));
|
||||||
|
|
||||||
|
return rowView;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
462
src/org/thoughtcrime/securesms/logsubmit/SubmitLogFragment.java
Normal file
462
src/org/thoughtcrime/securesms/logsubmit/SubmitLogFragment.java
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Open Whisper Systems
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.logsubmit;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Build.VERSION;
|
||||||
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.text.ClipboardManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.logsubmit.util.Scrubber;
|
||||||
|
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.MultipartBody;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper {@link Fragment} to preview and submit logcat information to a public pastebin.
|
||||||
|
* Activities that contain this fragment must implement the
|
||||||
|
* {@link SubmitLogFragment.OnLogSubmittedListener} interface
|
||||||
|
* to handle interaction events.
|
||||||
|
* Use the {@link SubmitLogFragment#newInstance} factory method to
|
||||||
|
* create an instance of this fragment.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SubmitLogFragment extends Fragment {
|
||||||
|
private static final String TAG = SubmitLogFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
private EditText logPreview;
|
||||||
|
private Button okButton;
|
||||||
|
private Button cancelButton;
|
||||||
|
private String supportEmailAddress;
|
||||||
|
private String supportEmailSubject;
|
||||||
|
private String hackSavedLogUrl;
|
||||||
|
private boolean emailActivityWasStarted = false;
|
||||||
|
|
||||||
|
private static final String API_ENDPOINT = "https://debuglogs.org";
|
||||||
|
|
||||||
|
private OnLogSubmittedListener mListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this factory method to create a new instance of
|
||||||
|
* this fragment using the provided parameters.
|
||||||
|
*
|
||||||
|
* @return A new instance of fragment SubmitLogFragment.
|
||||||
|
*/
|
||||||
|
public static SubmitLogFragment newInstance(String supportEmailAddress,
|
||||||
|
String supportEmailSubject)
|
||||||
|
{
|
||||||
|
SubmitLogFragment fragment = new SubmitLogFragment();
|
||||||
|
|
||||||
|
fragment.supportEmailAddress = supportEmailAddress;
|
||||||
|
fragment.supportEmailSubject = supportEmailSubject;
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SubmitLogFragment newInstance()
|
||||||
|
{
|
||||||
|
return newInstance(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubmitLogFragment() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
return inflater.inflate(R.layout.fragment_submit_log, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
initializeResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
try {
|
||||||
|
mListener = (OnLogSubmittedListener) activity;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
if (emailActivityWasStarted && mListener != null)
|
||||||
|
mListener.onSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetach() {
|
||||||
|
super.onDetach();
|
||||||
|
mListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeResources() {
|
||||||
|
logPreview = (EditText) getView().findViewById(R.id.log_preview);
|
||||||
|
okButton = (Button ) getView().findViewById(R.id.ok );
|
||||||
|
cancelButton = (Button ) getView().findViewById(R.id.cancel );
|
||||||
|
|
||||||
|
okButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
new SubmitToPastebinAsyncTask(logPreview.getText().toString()).execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cancelButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (mListener != null) mListener.onCancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new PopulateLogcatAsyncTask(getActivity()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String grabLogcat() {
|
||||||
|
try {
|
||||||
|
final Process process = Runtime.getRuntime().exec("logcat -d");
|
||||||
|
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
final StringBuilder log = new StringBuilder();
|
||||||
|
final String separator = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
|
log.append(line);
|
||||||
|
log.append(separator);
|
||||||
|
}
|
||||||
|
return log.toString();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.w(TAG, "IOException when trying to read logcat.", ioe);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent getIntentForSupportEmail(String logUrl) {
|
||||||
|
Intent emailSendIntent = new Intent(Intent.ACTION_SEND);
|
||||||
|
|
||||||
|
emailSendIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { supportEmailAddress });
|
||||||
|
emailSendIntent.putExtra(Intent.EXTRA_SUBJECT, supportEmailSubject);
|
||||||
|
emailSendIntent.putExtra(
|
||||||
|
Intent.EXTRA_TEXT,
|
||||||
|
getString(R.string.log_submit_activity__please_review_this_log_from_my_app, logUrl)
|
||||||
|
);
|
||||||
|
emailSendIntent.setType("message/rfc822");
|
||||||
|
|
||||||
|
return emailSendIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleShowChooserForIntent(final Intent intent, String chooserTitle) {
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
final ShareIntentListAdapter adapter = ShareIntentListAdapter.getAdapterForIntent(getActivity(), intent);
|
||||||
|
|
||||||
|
builder.setTitle(chooserTitle)
|
||||||
|
.setAdapter(adapter, new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
ActivityInfo info = adapter.getItem(which).activityInfo;
|
||||||
|
intent.setClassName(info.packageName, info.name);
|
||||||
|
startActivity(intent);
|
||||||
|
|
||||||
|
emailActivityWasStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel(DialogInterface dialogInterface) {
|
||||||
|
if (hackSavedLogUrl != null)
|
||||||
|
handleShowSuccessDialog(hackSavedLogUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextView handleBuildSuccessTextView(final String logUrl) {
|
||||||
|
TextView showText = new TextView(getActivity());
|
||||||
|
|
||||||
|
showText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
|
||||||
|
showText.setPadding(15, 30, 15, 30);
|
||||||
|
showText.setText(getString(R.string.log_submit_activity__copy_this_url_and_add_it_to_your_issue, logUrl));
|
||||||
|
showText.setAutoLinkMask(Activity.RESULT_OK);
|
||||||
|
showText.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
showText.setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
ClipboardManager manager =
|
||||||
|
(ClipboardManager) getActivity().getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||||
|
manager.setText(logUrl);
|
||||||
|
Toast.makeText(getActivity(),
|
||||||
|
R.string.log_submit_activity__copied_to_clipboard,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Linkify.addLinks(showText, Linkify.WEB_URLS);
|
||||||
|
return showText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleShowSuccessDialog(final String logUrl) {
|
||||||
|
TextView showText = handleBuildSuccessTextView(logUrl);
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
|
||||||
|
builder.setTitle(R.string.log_submit_activity__success)
|
||||||
|
.setView(showText)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setNeutralButton(R.string.log_submit_activity__button_got_it, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
if (mListener != null) mListener.onSuccess();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (supportEmailAddress != null) {
|
||||||
|
builder.setPositiveButton(R.string.log_submit_activity__button_compose_email, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
handleShowChooserForIntent(
|
||||||
|
getIntentForSupportEmail(logUrl),
|
||||||
|
getString(R.string.log_submit_activity__choose_email_app)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.create().show();
|
||||||
|
hackSavedLogUrl = logUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PopulateLogcatAsyncTask extends AsyncTask<Void,Void,String> {
|
||||||
|
private WeakReference<Context> weakContext;
|
||||||
|
|
||||||
|
public PopulateLogcatAsyncTask(Context context) {
|
||||||
|
this.weakContext = new WeakReference<>(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String doInBackground(Void... voids) {
|
||||||
|
Context context = weakContext.get();
|
||||||
|
if (context == null) return null;
|
||||||
|
|
||||||
|
return buildDescription(context) + "\n" + new Scrubber().scrub(grabLogcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
logPreview.setText(R.string.log_submit_activity__loading_logs);
|
||||||
|
okButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(String logcat) {
|
||||||
|
super.onPostExecute(logcat);
|
||||||
|
if (TextUtils.isEmpty(logcat)) {
|
||||||
|
if (mListener != null) mListener.onFailure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logPreview.setText(logcat);
|
||||||
|
okButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SubmitToPastebinAsyncTask extends ProgressDialogAsyncTask<Void,Void,String> {
|
||||||
|
private final String paste;
|
||||||
|
|
||||||
|
public SubmitToPastebinAsyncTask(String paste) {
|
||||||
|
super(getActivity(), R.string.log_submit_activity__submitting, R.string.log_submit_activity__uploading_logs);
|
||||||
|
this.paste = paste;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String doInBackground(Void... voids) {
|
||||||
|
try {
|
||||||
|
OkHttpClient client = new OkHttpClient.Builder().build();
|
||||||
|
Response response = client.newCall(new Request.Builder().url(API_ENDPOINT).get().build()).execute();
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
|
||||||
|
if (!response.isSuccessful() || body == null) {
|
||||||
|
throw new IOException("Unsuccessful response: " + response);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject json = new JSONObject(body.string());
|
||||||
|
String url = json.getString("url");
|
||||||
|
JSONObject fields = json.getJSONObject("fields");
|
||||||
|
String item = fields.getString("key");
|
||||||
|
MultipartBody.Builder post = new MultipartBody.Builder();
|
||||||
|
Iterator<String> keys = fields.keys();
|
||||||
|
|
||||||
|
post.addFormDataPart("Content-Type", "text/plain");
|
||||||
|
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
post.addFormDataPart(key, fields.getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
post.addFormDataPart("file", "file", RequestBody.create(MediaType.parse("text/plain"), paste));
|
||||||
|
|
||||||
|
Response postResponse = client.newCall(new Request.Builder().url(url).post(post.build()).build()).execute();
|
||||||
|
|
||||||
|
if (!postResponse.isSuccessful()) {
|
||||||
|
throw new IOException("Bad response: " + postResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return API_ENDPOINT + "/" + item;
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
Log.w("ImageActivity", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(final String response) {
|
||||||
|
super.onPostExecute(response);
|
||||||
|
|
||||||
|
if (response != null)
|
||||||
|
handleShowSuccessDialog(response);
|
||||||
|
else {
|
||||||
|
Log.w(TAG, "Response was null from Gist API.");
|
||||||
|
Toast.makeText(getActivity(), R.string.log_submit_activity__network_failure, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long asMegs(long bytes) {
|
||||||
|
return bytes / 1048576L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMemoryUsage(Context context) {
|
||||||
|
Runtime info = Runtime.getRuntime();
|
||||||
|
info.totalMemory();
|
||||||
|
return String.format(Locale.ENGLISH, "%dM (%.2f%% free, %dM max)",
|
||||||
|
asMegs(info.totalMemory()),
|
||||||
|
(float)info.freeMemory() / info.totalMemory() * 100f,
|
||||||
|
asMegs(info.maxMemory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(VERSION_CODES.KITKAT)
|
||||||
|
public static String getMemoryClass(Context context) {
|
||||||
|
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
|
String lowMem = "";
|
||||||
|
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) {
|
||||||
|
lowMem = ", low-mem device";
|
||||||
|
}
|
||||||
|
return activityManager.getMemoryClass() + lowMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildDescription(Context context) {
|
||||||
|
final PackageManager pm = context.getPackageManager();
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
|
||||||
|
builder.append("Device : ")
|
||||||
|
.append(Build.MANUFACTURER).append(" ")
|
||||||
|
.append(Build.MODEL).append(" (")
|
||||||
|
.append(Build.PRODUCT).append(")\n");
|
||||||
|
builder.append("Android : ").append(VERSION.RELEASE).append(" (")
|
||||||
|
.append(VERSION.INCREMENTAL).append(", ")
|
||||||
|
.append(Build.DISPLAY).append(")\n");
|
||||||
|
builder.append("Memory : ").append(getMemoryUsage(context)).append("\n");
|
||||||
|
builder.append("Memclass: ").append(getMemoryClass(context)).append("\n");
|
||||||
|
builder.append("OS Host : ").append(Build.HOST).append("\n");
|
||||||
|
builder.append("App : ");
|
||||||
|
try {
|
||||||
|
builder.append(pm.getApplicationLabel(pm.getApplicationInfo(context.getPackageName(), 0)))
|
||||||
|
.append(" ")
|
||||||
|
.append(pm.getPackageInfo(context.getPackageName(), 0).versionName)
|
||||||
|
.append("\n");
|
||||||
|
} catch (PackageManager.NameNotFoundException nnfe) {
|
||||||
|
builder.append("Unknown\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface must be implemented by activities that contain this
|
||||||
|
* fragment to allow an interaction in this fragment to be communicated
|
||||||
|
* to the activity and potentially other fragments contained in that
|
||||||
|
* activity.
|
||||||
|
* <p>
|
||||||
|
* See the Android Training lesson <a href=
|
||||||
|
* "http://developer.android.com/training/basics/fragments/communicating.html"
|
||||||
|
* >Communicating with Other Fragments</a> for more information.
|
||||||
|
*/
|
||||||
|
public interface OnLogSubmittedListener {
|
||||||
|
public void onSuccess();
|
||||||
|
public void onFailure();
|
||||||
|
public void onCancel();
|
||||||
|
}
|
||||||
|
}
|
64
src/org/thoughtcrime/securesms/logsubmit/util/Scrubber.java
Normal file
64
src/org/thoughtcrime/securesms/logsubmit/util/Scrubber.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Open Whisper Systems
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.logsubmit.util;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scrub data for possibly sensitive information
|
||||||
|
*/
|
||||||
|
public class Scrubber {
|
||||||
|
private static final String TAG = Scrubber.class.getSimpleName();
|
||||||
|
private static final Pattern E164_PATTERN = Pattern.compile("\\+\\d{10,15}");
|
||||||
|
|
||||||
|
private static final Pattern[] DEFAULTS = new Pattern[] {
|
||||||
|
E164_PATTERN
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Pattern[] patterns;
|
||||||
|
public Scrubber(Pattern... patterns) {
|
||||||
|
this.patterns = patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scrubber() {
|
||||||
|
this(DEFAULTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String scrub(final String in) {
|
||||||
|
Log.d(TAG, "scrubbing input");
|
||||||
|
String out = in;
|
||||||
|
for (Pattern pattern : patterns) {
|
||||||
|
Matcher matcher = pattern.matcher(out);
|
||||||
|
while (matcher.find()) {
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder(out.substring(0, matcher.start()));
|
||||||
|
final String censored = matcher.group().substring(0,1) +
|
||||||
|
new String(new char[matcher.group().length()-3]).replace("\0", "*") +
|
||||||
|
matcher.group().substring(matcher.group().length()-2);
|
||||||
|
builder.append(censored);
|
||||||
|
builder.append(out.substring(matcher.end()));
|
||||||
|
Log.i(TAG, "replacing a match on /" + pattern.toString() + "/ => " + censored);
|
||||||
|
out = builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user