View Javadoc
1   package edu.jiangxin.apktoolbox.reverse;
2   
3   import edu.jiangxin.apktoolbox.swing.extend.listener.SelectDirectoryListener;
4   import edu.jiangxin.apktoolbox.swing.extend.plugin.PluginPanel;
5   import edu.jiangxin.apktoolbox.utils.Constants;
6   import edu.jiangxin.apktoolbox.utils.ProcessLogOutputStream;
7   import org.apache.commons.exec.CommandLine;
8   import org.apache.commons.exec.DefaultExecutor;
9   import org.apache.commons.exec.PumpStreamHandler;
10  import org.apache.commons.io.IOUtils;
11  import org.apache.logging.log4j.Level;
12  
13  import javax.swing.*;
14  import java.awt.*;
15  import java.awt.event.ActionEvent;
16  import java.awt.event.ActionListener;
17  import java.io.*;
18  import java.util.Enumeration;
19  import java.util.zip.ZipEntry;
20  import java.util.zip.ZipFile;
21  
22  /**
23   * @author jiangxin
24   * @author 2019-04-12
25   *
26   */
27  public class AxmlPrinterPanel extends PluginPanel {
28      private static final long serialVersionUID = 1L;
29  
30      private JTextField srcTextField;
31  
32      private JTextField targetTextField;
33  
34      public AxmlPrinterPanel() throws HeadlessException {
35          super();
36      }
37  
38      @Override
39      public String getPluginFilename() {
40          return "AXMLPrinter3.jar";
41      }
42  
43      @Override
44      public void initUI() {
45          BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
46          setLayout(boxLayout);
47  
48          createSrcPanel();
49          add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
50  
51          createTargetPanel();
52          add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
53  
54          createOperationPanel();
55      }
56  
57      private void createOperationPanel() {
58          JPanel operationPanel = new JPanel();
59          operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
60          add(operationPanel);
61  
62          JButton getFileButton = new JButton("Get File");
63          getFileButton.addActionListener(new GetFileButtonActionListener());
64  
65          operationPanel.add(getFileButton);
66      }
67  
68      private void createTargetPanel() {
69          JPanel targetPanel = new JPanel();
70          targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.X_AXIS));
71          add(targetPanel);
72  
73          targetTextField = new JTextField();
74          targetTextField.setText(conf.getString("axmlprinter.target.dir"));
75  
76          JButton targetButton = new JButton("Save Dir");
77          targetButton.addActionListener(new SelectDirectoryListener("Save To", targetTextField));
78  
79          targetPanel.add(targetTextField);
80          targetPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
81          targetPanel.add(targetButton);
82      }
83  
84      private void createSrcPanel() {
85          JPanel srcPanel = new JPanel();
86          srcPanel.setLayout(new BoxLayout(srcPanel, BoxLayout.X_AXIS));
87          add(srcPanel);
88  
89          srcTextField = new JTextField();
90          srcTextField.setText(conf.getString("axmlprinter.src.file"));
91  
92          JButton srcButton = new JButton("Source File");
93          srcButton.addActionListener(new SrcButtonActionListener());
94  
95          srcPanel.add(srcTextField);
96          srcPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
97          srcPanel.add(srcButton);
98      }
99  
100     private final class SrcButtonActionListener implements ActionListener {
101         @Override
102         public void actionPerformed(ActionEvent e) {
103             JFileChooser jfc = new JFileChooser();
104             jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
105             jfc.setDialogTitle("select a file");
106             int ret = jfc.showDialog(new JLabel(), null);
107             switch (ret) {
108                 case JFileChooser.APPROVE_OPTION:
109                     File file = jfc.getSelectedFile();
110                     srcTextField.setText(file.getAbsolutePath());
111                     break;
112                 default:
113                     break;
114             }
115 
116         }
117     }
118 
119     private final class GetFileButtonActionListener implements ActionListener {
120         @Override
121         public void actionPerformed(ActionEvent e) {
122             String srcPath = checkAndGetFileContent(srcTextField, "axmlprinter.src.file", "Source file is invalid");
123             if (srcPath == null) {
124                 return;
125             }
126 
127             String targetPath = checkAndGetDirContent(targetTextField, "axmlprinter.target.dir", "Target dir is invalid");
128             if (targetPath == null) {
129                 return;
130             }
131 
132             try (ZipFile zip = new ZipFile(srcPath)) {
133                 Enumeration<?> entries = zip.entries();
134                 while (entries.hasMoreElements()) {
135                     ZipEntry entry = (ZipEntry) entries.nextElement();
136                     if ("AndroidManifest.xml".equals(entry.getName())) {
137                         try (InputStream inputStream = zip.getInputStream(entry);
138                              OutputStream outputSteam = new FileOutputStream(new File(targetPath, "AndroidManifest.xml.orig"))) {
139                             IOUtils.copy(inputStream,outputSteam);
140                         } catch (IOException e2) {
141                             logger.error("axmlprinter fail", e2);
142                         }
143                         break;
144                     }
145                 }
146 
147                 StringBuilder sb = new StringBuilder();
148                 sb.append(getPluginStartupCmd()).append(" ").append(new File(targetPath, "AndroidManifest.xml.orig").getCanonicalPath());
149                 String cmd = sb.toString();
150                 logger.info(cmd);
151                 File outputFile = new File(new File(targetPath), "AndroidManifest.xml");
152                 try (FileOutputStream outStream = new FileOutputStream(outputFile);
153                      ProcessLogOutputStream errStream = new ProcessLogOutputStream(logger, Level.ERROR)
154                 ) {
155                     CommandLine commandLine = CommandLine.parse(cmd);
156                     DefaultExecutor exec = new DefaultExecutor();
157                     PumpStreamHandler streamHandler = new PumpStreamHandler(outStream, errStream);
158                     exec.setStreamHandler(streamHandler);
159                     int exitValue = exec.execute(commandLine);
160                     logger.info("exitValue: [" + exitValue + "]");
161                 }
162             } catch (IOException e1) {
163                 logger.error("axmlprinter fail", e1);
164             }
165         }
166     }
167 }