mirror of
https://github.com/revanced/jadb.git
synced 2025-04-30 06:34:39 +02:00
Merge pull request #112 from phantamanta44/master
Allow multi-byte characters in payload
This commit is contained in:
commit
4546c0583f
@ -19,8 +19,9 @@ public class SyncTransport {
|
|||||||
public void send(String syncCommand, String name) throws IOException {
|
public void send(String syncCommand, String name) throws IOException {
|
||||||
if (syncCommand.length() != 4) throw new IllegalArgumentException("sync commands must have length 4");
|
if (syncCommand.length() != 4) throw new IllegalArgumentException("sync commands must have length 4");
|
||||||
output.writeBytes(syncCommand);
|
output.writeBytes(syncCommand);
|
||||||
output.writeInt(Integer.reverseBytes(name.length()));
|
byte[] data = name.getBytes(StandardCharsets.UTF_8);
|
||||||
output.writeBytes(name);
|
output.writeInt(Integer.reverseBytes(data.length));
|
||||||
|
output.write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendStatus(String statusCode, int length) throws IOException {
|
public void sendStatus(String statusCode, int length) throws IOException {
|
||||||
@ -50,6 +51,21 @@ public class SyncTransport {
|
|||||||
return new String(buffer, StandardCharsets.UTF_8);
|
return new String(buffer, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendDirectoryEntry(RemoteFile file) throws IOException {
|
||||||
|
output.writeBytes("DENT");
|
||||||
|
output.writeInt(Integer.reverseBytes(0666 | (file.isDirectory() ? (1 << 14) : 0)));
|
||||||
|
output.writeInt(Integer.reverseBytes(file.getSize()));
|
||||||
|
output.writeInt(Integer.reverseBytes(Long.valueOf(file.getLastModified()).intValue()));
|
||||||
|
byte[] pathChars = file.getPath().getBytes(StandardCharsets.UTF_8);
|
||||||
|
output.writeInt(Integer.reverseBytes(pathChars.length));
|
||||||
|
output.write(pathChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDirectoryEntryDone() throws IOException {
|
||||||
|
output.writeBytes("DONE");
|
||||||
|
output.writeBytes("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); // equivalent to the length of a "normal" dent
|
||||||
|
}
|
||||||
|
|
||||||
public RemoteFileRecord readDirectoryEntry() throws IOException {
|
public RemoteFileRecord readDirectoryEntry() throws IOException {
|
||||||
String id = readString(4);
|
String id = readString(4);
|
||||||
int mode = readInt();
|
int mode = readInt();
|
||||||
|
@ -7,6 +7,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by vidstige on 20/03/14.
|
* Created by vidstige on 20/03/14.
|
||||||
@ -19,4 +20,6 @@ public interface AdbDeviceResponder {
|
|||||||
void filePulled(RemoteFile path, ByteArrayOutputStream buffer) throws JadbException, IOException;
|
void filePulled(RemoteFile path, ByteArrayOutputStream buffer) throws JadbException, IOException;
|
||||||
|
|
||||||
void shell(String command, DataOutputStream stdout, DataInput stdin) throws IOException;
|
void shell(String command, DataOutputStream stdout, DataInput stdin) throws IOException;
|
||||||
|
|
||||||
|
List<RemoteFile> list(String path) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -175,6 +175,8 @@ class AdbProtocolHandler implements Runnable {
|
|||||||
syncSend(output, input, length);
|
syncSend(output, input, length);
|
||||||
} else if ("RECV".equals(id)) {
|
} else if ("RECV".equals(id)) {
|
||||||
syncRecv(output, input, length);
|
syncRecv(output, input, length);
|
||||||
|
} else if ("LIST".equals(id)) {
|
||||||
|
syncList(output, input, length);
|
||||||
} else throw new JadbException("Unknown sync id " + id);
|
} else throw new JadbException("Unknown sync id " + id);
|
||||||
} catch (JadbException e) { // sync response with a different type of fail message
|
} catch (JadbException e) { // sync response with a different type of fail message
|
||||||
SyncTransport sync = getSyncTransport(output, input);
|
SyncTransport sync = getSyncTransport(output, input);
|
||||||
@ -207,6 +209,15 @@ class AdbProtocolHandler implements Runnable {
|
|||||||
transport.sendStatus("OKAY", 0); // 0 = ignored
|
transport.sendStatus("OKAY", 0); // 0 = ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncList(DataOutput output, DataInput input, int length) throws IOException, JadbException {
|
||||||
|
String remotePath = readString(input, length);
|
||||||
|
SyncTransport transport = getSyncTransport(output, input);
|
||||||
|
for (RemoteFile file : selected.list(remotePath)) {
|
||||||
|
transport.sendDirectoryEntry(file);
|
||||||
|
}
|
||||||
|
transport.sendDirectoryEntryDone();
|
||||||
|
}
|
||||||
|
|
||||||
private String getCommandLength(String command) {
|
private String getCommandLength(String command) {
|
||||||
return String.format("%04x", command.length());
|
return String.format("%04x", command.length());
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import java.io.IOException;
|
|||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +87,10 @@ public class FakeAdbServer implements AdbResponder {
|
|||||||
return findBySerial(serial).expectShell(commands);
|
return findBySerial(serial).expectShell(commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeviceResponder.ListExpectation expectList(String serial, String remotePath) {
|
||||||
|
return findBySerial(serial).expectList(remotePath);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AdbDeviceResponder> getDevices() {
|
public List<AdbDeviceResponder> getDevices() {
|
||||||
return new ArrayList<AdbDeviceResponder>(devices);
|
return new ArrayList<AdbDeviceResponder>(devices);
|
||||||
@ -96,6 +101,7 @@ public class FakeAdbServer implements AdbResponder {
|
|||||||
private final String type;
|
private final String type;
|
||||||
private List<FileExpectation> fileExpectations = new ArrayList<>();
|
private List<FileExpectation> fileExpectations = new ArrayList<>();
|
||||||
private List<ShellExpectation> shellExpectations = new ArrayList<>();
|
private List<ShellExpectation> shellExpectations = new ArrayList<>();
|
||||||
|
private List<ListExpectation> listExpectations = new ArrayList<>();
|
||||||
|
|
||||||
private DeviceResponder(String serial, String type) {
|
private DeviceResponder(String serial, String type) {
|
||||||
this.serial = serial;
|
this.serial = serial;
|
||||||
@ -150,9 +156,21 @@ public class FakeAdbServer implements AdbResponder {
|
|||||||
throw new ProtocolException("Unexpected shell to device " + serial + ": " + command);
|
throw new ProtocolException("Unexpected shell to device " + serial + ": " + command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RemoteFile> list(String path) throws IOException {
|
||||||
|
for (ListExpectation le : listExpectations) {
|
||||||
|
if (le.matches(path)) {
|
||||||
|
listExpectations.remove(le);
|
||||||
|
return le.getFiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ProtocolException("Unexpected list of device " + serial + " in dir " + path);
|
||||||
|
}
|
||||||
|
|
||||||
public void verifyExpectations() {
|
public void verifyExpectations() {
|
||||||
org.junit.Assert.assertEquals(0, fileExpectations.size());
|
org.junit.Assert.assertEquals(0, fileExpectations.size());
|
||||||
org.junit.Assert.assertEquals(0, shellExpectations.size());
|
org.junit.Assert.assertEquals(0, shellExpectations.size());
|
||||||
|
org.junit.Assert.assertEquals(0, listExpectations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FileExpectation implements ExpectationBuilder {
|
private static class FileExpectation implements ExpectationBuilder {
|
||||||
@ -161,7 +179,6 @@ public class FakeAdbServer implements AdbResponder {
|
|||||||
private String failMessage;
|
private String failMessage;
|
||||||
|
|
||||||
public FileExpectation(RemoteFile path) {
|
public FileExpectation(RemoteFile path) {
|
||||||
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
content = null;
|
content = null;
|
||||||
failMessage = null;
|
failMessage = null;
|
||||||
@ -220,6 +237,62 @@ public class FakeAdbServer implements AdbResponder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ListExpectation {
|
||||||
|
|
||||||
|
private final String remotePath;
|
||||||
|
private final List<RemoteFile> files = new ArrayList<>();
|
||||||
|
|
||||||
|
public ListExpectation(String remotePath) {
|
||||||
|
this.remotePath = remotePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(String remotePath) {
|
||||||
|
return remotePath.equals(this.remotePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListExpectation withFile(String path, int size, long modifyTime) {
|
||||||
|
files.add(new MockFileEntry(path, size, modifyTime, false));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListExpectation withDir(String path, long modifyTime) {
|
||||||
|
files.add(new MockFileEntry(path, -1, modifyTime, true));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RemoteFile> getFiles() {
|
||||||
|
return Collections.unmodifiableList(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MockFileEntry extends RemoteFile {
|
||||||
|
|
||||||
|
private final int size;
|
||||||
|
private final long modifyTime;
|
||||||
|
private final boolean dir;
|
||||||
|
|
||||||
|
MockFileEntry(String path, int size, long modifyTime, boolean dir) {
|
||||||
|
super(path);
|
||||||
|
this.size = size;
|
||||||
|
this.modifyTime = modifyTime;
|
||||||
|
this.dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastModified() {
|
||||||
|
return modifyTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDirectory() {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public ExpectationBuilder expectPush(RemoteFile path) {
|
public ExpectationBuilder expectPush(RemoteFile path) {
|
||||||
FileExpectation expectation = new FileExpectation(path);
|
FileExpectation expectation = new FileExpectation(path);
|
||||||
fileExpectations.add(expectation);
|
fileExpectations.add(expectation);
|
||||||
@ -237,5 +310,11 @@ public class FakeAdbServer implements AdbResponder {
|
|||||||
shellExpectations.add(expectation);
|
shellExpectations.add(expectation);
|
||||||
return expectation;
|
return expectation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ListExpectation expectList(String remotePath) {
|
||||||
|
ListExpectation expectation = new ListExpectation(remotePath);
|
||||||
|
listExpectations.add(expectation);
|
||||||
|
return expectation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MockedTestCases {
|
public class MockedTestCases {
|
||||||
@ -117,8 +118,59 @@ public class MockedTestCases {
|
|||||||
device.executeShell("echo", "newline2\r\nstring");
|
device.executeShell("echo", "newline2\r\nstring");
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseDate(String date) throws ParseException {
|
@Test
|
||||||
|
public void testFileList() throws Exception {
|
||||||
|
server.add("serial-123");
|
||||||
|
server.expectList("serial-123", "/sdcard/Documents")
|
||||||
|
.withDir("school", 123456789L)
|
||||||
|
.withDir("finances", 7070707L)
|
||||||
|
.withDir("\u904A\u6232", 528491L)
|
||||||
|
.withFile("user_manual.pdf", 3000, 648649L)
|
||||||
|
.withFile("effective java vol. 7.epub", 0xCAFE, 0xBABEL)
|
||||||
|
.withFile("\uB9AC\uADF8 \uC624\uBE0C \uB808\uC804\uB4DC", 240, 9001L);
|
||||||
|
JadbDevice device = connection.getDevices().get(0);
|
||||||
|
List<RemoteFile> files = device.list("/sdcard/Documents");
|
||||||
|
Assert.assertEquals(6, files.size());
|
||||||
|
assertHasDir("school", 123456789L, files);
|
||||||
|
assertHasDir("finances", 7070707L, files);
|
||||||
|
assertHasDir("\u904A\u6232", 528491L, files);
|
||||||
|
assertHasFile("user_manual.pdf", 3000, 648649L, files);
|
||||||
|
assertHasFile("effective java vol. 7.epub", 0xCAFE, 0xBABEL, files);
|
||||||
|
assertHasFile("\uB9AC\uADF8 \uC624\uBE0C \uB808\uC804\uB4DC", 240, 9001L, files);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long parseDate(String date) throws ParseException {
|
||||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
return dateFormat.parse(date).getTime();
|
return dateFormat.parse(date).getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void assertHasFile(String expPath, int expSize, long expModifyTime, List<RemoteFile> actualFiles) {
|
||||||
|
for (RemoteFile file : actualFiles) {
|
||||||
|
if (expPath.equals(file.getPath())) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
Assert.fail("File " + expPath + " was listed as a dir!");
|
||||||
|
} else if (expSize != file.getSize() || expModifyTime != file.getLastModified()) {
|
||||||
|
Assert.fail("File " + expPath + " exists but has incorrect properties!");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.fail("File " + expPath + " could not be found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertHasDir(String expPath, long expModifyTime, List<RemoteFile> actualFiles) {
|
||||||
|
for (RemoteFile file : actualFiles) {
|
||||||
|
if (expPath.equals(file.getPath())) {
|
||||||
|
if (!file.isDirectory()) {
|
||||||
|
Assert.fail("Dir " + expPath + " was listed as a file!");
|
||||||
|
} else if (expModifyTime != file.getLastModified()) {
|
||||||
|
Assert.fail("Dir " + expPath + " exists but has incorrect properties!");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.fail("Dir " + expPath + " could not be found!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user