Skip to content

Commit

Permalink
modification to code to comply with FXP parsing options (#368)
Browse files Browse the repository at this point in the history
Signed-off-by: George M Dias <[email protected]>
  • Loading branch information
georgedias authored Jan 27, 2025
1 parent 5731c24 commit bd4dd2c
Show file tree
Hide file tree
Showing 15 changed files with 32,382 additions and 30,047 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mitre/inspec-objects",
"version": "2.0.0",
"version": "2.0.1",
"description": "Typescript objects for normalizing between InSpec profiles and XCCDF benchmarks",
"main": "lib/index.js",
"publishConfig": {
Expand Down
4 changes: 2 additions & 2 deletions src/parsers/oval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ export function processOVAL(oval?: string): Record<string, OvalDefinitionValue>
return undefined
}

const parsed: Oval = convertEncodedXmlIntoJson(oval)

const parsed: Oval = convertEncodedXmlIntoJson(oval, 'withArrayNoEntitiesOption')
const extractedDefinitions: Record<string, OvalDefinitionValue & { criteriaRefs?: string[]; resolvedValues?: any }> = {}

for (const ovalDefinitions of parsed.oval_definitions) {
Expand Down
185 changes: 140 additions & 45 deletions src/parsers/xccdf.ts

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/types/xccdf.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export interface FrontMatter {
'html:code'?: HTMLEmElement[];
'html:a'?: HTMLA[];
'@_override'?: string;
'@_id'?: string;
}

export enum Category {
Expand Down Expand Up @@ -207,6 +208,7 @@ export interface HTMLAElement {

export interface RationaleElement {
'#text'?: string;
'p'?: string;
'@_xmlns:xhtml': string;
'@_xml:lang': XMLLang;
'html:br'?: HTMLBr[];
Expand Down
4 changes: 2 additions & 2 deletions src/utilities/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export function diffProfile(
fromControlIDs,
toControlIDs
)?.filter((item: string) => !(item.length === 1 && item[0] === ' '));

// Contains the new IDs
const changedControlIds: string[] = [];

Expand Down Expand Up @@ -177,7 +177,7 @@ export function diffProfile(
} else {
logger.error(`Unable to find existing control ${diffValue[1]}`);
}
} else if (diffValue[0] === '+' && !changedControlIds.includes(diffValue[1].toString().toLowerCase()) && diffValue[1]) {
} else if (diffValue[0] === '+' && !changedControlIds.includes(diffValue[1].toLowerCase()) && diffValue[1]) {
logger.info(JSON.stringify(diffValue))
logger.info(JSON.stringify(changedControlIds))
profileDiff.addedControlIDs.push(diffValue[1]);
Expand Down
4 changes: 2 additions & 2 deletions src/utilities/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@ export function getExistingDescribeFromControl(control: Control): string {
export function findUpdatedControlByAllIdentifiers(existingControl: Control, updatedControls: Control[]): Control | undefined {
// Try to match based on IDs
let updatedControl = updatedControls.find((updatedControl) => {
return updatedControl.id[0].toLowerCase() === existingControl.id[0].toLowerCase()
return updatedControl.id.toLowerCase() === existingControl.id.toLowerCase()
})

if (updatedControl) {
return updatedControl
}
Expand Down
96 changes: 80 additions & 16 deletions src/utilities/xccdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,91 @@ import {DecodedDescription} from '../types/xccdf'
import he from 'he'

/**
* Converts an encoded XML string into a JSON object.
* Converts an encoded XML string into a JSON object using specified
* parsing options.
*
* @param encodedXml - The encoded XML string to be converted.
* @param encodedXml - The encoded XML string to be converted.
* @param xmlParserOption - The parsing option to be used. Defaults to
* 'withArrayOption'.
* Possible values are:
* - 'withArrayOption': Parses XML with array option enabled.
* - 'withArrayNoEntitiesOption': Parses XML with array option
* enabled and processes entities.
* - Any other value: Parses XML without array option.
* @returns The JSON representation of the XML string.
*
* @remarks
* This function uses the `fast-xml-parser` library to parse the XML string.
* The parser options are configured to:
* - Not ignore attributes.
* - Prevent the parser from converting XML entities (converting &lt into <)
* - Ignore attributes, allow or disallows attributes to be parsed
* - Remove namespace prefixes.
* - Prefix attribute names with '@_'.
* - Stop parsing at 'div' and 'p' nodes.
* - Treat all nodes as arrays.
* - Stop parsing 'div' and 'p' tags.
* - Treat all nodes as arrays or not
*
* Options being used for the XML parser (V4) are:
* - processEntities: true or false (based on xmlParserOption)
* - ignoreAttributes: false (allow attributes to be parsed)
* - removeNSPrefix: true (remove namespace prefixes)
* - attributeNamePrefix: '@_' (prefix all attribute names with @_)
* - stopNodes: ["*.pre", "*.p"]
* - isArray(): true or false (based on xmlParserOption)
*
* NOTE: The isArray can specify what tags to always convert into an array, we
* do not specify specific fields as it could break parsing if future
* fields are added, we parse all fields as an array.
*
* For more details on the parser options, see the documentation for the v4 or v5 version of the library:
* {@link https://github.com/NaturalIntelligence/fast-xml-parser/tree/master/docs/v4}
*/
export function convertEncodedXmlIntoJson(
encodedXml: string
): any {
const options = {
/**
* Converts an encoded XML string into a JSON object using specified parsing options.
*
* @param encodedXml - The encoded XML string to be converted.
* @param xmlParserOption - The parsing option to be used. Defaults to 'withArrayOption'.
* Possible values are:
* - 'withArrayOption': Parses XML with array option enabled.
* - 'withArrayNoEntitiesOption': Parses XML with array option enabled and processes entities.
* - Any other value: Parses XML without array option.
* @returns The JSON object resulting from the XML parsing.
*/
export function convertEncodedXmlIntoJson(encodedXml: string, xmlParserOption: string = 'withArrayOption'): any {

const withArrayOption = {
processEntities: false,
ignoreAttributes: false,
removeNSPrefix: true,
attributeNamePrefix: '@_',
stopNodes: ['*.div', '*.p'],
isArray: () => true,
};

const withArrayNoEntitiesOption = {
processEntities: true,
ignoreAttributes: false,
removeNSPrefix: true,
attributeNamePrefix: '@_',
stopNodes: ['*.div', '*.p'],
isArray: () => true,
};

const noArrayOption = {
processEntities: false,
ignoreAttributes: false,
removeNSPrefix: true,
attributeNamePrefix: '@_',
stopNodes: ['div', 'p'],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isArray: (_name: string, _jpath: string, _isLeafNode: boolean, _isAttribute: boolean) => true,
stopNodes: ['*.div', '*.p'],
isArray: () => false,
};
const parser = new XMLParser(options);

const parser = new XMLParser(
xmlParserOption === 'withArrayOption'
? withArrayOption
: xmlParserOption === 'withArrayNoEntitiesOption'
? withArrayNoEntitiesOption
: noArrayOption)

return parser.parse(encodedXml);
}

Expand All @@ -58,12 +114,20 @@ export function convertJsonIntoXML(data: any) {
* @returns The decoded string with XML special characters removed.
*/
export function removeXMLSpecialCharacters(str: string) {
//console.log('Remove special characters: ', JSON.stringify(str, null, 2));
const result = he.decode(str);
//console.log('Result of he.decode: ', JSON.stringify(result));
return result
}

/**
* Removes HTML tags from the given input string.
*
* @param input - The string from which HTML tags should be removed.
* @returns A new string with all HTML tags removed.
*/
export function removeHtmlTags(input: string): string {
return input.replace(/<\/?[^>]+(>|$)/g, '');
}

/**
* Converts a severity string to a numerical impact value.
*
Expand Down Expand Up @@ -174,7 +238,7 @@ export function convertEncodedHTMLIntoJson(encodedHTML?: string): DecodedDescrip
})
htmlParser.write(patchedHTML)
htmlParser.end()
const converted = convertEncodedXmlIntoJson(xmlChunks.join(''))
const converted = convertEncodedXmlIntoJson(xmlChunks.join(''), 'noArrayOption')
let cleaned: Record<string, string | boolean | undefined> = {}

// Some STIGs have xml tags inside of the actual text which breaks processing,
Expand Down
Loading

0 comments on commit bd4dd2c

Please sign in to comment.