Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .github/workflows/embARC_Checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ jobs:
- name: embARC-maj
run: |
# Don't use git clone because it's fail on Windows due to invalid path (.metadata/.plugins/org.eclipse.core.runtime/.settings/org.springframework.ide.eclipse.boot.dash:Cloud Foundry.prefs')
Invoke-WebRequest -Uri "https://github.com/PortalMedia/embARC-maj/archive/refs/heads/master.zip" -OutFile "embARC-maj.zip"
Expand-Archive -Path "embARC-maj.zip" -DestinationPath "."
Invoke-WebRequest -Uri "https://github.com/MediaArea/embARC-maj/archive/refs/heads/master.zip" -OutFile "embARC-maj.zip"
& 7z.exe x embARC-maj.zip
Rename-Item -Path "embARC-maj-master" -NewName "embARC-maj"
- name: Compile
run: |
Expand Down
2 changes: 1 addition & 1 deletion src/main/com/portalmedia/embarc/cli/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ private static void printAS07CoreDMS(MXFMetadata data) {

private static void printCoreProperty(HashMap<MXFColumn, MetadataColumnDef> coreData, MXFColumn col, String label) {
String value = "";
if (coreData.containsKey(col)) {
if (coreData.containsKey(col) && coreData.get(col).getCurrentValue() != null) {
value = coreData.get(col).getCurrentValue();
}
System.out.format("%-35s%-1s\n", label, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,11 @@ private void createIdentifiersDisplay(MXFSelectedFilesSummary summary, MXFColumn
});
iconHbox.setAccessibleRole(AccessibleRole.BUTTON);
iconHbox.setAccessibleText("Open modal with Identifiers specification.");
if (col.isRequired() && identifiers.size() == 0) {
final FontIcon warningIcon = new FontIcon(FontAwesomeSolid.EXCLAMATION_CIRCLE);
warningIcon.getStyleClass().add("fadgi-sr-warning");
labelIconHbox.getChildren().add(warningIcon);
}
hbox.getChildren().addAll(labelIconHbox);

labelIconHbox.setPrefWidth(285.0);
Expand Down
83 changes: 83 additions & 0 deletions src/main/com/portalmedia/embarc/parser/mxf/DelimitedListCodec.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.portalmedia.embarc.parser.mxf;

import java.util.ArrayList;
import java.util.List;

/**
* Shared escaping/splitting logic for IdentifierSetHelper and DeviceSetHelper, which both encode a
* list of records as fields joined by a run of 4 commas, records joined by a run of 4 slashes. A
* field value containing a run of 4 (or more) of the delimiter character used to be indistinguishable
* from the delimiter itself, corrupting the split. Every backslash, comma, and slash in a raw field
* value is now backslash-escaped before joining, so an unescaped run of the delimiter character can
* only be a real delimiter -- single, unescaped commas/slashes (i.e. anything shorter than the 4-char
* run) are left untouched on read for compatibility with files written before this escaping existed.
*/
final class DelimitedListCodec {
private DelimitedListCodec() {}

static String escapeField(String value) {
if (value == null) return "";
StringBuilder sb = new StringBuilder(value.length());
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '\\' || c == ',' || c == '/') sb.append('\\');
sb.append(c);
}
return sb.toString();
}

private static boolean isEscapable(char c) {
return c == '\\' || c == ',' || c == '/';
}

static String unescapeField(String value) {
StringBuilder sb = new StringBuilder(value.length());
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '\\' && i + 1 < value.length() && isEscapable(value.charAt(i + 1))) {
sb.append(value.charAt(++i));
} else {
sb.append(c);
}
}
return sb.toString();
}

/**
* Splits on runs of exactly `runLength` (or more) unescaped occurrences of `delimiter`.
* Backslash-escaped characters are skipped over (not unescaped here) so this can be applied at
* the record level (slash) and then again at the field level (comma) on each resulting piece,
* with a single final {@link #unescapeField} pass on each leaf field. A backslash NOT followed
* by one of the escapable characters is not an escape sequence (e.g. a raw "C:\path" typed
* directly into a CSV cell): leave it as an ordinary character rather than swallowing it, so
* pre-existing, un-escaped text with incidental backslashes doesn't silently lose them.
*/
static List<String> splitOnDelimiterRun(String value, char delimiter, int runLength) {
List<String> parts = new ArrayList<String>();
int start = 0;
int i = 0;
int length = value.length();
while (i < length) {
char c = value.charAt(i);
if (c == '\\' && i + 1 < length && isEscapable(value.charAt(i + 1))) {
i += 2;
continue;
}
if (c == delimiter) {
int runEnd = i;
while (runEnd < length && value.charAt(runEnd) == delimiter) runEnd++;
if (runEnd - i >= runLength) {
parts.add(value.substring(start, i));
i += runLength;
start = i;
continue;
}
i = runEnd;
continue;
}
i++;
}
parts.add(value.substring(start));
return parts;
}
}
20 changes: 11 additions & 9 deletions src/main/com/portalmedia/embarc/parser/mxf/DeviceSetHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ public class DeviceSetHelper {

public ArrayList<AS07CoreDMSDeviceObjectsImpl> createDeviceListFromString(String values) {
ArrayList<AS07CoreDMSDeviceObjectsImpl> devices = new ArrayList<AS07CoreDMSDeviceObjectsImpl>();
String[] valList = values.split(slash);
List<String> valList = DelimitedListCodec.splitOnDelimiterRun(values, slash.charAt(0), slash.length());
for (String v : valList) {
if (v != "") devices.add(createDeviceFromString(v));
if (!v.isEmpty()) devices.add(createDeviceFromString(v));
}
return devices;
}

public AS07CoreDMSDeviceObjectsImpl createDeviceFromString(String values) {
String[] valList = values.split(comma);
List<String> valList = DelimitedListCodec.splitOnDelimiterRun(values, comma.charAt(0), comma.length());
AS07CoreDMSDeviceObjectsImpl device = new AS07CoreDMSDeviceObjectsImpl();
if(valList.length>0) device.setDeviceType(valList[0]);
if(valList.length>1) device.setManufacturer(valList[1]);
if(valList.length>2) device.setModel(valList[2]);
if(valList.length>3) device.setSerialNumber(valList[3]);
if(valList.length>4) device.setUsageDescription(valList[4]);
if(valList.size()>0) device.setDeviceType(DelimitedListCodec.unescapeField(valList.get(0)));
if(valList.size()>1) device.setManufacturer(DelimitedListCodec.unescapeField(valList.get(1)));
if(valList.size()>2) device.setModel(DelimitedListCodec.unescapeField(valList.get(2)));
if(valList.size()>3) device.setSerialNumber(DelimitedListCodec.unescapeField(valList.get(3)));
if(valList.size()>4) device.setUsageDescription(DelimitedListCodec.unescapeField(valList.get(4)));
return device;
}

Expand Down Expand Up @@ -69,6 +69,8 @@ public String deviceToString(AS07CoreDMSDeviceObjectsImpl device) {
usage = device.getUsageDescription();
} catch(PropertyNotPresentException pex) {}

return type + comma + manu + comma + model + comma + serial + comma + usage;
return DelimitedListCodec.escapeField(type) + comma + DelimitedListCodec.escapeField(manu) + comma
+ DelimitedListCodec.escapeField(model) + comma + DelimitedListCodec.escapeField(serial) + comma
+ DelimitedListCodec.escapeField(usage);
}
}
27 changes: 13 additions & 14 deletions src/main/com/portalmedia/embarc/parser/mxf/IdentifierSetHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ public class IdentifierSetHelper {

public ArrayList<AS07DMSIdentifierSetImpl> createIdentifierListFromString(String values) {
ArrayList<AS07DMSIdentifierSetImpl> idents = new ArrayList<AS07DMSIdentifierSetImpl>();
String[] valList = values.split(slash);
List<String> valList = DelimitedListCodec.splitOnDelimiterRun(values, slash.charAt(0), slash.length());
for (String v : valList) {
if (v != "") idents.add(createIdentifierFromString(v));
if (!v.isEmpty()) idents.add(createIdentifierFromString(v));
}
return idents;
}

public AS07DMSIdentifierSetImpl createIdentifierFromString(String values) {
String[] valList = values.split(comma);
List<String> valList = DelimitedListCodec.splitOnDelimiterRun(values, comma.charAt(0), comma.length());
AS07DMSIdentifierSetImpl ident = new AS07DMSIdentifierSetImpl();
if (valList.length > 0) ident.setIdentifierValue(valList[0]);
if (valList.length > 1) ident.setIdentifierRole(valList[1]);
if (valList.length > 2) ident.setIdentifierType(valList[2]);
if (valList.length > 3) ident.setIdentifierComment(valList[3]);
if (valList.size() > 0) ident.setIdentifierValue(DelimitedListCodec.unescapeField(valList.get(0)));
if (valList.size() > 1) ident.setIdentifierRole(DelimitedListCodec.unescapeField(valList.get(1)));
if (valList.size() > 2) ident.setIdentifierType(DelimitedListCodec.unescapeField(valList.get(2)));
if (valList.size() > 3) ident.setIdentifierComment(DelimitedListCodec.unescapeField(valList.get(3)));
return ident;
}

Expand All @@ -47,13 +47,12 @@ public String identifierToString(AS07DMSIdentifierSetImpl id) {
String type = null;
String comm = null;

try {
val = id.getIdentifierValue();
role = id.getIdentifierRole();
type = id.getIdentifierType();
comm = id.getIdentifierComment();
} catch (PropertyNotPresentException ex) {}
try { val = id.getIdentifierValue(); } catch (PropertyNotPresentException ex) {}
try { role = id.getIdentifierRole(); } catch (PropertyNotPresentException ex) {}
try { type = id.getIdentifierType(); } catch (PropertyNotPresentException ex) {}
try { comm = id.getIdentifierComment(); } catch (PropertyNotPresentException ex) {}

return val + comma + role + comma + type + comma + comm;
return DelimitedListCodec.escapeField(val) + comma + DelimitedListCodec.escapeField(role) + comma
+ DelimitedListCodec.escapeField(type) + comma + DelimitedListCodec.escapeField(comm);
}
}
Loading
Loading