Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

Iv hex encoding #51

Merged
merged 4 commits into from
Oct 20, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/main/java/com/iheartradio/m3u8/ParseUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static <T extends Enum<T>> T parseEnum(String string, Class<T> enumType,
throw ParseException.create(ParseExceptionType.NOT_JAVA_ENUM, tag, string);
}
}

public static String parseDateTime(String string, String tag) throws ParseException {
Matcher matcher = Constants.EXT_X_PROGRAM_DATE_TIME_PATTERN.matcher(string);

Expand All @@ -54,17 +54,20 @@ public static List<Byte> parseHexadecimal(String hexString, String tag) throws P

if (matcher.matches()) {
String valueString = matcher.group(1);
if (valueString.length() % 2 != 0) {
throw ParseException.create(ParseExceptionType.INVALID_HEXADECIMAL_STRING, tag, hexString);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseHexadecimal doesn't know what it's parsing, so it shouldn't assume the length of the string is a multiple of 2. If you want to validate the IV (is the IV required to have an even length?), then that validation probably belongs in PlaylistValidation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since each byte maps to 2 hexadecimal digits it has to be a multiple of 2 - unless you want to assume the last half byte is all zeroes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, let's keep it like you implemented.


for (char c : valueString.toCharArray()) {
bytes.add(hexCharToByte(c));
for (int i = 0; i < valueString.length(); i += 2) {
bytes.add((byte)(Short.parseShort(valueString.substring(i, i+2), 16) & 0xFF));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug description seems to be affecting the writing, not the parsing. Is there a problem with hexCharToByte?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, the issue is 2 hex chars fit within 1 byte. I don't work with low level very often. :( I think I'm okay with this implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed issues with parsing after I created the issue and updated the PR, I can open up another issue if you want

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need, this is fine.

}

return bytes;
} else {
throw ParseException.create(ParseExceptionType.INVALID_HEXADECIMAL_STRING, tag, hexString);
}
}

private static byte hexCharToByte(char hex) {
if (hex >= 'A') {
return (byte) ((hex & 0xF) + 9);
Expand Down Expand Up @@ -183,7 +186,7 @@ public static List<Attribute> parseAttributeList(String line, String tag) throws
//Even Apple playlists have sometimes spaces after a ,
final String name = string.substring(0, separator).trim();
final String value = string.substring(separator + 1);

if (name.isEmpty()) {
throw ParseException.create(ParseExceptionType.MISSING_ATTRIBUTE_NAME, tag, attributes.toString());
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/iheartradio/m3u8/WriteUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static String writeHexadecimal(List<Byte> hex) {
StringBuilder builder = new StringBuilder(hex.size() + prefix.length());
builder.append(prefix);
for(Byte b : hex) {
builder.append(Integer.toHexString(b));
builder.append(String.format("%02x", b));
}
return builder.toString();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2017, Spiideo
*/

package com.iheartradio.m3u8;

import java.util.Arrays;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
* @author Raniz
* @since 02/08/17.
*/
@RunWith(Parameterized.class)
public class ParseUtilParseHexadecimalTest {

@Parameterized.Parameters(name = "{index}: {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{Arrays.asList((byte) 0), "0x00"},
{Arrays.asList((byte) 1), "0x01"},
{Arrays.asList((byte) -1), "0xff"},
{Arrays.asList((byte) -16), "0xf0"},
{Arrays.asList((byte) 0, (byte) 1), "0x0001"},
{Arrays.asList((byte) 1, (byte) 1), "0x0101"},
{Arrays.asList((byte) -1, (byte) -1), "0xffff"},
{Arrays.asList((byte) -121, (byte) -6), "0x87fa"},
{Arrays.asList((byte) 75, (byte) 118), "0x4b76"},
});
}

private final List<Byte> expected;
private final String input;

public ParseUtilParseHexadecimalTest(final List<Byte> expected, final String input) {
this.expected = expected;
this.input = input;
}

@Test
public void parseHexadecimal() throws Exception {
Assert.assertEquals(expected, ParseUtil.parseHexadecimal(input, ""));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2017, Spiideo
*/

package com.iheartradio.m3u8;

import java.util.Arrays;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
* @author Raniz
* @since 02/08/17.
*/
@RunWith(Parameterized.class)
public class WriteUtilWriteHexadecimalTest {

@Parameterized.Parameters(name = "{index}: {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{Arrays.asList((byte) 0), "0x00"},
{Arrays.asList((byte) 1), "0x01"},
{Arrays.asList((byte) -1), "0xff"},
{Arrays.asList((byte) -16), "0xf0"},
{Arrays.asList((byte) 0, (byte) 1), "0x0001"},
{Arrays.asList((byte) 1, (byte) 1), "0x0101"},
{Arrays.asList((byte) -1, (byte) -1), "0xffff"},
{Arrays.asList((byte) -121, (byte) -6), "0x87fa"},
{Arrays.asList((byte) 75, (byte) 118), "0x4b76"},
});
}

private final List<Byte> input;
private final String expected;

public WriteUtilWriteHexadecimalTest(final List<Byte> input, final String expected) {
this.input = input;
this.expected = expected;
}

@Test
public void writeHexadecimal() throws Exception {
Assert.assertEquals(expected, WriteUtil.writeHexadecimal(input));
}

}