/*
* Tencent is pleased to support the open source community by making
* Tencent GT (Version 2.4 and subsequent versions) available.
*
* Notwithstanding anything to the contrary herein, any previous version
* of Tencent GT shall not be subject to the license hereunder.
* All right, title, and interest, including all intellectual property rights,
* in and to the previous version of Tencent GT (including any and all copies thereof)
* shall be owned and retained by Tencent and subject to the license under the
* Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html).
*
* Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.wstt.gt.plugin.tcpdump;
import java.net.NetworkInterface;
import java.net.SocketException;
import com.tencent.wstt.gt.R;
import com.tencent.wstt.gt.activity.GTBaseActivity;
import com.tencent.wstt.gt.api.utils.Env;
import com.tencent.wstt.gt.api.utils.NetUtils;
import com.tencent.wstt.gt.api.utils.WidgetUtils;
import com.tencent.wstt.gt.utils.FileUtil;
import com.tencent.wstt.gt.utils.GTUtils;
import com.tencent.wstt.gt.views.GTCheckBox;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class GTCaptureActivity extends GTBaseActivity implements GTCaptureListener {
private EditText et_filename;
private TextView tv_param_title;
private FrameLayout fl_param;
private TextView tv_tcpdump_back;
private GTCheckBox cb_param_switch;
private TextView tv_param_switch;
private Button btn_param_clear;
private EditText et_param;
private TextView tv_switch;
private TextView tv_tcpdump_curFile;
private TextView tv_tcpdump_progress;
private Handler tcpdumpSwitchHandler;
private ProgressDialog proDialog;
private static int count = 1;
private static String foldername;
private static String filename = "Capture";
private static String curFilePath;
private static String curFileSize;
private static final String default_param = "-p -s 0 -vv -w";
private static String param = default_param;
private static boolean initOnCreate = true;
private static boolean switch_param = true;
public static boolean switch_tcpdump = false;
private static boolean cur_param_switch_status = false;
@Override
protected void onDestroy() {
super.onDestroy();
GTCaptureEngine.getInstance().removeListener(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pi_capture);
initLayout();
tv_tcpdump_back = (TextView) findViewById(R.id.tcpdump_back_gt);
tv_tcpdump_back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
tv_tcpdump_curFile.setText(
curFilePath == null ? "" : curFilePath);
tv_tcpdump_progress.setText(
curFileSize == null ? "" : curFileSize + "KB");
tv_param_switch = (TextView) findViewById(R.id.tcpdump_param_switch);
tv_param_switch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!switch_param) {
switch_param = true;
tv_param_title.setVisibility(View.VISIBLE);
fl_param.setVisibility(View.VISIBLE);
} else {
switch_param = false;
et_param.setText(param);
tv_param_title.setVisibility(View.GONE);
fl_param.setVisibility(View.GONE);
}
}
});
btn_param_clear = (Button) findViewById(R.id.tcpdump_param_cancel);
btn_param_clear.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
param = "";
et_param.setText(param);
}
});
et_param = (EditText) findViewById(R.id.tcpdump_param);
et_param.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
return (event.getKeyCode() == KeyEvent.KEYCODE_ENTER);
}
});
tv_switch = (TextView) findViewById(R.id.tcpdump_switch);
tv_switch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 获取权限过程比较耗时,交给菊花去处理
Thread t = new Thread(new ProgressRunnable());
t.start();
}
});
cb_param_switch = (GTCheckBox) findViewById(R.id.cb_param_switch);
cb_param_switch
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
cur_param_switch_status = isChecked;
tv_param_title.setVisibility(View.VISIBLE);
fl_param.setVisibility(View.VISIBLE);
String cur_param = et_param.getText().toString();
if (cur_param.equals("")
|| cur_param.trim().equals("")) {
et_param.setText(default_param);
}
} else {
cur_param_switch_status = isChecked;
tv_param_title.setVisibility(View.GONE);
fl_param.setVisibility(View.GONE);
}
}
});
tcpdumpSwitchHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0: // 启动抓包开始,控件状态置为红色,显示stop
switch_tcpdump = true;
tv_switch.setBackgroundResource(R.drawable.switch_off_border);
tv_switch.setText(getString(R.string.stop));
break;
case 1: // 抓包结束,控件状态置为绿色,显示start
switch_tcpdump = false;
tv_switch.setBackgroundResource(R.drawable.switch_on_border);
tv_switch.setText(getString(R.string.start));
break;
case 2:// 吐槽提示
String message = msg.obj == null ? "" : msg.obj.toString();
WidgetUtils.openToast(message);
// 有菊花则停止菊花
dismissProDialog();
break;
case 3: // 抓包文件发生大小变化时
curFileSize = msg.obj == null ? "" : msg.obj.toString();
tv_tcpdump_progress.setText(curFileSize + "KB");
break;
case 4:// 启动抓包完成,显示当前保存的抓包文件 TODO
curFilePath = msg.obj == null ? "" : msg.obj.toString();
tv_tcpdump_curFile.setText(
curFilePath == null ? "" : curFilePath);
// 停止菊花
dismissProDialog();
break;
case 5:// 抓包之前的校验,转菊花
showProDialog();
break;
}
}
};
GTCaptureEngine.getInstance().addListener(this);
}
private void initLayout() {
et_filename = (EditText) findViewById(R.id.et_tcpdump_filename);
et_filename.setText(filename);
tv_param_title = (TextView) findViewById(R.id.tcpdump_param_title);
fl_param = (FrameLayout) findViewById(R.id.tcpdump_param_layout);
if (initOnCreate) {
initOnCreate = false;
}
tv_tcpdump_curFile = (TextView) findViewById(R.id.tcpdump_curFile);
tv_tcpdump_progress = (TextView) findViewById(R.id.tcpdump_progress);
}
private boolean checkTcpDump() {
Message message = tcpdumpSwitchHandler.obtainMessage();
message.what = 2;
// 获取filename,filename为空弹toast什么都不做
foldername = et_filename.getText().toString();
if (foldername.equals("") || foldername.trim().equals("")) {
message.obj = "foldername cannot be null!";
tcpdumpSwitchHandler.sendMessage(message);
return false;
}
if (foldername.contains("\\") || foldername.contains("/")
|| foldername.contains(":") || foldername.contains("*")
|| foldername.contains("?") || foldername.contains("\"")
|| foldername.contains("<") || foldername.contains(">")
|| foldername.contains("|")) {
message.obj = "foldername can't contain:\\/:*?\"<>|";
tcpdumpSwitchHandler.sendMessage(message);
return false;
}
// 获取param,如果param为空则采用默认给的参数,并把默认给的参数放到UI中显示
param = et_param.getText().toString();
if (param.contains("|") || param.contains(">") || param.contains(">>")) {
message.obj = "param can't contain: | > >>";
tcpdumpSwitchHandler.sendMessage(message);
return false;
}
if (param.trim().equals("")) {
param = default_param;
}
// 先把存储抓包文件的文件夹创建出来
String dir = Env.S_ROOT_TCPDUMP_FOLDER + foldername + "/";
if (GTCaptureEngine.getInstance().getCaptureState()) {
message.obj = "capture has start!";
tcpdumpSwitchHandler.sendMessage(message);
return false;
} else {
// 检查文件夹是否存在
if (!FileUtil.createDir(dir)) {
message.obj = "folder create failed!";
tcpdumpSwitchHandler.sendMessage(message);
return false;
}
// modify on 20150108
filename = "Capture" + GTUtils.getSaveDate();
startTcpDump(dir + filename);
return true;
}
}
// 最后调整实际的文件名和参数
private void startTcpDump(String filePath) {
String realParam = param;
// 如果是wifi,则适配为wlan0,对应小米等手机,其实大部分机型可用网卡名都是wlan0
if (NetUtils.isWifiActive())
{
try {
NetworkInterface network = NetworkInterface.getByName("wlan0");
if (network != null && !param.contains("wlan0")) {
realParam = "-i wlan0 " + param;
}
} catch (SocketException e) {
// nothing should do
}
}
GTCaptureEngine.getInstance().doCapture(
filePath + "_" + String.valueOf(count) + ".pcap", realParam);
}
private void endTcpDump() {
GTCaptureEngine.getInstance().endTcpDump();
count = 1;
}
@Override
protected void onPause() {
super.onPause();
param = et_param.getText().toString();
}
@Override
protected void onResume() {
super.onResume();
// 初始化时,参数开关是关着的
cb_param_switch.setChecked(cur_param_switch_status);
// 文件名保存下来
if (foldername != null) {
et_filename.setText(foldername);
} else {
et_filename.setText(filename);
}
// 维持控件状态
cb_param_switch.setChecked(cur_param_switch_status);
if (cur_param_switch_status) {
tv_param_title.setVisibility(View.VISIBLE);
fl_param.setVisibility(View.VISIBLE);
} else {
tv_param_title.setVisibility(View.GONE);
fl_param.setVisibility(View.GONE);
}
// param保存下来
et_param.setText(param);
// 维持控件状态
if (switch_tcpdump) {
tv_switch.setBackgroundResource(R.drawable.switch_off_border);
tv_switch.setText(getString(R.string.stop));
} else {
tv_switch.setBackgroundResource(R.drawable.switch_on_border);
tv_switch.setText(getString(R.string.start));
}
}
final class ProgressRunnable implements Runnable {
@Override
public void run() {
try {
if (!switch_tcpdump) {
boolean result = checkTcpDump();
if (result) {
tcpdumpSwitchHandler.sendEmptyMessage(0);
} else {
tcpdumpSwitchHandler.sendEmptyMessage(1);
}
} else {
endTcpDump();
tcpdumpSwitchHandler.sendEmptyMessage(1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void dismissProDialog()
{
if (proDialog != null)
{
proDialog.dismiss();
proDialog = null;
}
}
private void showProDialog()
{
if (proDialog == null)
{
proDialog = ProgressDialog.show(GTCaptureActivity.this,
"get root..", "geting root..wait...", true, true);
}
}
@Override
public void preStartCapture() {
tcpdumpSwitchHandler.sendEmptyMessage(5);
}
@Override
public void onStartCaptureBegin() {
tcpdumpSwitchHandler.sendEmptyMessage(0);
}
@Override
public void onStartCaptureEnd(String curFile) {
Message msg = tcpdumpSwitchHandler.obtainMessage();
msg.what = 4;
msg.obj = curFile;
tcpdumpSwitchHandler.sendMessage(msg);
}
@Override
public void onStopCaptureBegin() {
}
@Override
public void onStopCaptureEnd() {
tcpdumpSwitchHandler.sendEmptyMessage(1);
}
@Override
public void onCaptureFail(String errorstr) {
Message msg = tcpdumpSwitchHandler.obtainMessage();
msg.what = 2;
msg.obj = errorstr;
tcpdumpSwitchHandler.sendMessage(msg);
}
@Override
public void onDataChange(long data) {
Message msg = tcpdumpSwitchHandler.obtainMessage();
msg.what = 3;
msg.obj = data;
tcpdumpSwitchHandler.sendMessage(msg);
}
}