Merge "Redact ISOBMFF boxes with 'free'" into qt-dev
am: f68a201ebc
Change-Id: I4755c6f884958dce01e06aa5a889f06e035f1f1c
This commit is contained in:
@@ -35,7 +35,7 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Variant of {@link FileDescriptor} that allows its creator to specify regions
|
* Variant of {@link FileDescriptor} that allows its creator to specify regions
|
||||||
* that should be redacted (appearing as zeros to the reader).
|
* that should be redacted.
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -44,13 +44,16 @@ public class RedactingFileDescriptor {
|
|||||||
private static final boolean DEBUG = true;
|
private static final boolean DEBUG = true;
|
||||||
|
|
||||||
private volatile long[] mRedactRanges;
|
private volatile long[] mRedactRanges;
|
||||||
|
private volatile long[] mFreeOffsets;
|
||||||
|
|
||||||
private FileDescriptor mInner = null;
|
private FileDescriptor mInner = null;
|
||||||
private ParcelFileDescriptor mOuter = null;
|
private ParcelFileDescriptor mOuter = null;
|
||||||
|
|
||||||
private RedactingFileDescriptor(Context context, File file, int mode, long[] redactRanges)
|
private RedactingFileDescriptor(
|
||||||
|
Context context, File file, int mode, long[] redactRanges, long[] freeOffsets)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
mRedactRanges = checkRangesArgument(redactRanges);
|
mRedactRanges = checkRangesArgument(redactRanges);
|
||||||
|
mFreeOffsets = freeOffsets;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
@@ -88,13 +91,17 @@ public class RedactingFileDescriptor {
|
|||||||
*
|
*
|
||||||
* @param file The underlying file to open.
|
* @param file The underlying file to open.
|
||||||
* @param mode The {@link ParcelFileDescriptor} mode to open with.
|
* @param mode The {@link ParcelFileDescriptor} mode to open with.
|
||||||
* @param redactRanges List of file offsets that should be redacted, stored
|
* @param redactRanges List of file ranges that should be redacted, stored
|
||||||
* as {@code [start1, end1, start2, end2, ...]}. Start values are
|
* as {@code [start1, end1, start2, end2, ...]}. Start values are
|
||||||
* inclusive and end values are exclusive.
|
* inclusive and end values are exclusive.
|
||||||
|
* @param freePositions List of file offsets at which the four byte value 'free' should be
|
||||||
|
* written instead of zeros within parts of the file covered by {@code redactRanges}.
|
||||||
|
* Non-redacted bytes will not be modified even if covered by a 'free'. This is
|
||||||
|
* useful for overwriting boxes in ISOBMFF files with padding data.
|
||||||
*/
|
*/
|
||||||
public static ParcelFileDescriptor open(Context context, File file, int mode,
|
public static ParcelFileDescriptor open(Context context, File file, int mode,
|
||||||
long[] redactRanges) throws IOException {
|
long[] redactRanges, long[] freePositions) throws IOException {
|
||||||
return new RedactingFileDescriptor(context, file, mode, redactRanges).mOuter;
|
return new RedactingFileDescriptor(context, file, mode, redactRanges, freePositions).mOuter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,6 +176,15 @@ public class RedactingFileDescriptor {
|
|||||||
for (long j = start; j < end; j++) {
|
for (long j = start; j < end; j++) {
|
||||||
data[(int) (j - offset)] = 0;
|
data[(int) (j - offset)] = 0;
|
||||||
}
|
}
|
||||||
|
// Overwrite data at 'free' offsets within the redaction ranges.
|
||||||
|
for (long freeOffset : mFreeOffsets) {
|
||||||
|
final long freeEnd = freeOffset + 4;
|
||||||
|
final long redactFreeStart = Math.max(freeOffset, start);
|
||||||
|
final long redactFreeEnd = Math.min(freeEnd, end);
|
||||||
|
for (long j = redactFreeStart; j < redactFreeEnd; j++) {
|
||||||
|
data[(int) (j - offset)] = (byte) "free".charAt((int) (j - freeOffset));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class RedactingFileDescriptorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSingleByte() throws Exception {
|
public void testSingleByte() throws Exception {
|
||||||
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
|
||||||
new long[] { 10, 11 }).getFileDescriptor();
|
new long[] { 10, 11 }, new long[] {}).getFileDescriptor();
|
||||||
|
|
||||||
final byte[] buf = new byte[1_000];
|
final byte[] buf = new byte[1_000];
|
||||||
assertEquals(buf.length, Os.read(fd, buf, 0, buf.length));
|
assertEquals(buf.length, Os.read(fd, buf, 0, buf.length));
|
||||||
@@ -80,7 +80,7 @@ public class RedactingFileDescriptorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRanges() throws Exception {
|
public void testRanges() throws Exception {
|
||||||
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
|
||||||
new long[] { 100, 200, 300, 400 }).getFileDescriptor();
|
new long[] { 100, 200, 300, 400 }, new long[] {}).getFileDescriptor();
|
||||||
|
|
||||||
final byte[] buf = new byte[10];
|
final byte[] buf = new byte[10];
|
||||||
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 90));
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 90));
|
||||||
@@ -102,7 +102,7 @@ public class RedactingFileDescriptorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEntireFile() throws Exception {
|
public void testEntireFile() throws Exception {
|
||||||
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
|
||||||
new long[] { 0, 5_000_000 }).getFileDescriptor();
|
new long[] { 0, 5_000_000 }, new long[] {}).getFileDescriptor();
|
||||||
|
|
||||||
try (FileInputStream in = new FileInputStream(fd)) {
|
try (FileInputStream in = new FileInputStream(fd)) {
|
||||||
int val;
|
int val;
|
||||||
@@ -115,7 +115,7 @@ public class RedactingFileDescriptorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadWrite() throws Exception {
|
public void testReadWrite() throws Exception {
|
||||||
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
new long[] { 100, 200, 300, 400 }).getFileDescriptor();
|
new long[] { 100, 200, 300, 400 }, new long[] {}).getFileDescriptor();
|
||||||
|
|
||||||
// Redacted at first
|
// Redacted at first
|
||||||
final byte[] buf = new byte[10];
|
final byte[] buf = new byte[10];
|
||||||
@@ -168,4 +168,76 @@ public class RedactingFileDescriptorTest {
|
|||||||
assertArrayEquals(new long[] { 100, 200 },
|
assertArrayEquals(new long[] { 100, 200 },
|
||||||
removeRange(new long[] { 100, 200 }, 150, 150));
|
removeRange(new long[] { 100, 200 }, 150, 150));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeAtStart() throws Exception {
|
||||||
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
|
new long[] { 1, 10 }, new long[] {1}).getFileDescriptor();
|
||||||
|
|
||||||
|
final byte[] buf = new byte[10];
|
||||||
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
|
||||||
|
assertArrayEquals(
|
||||||
|
new byte[] { 64, (byte) 'f', (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0, 0, 0 },
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeAtOffset() throws Exception {
|
||||||
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
|
new long[] { 1, 10 }, new long[] {3}).getFileDescriptor();
|
||||||
|
|
||||||
|
final byte[] buf = new byte[10];
|
||||||
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
|
||||||
|
assertArrayEquals(
|
||||||
|
new byte[] { 64, 0, 0, (byte) 'f', (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0 },
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeAcrossRedactionStart() throws Exception {
|
||||||
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
|
new long[] { 1, 10 }, new long[] {0}).getFileDescriptor();
|
||||||
|
|
||||||
|
final byte[] buf = new byte[10];
|
||||||
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
|
||||||
|
assertArrayEquals(
|
||||||
|
new byte[] { 64, (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0, 0, 0, 0 },
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeAcrossRedactionEnd() throws Exception {
|
||||||
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
|
new long[] { 1, 3 }, new long[] {2}).getFileDescriptor();
|
||||||
|
|
||||||
|
final byte[] buf = new byte[10];
|
||||||
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
|
||||||
|
assertArrayEquals(
|
||||||
|
new byte[] { 64, 0, (byte) 'f', 64, 64, 64, 64, 64, 64, 64 },
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeOutsideRedaction() throws Exception {
|
||||||
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
|
new long[] { 1, 8 }, new long[] { 8 }).getFileDescriptor();
|
||||||
|
|
||||||
|
final byte[] buf = new byte[10];
|
||||||
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
|
||||||
|
assertArrayEquals(
|
||||||
|
new byte[] { 64, 0, 0, 0, 0, 0, 0, 0, 64, 64 },
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeMultipleRedactions() throws Exception {
|
||||||
|
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
|
||||||
|
new long[] { 1, 2, 3, 4 }, new long[] { 0 }).getFileDescriptor();
|
||||||
|
|
||||||
|
final byte[] buf = new byte[10];
|
||||||
|
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
|
||||||
|
assertArrayEquals(
|
||||||
|
new byte[] { 64, (byte) 'r', 64, (byte) 'e', 64, 64, 64, 64, 64, 64 },
|
||||||
|
buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user