diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 90298169e6dbe..29478acafd657 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -86,7 +86,7 @@ const config: Config = { { name: 'twitter:image', content: 'https://developer.sailpoint.com/img/SailPoint-Logo-OG.png' }, // Content Security Policy - { 'http-equiv': 'Content-Security-Policy', content: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://code.jquery.com https://www.googletagmanager.com https://cdn.jsdelivr.net https://cdn.cookielaw.org https://googleads.g.doubleclick.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://p.typekit.net https://use.typekit.net; img-src 'self' data: https: http:; font-src 'self' data: https://cdn.jsdelivr.net https://use.typekit.net https://cdnjs.cloudflare.com; connect-src 'self' http://localhost:3000 https://nug87yusrg.execute-api.us-east-1.amazonaws.com https://*.algolia.net https://*.algolianet.com https://www.googletagmanager.com https://www.google.com https://analytics.google.com https://developer.sailpoint.com https://cdn.cookielaw.org https://stats.g.doubleclick.net https://googleads.g.doubleclick.net https://*.api.identitynow.com https://*.api.identitynow-demo.com; frame-src 'self' https://www.googletagmanager.com https://www.youtube.com https://play.vidyard.com; worker-src 'self' blob:;" }, + { 'http-equiv': 'Content-Security-Policy', content: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://code.jquery.com https://www.googletagmanager.com https://cdn.jsdelivr.net https://cdn.cookielaw.org https://googleads.g.doubleclick.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://p.typekit.net https://use.typekit.net https://fonts.googleapis.com; img-src 'self' data: https: http:; font-src 'self' data: https://cdn.jsdelivr.net https://use.typekit.net https://cdnjs.cloudflare.com https://fonts.gstatic.com; connect-src 'self' http://localhost:3000 https://nug87yusrg.execute-api.us-east-1.amazonaws.com https://*.algolia.net https://*.algolianet.com https://www.googletagmanager.com https://www.google.com https://analytics.google.com https://developer.sailpoint.com https://cdn.cookielaw.org https://stats.g.doubleclick.net https://googleads.g.doubleclick.net https://*.api.identitynow.com https://*.api.identitynow-demo.com; frame-src 'self' https://www.googletagmanager.com https://www.youtube.com https://play.vidyard.com; worker-src 'self' blob:;" }, ], algolia: { appId: 'TB01H1DFAM', @@ -159,6 +159,7 @@ const config: Config = { AUTH_PASSWORD: process.env.AUTH_PASSWORD || '', ENDPOINT_OVERRIDE: process.env.ENDPOINT_OVERRIDE || '', SAMPLE_TABLE: process.env.SAMPLE_TABLE || '', + SECRET_MESSAGE: process.env.SECRET_MESSAGE || '', CMS_APP_API_ENDPOINT: process.env.NODE_ENV === 'development' ? 'http://localhost:3000/' @@ -166,4 +167,4 @@ const config: Config = { }, }; -export default config; +export default config; \ No newline at end of file diff --git a/navbar.ts b/navbar.ts index ae0c094a36995..795922cb1bdef 100644 --- a/navbar.ts +++ b/navbar.ts @@ -34,6 +34,7 @@ const navbarConfig = { { label: 'CLI', to: '/docs/tools/cli' }, { label: 'Escaping Tool Formatter', to: '/tools/escaping-tool-formatter' }, { label: 'JSON Path Evaluator', to: '/tools/json-path-evaluator' }, + { label: 'XPath Evaluator', to: '/tools/xpath-evaluator' }, { label: 'Rule Development Kit', to: '/docs/tools/rule-development-kit' }, { label: 'UI Development Kit', to: '/docs/tools/ui-development-kit' }, { label: 'Velocity PlayGround', to: '/tools/velocity-playground' }, diff --git a/package-lock.json b/package-lock.json index a9c8af701c522..a08365cd7c827 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "@mui/material": "^6.1.6", "@reduxjs/toolkit": "^2.11.2", "@typeform/embed-react": "^1.21.0", + "@xmldom/xmldom": "^0.9.10", "ace-builds": "^1.36.4", "autoprefixer": "^10.4.13", "canvas-confetti": "^1.9.3", @@ -50,7 +51,8 @@ "react-markdown": "^8.0.7", "react-spinners": "^0.13.8", "react-tabs": "^4.3.0", - "velocityjs": "^2.1.5" + "velocityjs": "^2.1.5", + "xpath": "^0.0.34" }, "devDependencies": { "@docusaurus/core": "3.9.2", @@ -7631,6 +7633,15 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -26151,6 +26162,15 @@ "node": ">= 16" } }, + "node_modules/xpath": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz", + "integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==", + "license": "MIT", + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 1888e9f63574d..f370d134a66c9 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,9 @@ "react-markdown": "^8.0.7", "react-spinners": "^0.13.8", "react-tabs": "^4.3.0", - "velocityjs": "^2.1.5" + "velocityjs": "^2.1.5", + "@xmldom/xmldom": "^0.9.10", + "xpath": "^0.0.34" }, "overrides": { "mermaid": "10.9.3", diff --git a/src/components/xpath/ImplementationDropdown/index.tsx b/src/components/xpath/ImplementationDropdown/index.tsx new file mode 100644 index 0000000000000..234420693703b --- /dev/null +++ b/src/components/xpath/ImplementationDropdown/index.tsx @@ -0,0 +1,112 @@ +import React, { useState, FocusEvent, ChangeEvent } from 'react'; +import FormControl from '@mui/material/FormControl'; +import InputLabel from '@mui/material/InputLabel'; +import Select from '@mui/material/Select'; +import MenuItem from '@mui/material/MenuItem'; +import { useColorMode } from '@docusaurus/theme-common'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; + +// Define prop types +interface ImplementationDropdownProps { + implementation: string; + onImplementationChange: (value: string) => void; + onFocus?: (event: FocusEvent) => void; + onBlur?: (event: FocusEvent) => void; +} + +const ImplementationDropdown: React.FC = ({ + implementation, + onImplementationChange, + onFocus, + onBlur, +}) => { + const { colorMode } = useColorMode(); + const [isFocused, setIsFocused] = useState(false); + const [expanded, setExpanded] = useState(false); + + const theme = createTheme({ + components: { + MuiOutlinedInput: { + styleOverrides: { + root: { + '& .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? '#ffffff' : 'initial', + borderWidth: 1, + }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + }, + }, + }, + MuiSelect: { + styleOverrides: { + icon: { + color: colorMode === 'dark' ? '#ffffff' : 'black', + }, + }, + }, + }, + }); + + const handleChange = (event: ChangeEvent<{ value: unknown }>) => { + onImplementationChange(event.target.value as string); + }; + + // Handle focus and blur state changes + const handleFocus = (event: FocusEvent) => { + setIsFocused(true); + if (onFocus) onFocus(event); + }; + + const handleBlur = (event: FocusEvent) => { + setIsFocused(false); + if (onBlur) onBlur(event); + }; + + // Handle dropdown expanded state + const handleDropdownOpen = () => setExpanded(true); + const handleDropdownClose = () => setExpanded(false); + + return ( + + + + Implementation + + + + + + ); +}; + +export default ImplementationDropdown; diff --git a/src/components/xpath/InputTerminal/index.tsx b/src/components/xpath/InputTerminal/index.tsx new file mode 100644 index 0000000000000..ad567ec4c0567 --- /dev/null +++ b/src/components/xpath/InputTerminal/index.tsx @@ -0,0 +1,302 @@ +import React, {useEffect, useRef} from 'react'; +import AceEditor from 'react-ace'; +import 'ace-builds/src-noconflict/mode-xml'; +import 'ace-builds/src-noconflict/mode-json'; +import 'ace-builds/src-noconflict/mode-text'; +import 'ace-builds/src-noconflict/theme-github_dark'; +import 'ace-builds/src-noconflict/theme-github_light_default'; +import 'ace-builds/src-noconflict/ext-language_tools'; +import { useColorMode } from '@docusaurus/theme-common'; +import styles from '../../../pages/tools/xpath.module.css'; + +// Ensure ace is properly configured +declare const ace: any; +if (typeof ace !== 'undefined' && ace.config) { + ace.config.setModuleUrl( + 'ace/mode/xml_worker', + new URL( + 'https://ajaxorg.github.io/ace-builds/src-noconflict/worker-xml.js' + ).toString(), + ); +} + +interface InputTerminalProps { + fontSize: string; + value: string; + onChange: (value: string) => void; + hasParseError?: boolean; + mode?: 'xml' | 'json' | 'text'; + title?: string; + onHoverValueChange?: (value: HoverValuePayload | null) => void; + onHoverLock?: (value: HoverValuePayload | null) => void; + lockedHoverValue?: HoverValuePayload | null; +} +export type HoverValuePayload = { + value: string; + nodeKind: 'attribute' | 'text'; + occurrenceIndex: number; + row: number; + startCol: number; + endCol: number; +}; + +const InputTerminal: React.FC = ({ + fontSize, + value, + onChange, + hasParseError = false, + mode = 'xml', + title = 'Inputs', + onHoverValueChange, + onHoverLock, + lockedHoverValue = null, +}) => { + const { colorMode } = useColorMode(); + const editorRef = useRef(null); + const lastHoveredPayloadRef = useRef(null); + const lastNotifiedPayloadRef = useRef(null); + const lockedMarkerIdRef = useRef(null); + + const terminalClass = hasParseError + ? styles.inputTerminalContainer + : styles.terminalContainerDefault; + + useEffect(() => { + if (mode !== 'xml' || !onHoverValueChange || !editorRef.current) { + return; + } + + const editor = editorRef.current.editor; + if (!editor) { + return; + } + + const escapeForRegex = (text: string): string => + text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + + const countAttributeOccurrencesUntil = ( + fullText: string, + targetValue: string, + absoluteStart: number, + ): number => { + const escapedValue = escapeForRegex(targetValue); + const pattern = new RegExp(`=\\s*(['"])${escapedValue}\\1`, 'g'); + let count = 0; + let match: RegExpExecArray | null; + while ((match = pattern.exec(fullText)) !== null) { + const quoteOffset = match[0].search(/['"]/); + const valueStart = match.index + quoteOffset + 1; + if (valueStart > absoluteStart) { + break; + } + count += 1; + } + return Math.max(0, count - 1); + }; + + const countTextOccurrencesUntil = ( + fullText: string, + targetValue: string, + absoluteStart: number, + ): number => { + const pattern = />([^<]*) absoluteStart) { + break; + } + count += 1; + } + return Math.max(0, count - 1); + }; + + const extractHoveredValue = ( + line: string, + column: number, + ): {value: string; nodeKind: 'attribute' | 'text'; startCol: number} | null => { + if (!line) { + return null; + } + + const quoteChars = [`"`, `'`]; + for (const quote of quoteChars) { + const leftQuote = line.lastIndexOf(quote, column); + if (leftQuote >= 0) { + const rightQuote = line.indexOf(quote, leftQuote + 1); + if (rightQuote > leftQuote && column <= rightQuote) { + const quotedValue = line.slice(leftQuote + 1, rightQuote).trim(); + if (!quotedValue) { + return null; + } + return { + value: quotedValue, + nodeKind: 'attribute', + startCol: leftQuote + 1, + }; + } + } + } + + const leftTag = line.lastIndexOf('>', column); + const rightTag = line.indexOf('<', column); + if (leftTag >= 0 && rightTag > leftTag) { + const textValue = line.slice(leftTag + 1, rightTag).trim(); + if (!textValue) { + return null; + } + const originalSegment = line.slice(leftTag + 1, rightTag); + const trimmedOffset = originalSegment.indexOf(textValue); + return { + value: textValue, + nodeKind: 'text', + startCol: leftTag + 1 + Math.max(0, trimmedOffset), + }; + } + + return null; + }; + + const handleMouseMove = (event: MouseEvent) => { + const position = editor.renderer.screenToTextCoordinates( + event.clientX, + event.clientY, + ); + const line = editor.session.getLine(position.row); + const hoveredToken = extractHoveredValue(line, position.column); + if (!hoveredToken) { + lastHoveredPayloadRef.current = null; + if (lastNotifiedPayloadRef.current !== null) { + onHoverValueChange(null); + lastNotifiedPayloadRef.current = null; + } + return; + } + const absoluteStart = editor.session.doc.positionToIndex({ + row: position.row, + column: hoveredToken.startCol, + }); + const occurrenceIndex = + hoveredToken.nodeKind === 'attribute' + ? countAttributeOccurrencesUntil(value, hoveredToken.value, absoluteStart) + : countTextOccurrencesUntil(value, hoveredToken.value, absoluteStart); + const payload: HoverValuePayload = { + value: hoveredToken.value, + nodeKind: hoveredToken.nodeKind, + occurrenceIndex, + row: position.row, + startCol: hoveredToken.startCol, + endCol: hoveredToken.startCol + hoveredToken.value.length, + }; + lastHoveredPayloadRef.current = payload; + const lastNotified = lastNotifiedPayloadRef.current; + if ( + lastNotified && + lastNotified.value === payload.value && + lastNotified.nodeKind === payload.nodeKind && + lastNotified.occurrenceIndex === payload.occurrenceIndex + ) { + return; + } + onHoverValueChange(payload); + lastNotifiedPayloadRef.current = payload; + }; + + const handleMouseLeave = () => { + lastHoveredPayloadRef.current = null; + if (lastNotifiedPayloadRef.current !== null) { + onHoverValueChange(null); + lastNotifiedPayloadRef.current = null; + } + }; + + const handleMouseUp = () => { + if (!onHoverLock) { + return; + } + onHoverLock(lastHoveredPayloadRef.current); + }; + + editor.container.addEventListener('mousemove', handleMouseMove); + editor.container.addEventListener('mouseleave', handleMouseLeave); + editor.container.addEventListener('mouseup', handleMouseUp); + + return () => { + editor.container.removeEventListener('mousemove', handleMouseMove); + editor.container.removeEventListener('mouseleave', handleMouseLeave); + editor.container.removeEventListener('mouseup', handleMouseUp); + }; + }, [mode, onHoverLock, onHoverValueChange, value]); + + useEffect(() => { + if (mode !== 'xml' || !editorRef.current) { + return; + } + + const editor = editorRef.current.editor; + if (!editor) { + return; + } + + if (lockedMarkerIdRef.current !== null) { + editor.session.removeMarker(lockedMarkerIdRef.current); + lockedMarkerIdRef.current = null; + } + + if (!lockedHoverValue) { + return; + } + + const Range = ace.require('ace/range').Range; + lockedMarkerIdRef.current = editor.session.addMarker( + new Range( + lockedHoverValue.row, + lockedHoverValue.startCol, + lockedHoverValue.row, + lockedHoverValue.endCol, + ), + 'locked-hover-selection', + 'text', + false, + ); + + return () => { + if (lockedMarkerIdRef.current !== null) { + editor.session.removeMarker(lockedMarkerIdRef.current); + lockedMarkerIdRef.current = null; + } + }; + }, [lockedHoverValue, mode]); + + return ( +
+

{title}

+ { + editorRef.current = {editor}; + }} + className={terminalClass} + mode={mode} + theme={colorMode === 'dark' ? 'github_dark' : 'github_light_default'} + value={value} + onChange={onChange} + fontSize={`${fontSize}px`} + width="auto" + showPrintMargin={false} + editorProps={{ $blockScrolling: true }} + setOptions={{ + fontFamily: 'monospace', + }} + /> +
+ ); +}; + +export default InputTerminal; diff --git a/src/components/xpath/ResultTerminal/index.tsx b/src/components/xpath/ResultTerminal/index.tsx new file mode 100644 index 0000000000000..6ca944f2fe4f9 --- /dev/null +++ b/src/components/xpath/ResultTerminal/index.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import AceEditor from 'react-ace'; +import 'ace-builds/src-noconflict/mode-json'; +import 'ace-builds/src-noconflict/mode-text'; +import 'ace-builds/src-noconflict/theme-github_dark'; +import 'ace-builds/src-noconflict/theme-github_light_default'; +import 'ace-builds/src-noconflict/ext-language_tools'; +import { useColorMode } from '@docusaurus/theme-common'; +import styles from '../../../pages/tools/xpath.module.css'; + +// Ensure ace is properly configured +declare const ace: any; +if (typeof ace !== 'undefined' && ace.config) { + ace.config.setModuleUrl( + 'ace/mode/json_worker', + new URL( + 'https://ajaxorg.github.io/ace-builds/src-noconflict/worker-json.js' + ).toString(), + ); +} + +// Props interface with optional `mode` +interface ResultTerminalProps { + result: string; + fontSize: string; + mode?: 'json' | 'text'; +} + +const ResultTerminal: React.FC = ({ result, fontSize, mode = 'json' }) => { + const { colorMode } = useColorMode(); + + return ( +
+

Evaluation results

+ + +
+ ); +}; + +export default ResultTerminal; diff --git a/src/components/xpath/TerminalFontSizeDropdown/index.tsx b/src/components/xpath/TerminalFontSizeDropdown/index.tsx new file mode 100644 index 0000000000000..3188f2c2d3593 --- /dev/null +++ b/src/components/xpath/TerminalFontSizeDropdown/index.tsx @@ -0,0 +1,114 @@ +import React, { useState, ChangeEvent, FocusEvent } from 'react'; +import FormControl from '@mui/material/FormControl'; +import InputLabel from '@mui/material/InputLabel'; +import Select from '@mui/material/Select'; +import MenuItem from '@mui/material/MenuItem'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +import { useColorMode } from '@docusaurus/theme-common'; + +// Define props interface +interface TerminalFontSizeDropdownProps { + fontSize: string; + onFontSizeChange: (value: string) => void; + onFocus?: (event: FocusEvent) => void; + onBlur?: (event: FocusEvent) => void; +} + +const TerminalFontSizeDropdown: React.FC = ({ + fontSize, + onFontSizeChange, + onFocus, + onBlur, +}) => { + const { colorMode } = useColorMode(); + const [isFocused, setIsFocused] = useState(false); + const [expanded, setExpanded] = useState(false); + + const theme = createTheme({ + components: { + MuiOutlinedInput: { + styleOverrides: { + root: { + '& .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? '#ffffff' : 'initial', + borderWidth: 1, + }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + }, + }, + }, + MuiSelect: { + styleOverrides: { + icon: { + color: colorMode === 'dark' ? '#ffffff' : 'black', + }, + }, + }, + }, + }); + + const handleChange = (event: ChangeEvent<{ value: unknown }>) => { + onFontSizeChange(event.target.value as string); + }; + + // Handle focus and blur state changes + const handleFocus = (event: FocusEvent) => { + setIsFocused(true); + if (onFocus) onFocus(event); + }; + + const handleBlur = (event: FocusEvent) => { + setIsFocused(false); + if (onBlur) onBlur(event); + }; + + // Handle dropdown expanded state + const handleDropdownOpen = () => setExpanded(true); + const handleDropdownClose = () => setExpanded(false); + + return ( + + + + Terminal Font Size + + + + + ); +}; + +export default TerminalFontSizeDropdown; diff --git a/src/components/xpath/XPathQueryInput/index.tsx b/src/components/xpath/XPathQueryInput/index.tsx new file mode 100644 index 0000000000000..a66ec3b7f962f --- /dev/null +++ b/src/components/xpath/XPathQueryInput/index.tsx @@ -0,0 +1,69 @@ +import React, { useState, FocusEvent, ChangeEvent } from 'react'; +import TextField from '@mui/material/TextField'; +import { useColorMode } from '@docusaurus/theme-common'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; + +// Define props interface +interface XPathQueryInputProps { + value: string; + onChange: (event: ChangeEvent) => void; + onFocus?: (event: FocusEvent) => void; + onBlur?: (event: FocusEvent) => void; +} + +const XPathQueryInput: React.FC = ({ value, onChange, onFocus, onBlur }) => { + const { colorMode } = useColorMode(); + const [isFocused, setIsFocused] = useState(false); + + const theme = createTheme({ + components: { + MuiOutlinedInput: { + styleOverrides: { + root: { + '& .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? '#ffffff' : 'initial', + borderWidth: 1, + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + }, + }, + }, + }, + }); + + return ( + + { + setIsFocused(true); + if (onFocus) onFocus(event); + }} + onBlur={(event) => { + setIsFocused(false); + if (onBlur) onBlur(event); + }} + sx={{ + m: 1, + minWidth: 800, + '& .MuiInputLabel-root': { + color: isFocused ? (colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)') : 'initial', + }, + '& .MuiOutlinedInput-root.Mui-focused': { + '& fieldset': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + }, + }} + id="outlined-basic-xpath-input" + label="Enter XPath query" + variant="outlined" + value={value} + onChange={onChange} + /> + + ); +}; + +export default XPathQueryInput; diff --git a/src/components/xpath/XPathRootInput/index.tsx b/src/components/xpath/XPathRootInput/index.tsx new file mode 100644 index 0000000000000..3b8c6bdd46cee --- /dev/null +++ b/src/components/xpath/XPathRootInput/index.tsx @@ -0,0 +1,69 @@ +import React, { useState, FocusEvent, ChangeEvent } from 'react'; +import TextField from '@mui/material/TextField'; +import { useColorMode } from '@docusaurus/theme-common'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; + +// Define props interface +interface XPathRootInputProps { + value: string; + onChange: (event: ChangeEvent) => void; + onFocus?: (event: FocusEvent) => void; + onBlur?: (event: FocusEvent) => void; +} + +const XPathRootInput: React.FC = ({ value, onChange, onFocus, onBlur }) => { + const { colorMode } = useColorMode(); + const [isFocused, setIsFocused] = useState(false); + + const theme = createTheme({ + components: { + MuiOutlinedInput: { + styleOverrides: { + root: { + '& .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? '#ffffff' : 'initial', + borderWidth: 1, + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + }, + }, + }, + }, + }); + + return ( + + { + setIsFocused(true); + if (onFocus) onFocus(event); + }} + onBlur={(event) => { + setIsFocused(false); + if (onBlur) onBlur(event); + }} + sx={{ + m: 1, + minWidth: 800, + '& .MuiInputLabel-root': { + color: isFocused ? (colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)') : 'initial', + }, + '& .MuiOutlinedInput-root.Mui-focused': { + '& fieldset': { + borderColor: colorMode === 'dark' ? 'rgb(115,200,235)' : 'rgb(4,125,246)', + }, + }, + }} + id="outlined-basic-xpath-input" + label="Enter XPath root" + variant="outlined" + value={value} + onChange={onChange} + /> + + ); +}; + +export default XPathRootInput; diff --git a/src/components/xpath/useDebounce.ts b/src/components/xpath/useDebounce.ts new file mode 100644 index 0000000000000..481ad379e122d --- /dev/null +++ b/src/components/xpath/useDebounce.ts @@ -0,0 +1,16 @@ +import { useState, useEffect } from 'react'; + +// Define the hook's return type +export function useDebounce(value: T, delay: number): T { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => clearTimeout(handler); + }, [value, delay]); + + return debouncedValue; +} diff --git a/src/pages/tools/EscapeTool.module.css b/src/pages/tools/EscapeTool.module.css index 7187a01c6cbf5..daa975baa60dd 100644 --- a/src/pages/tools/EscapeTool.module.css +++ b/src/pages/tools/EscapeTool.module.css @@ -31,12 +31,12 @@ background: var(--terminal-background) !important; } -a[id^='jsonpathDocumentationLink'] { +a[id^='xpathDocumentationLink'] { color: var(--link-color) !important; text-decoration: underline !important; } -a[id^='jsonpathDocumentationLink']:hover { +a[id^='xpathDocumentationLink']:hover { text-decoration: none !important; } @@ -51,15 +51,15 @@ div[id^='implementation-dropdown-select'] { color: var(--ifm-primary-text-color); } -input[id^='outlined-basic-jsonpath-input'], -label[id^='outlined-basic-jsonpath-input-label'], +input[id^='outlined-basic-xpath-input'], +label[id^='outlined-basic-xpath-input-label'], select[id^='terminal-font-size-select'], label[id^='terminal-font-size-label'], select[id^='implementation-dropdown-select'], label[id^='implementation-dropdown-label'] { color: var(--ifm-primary-text-color); } -input[id^='outlined-basic-jsonpath-input'], +input[id^='outlined-basic-xpath-input'], div[id^='terminal-font-size-select'], div[id^='implementation-dropdown-select'] { background: var(--terminal-background); @@ -84,7 +84,7 @@ span[class^='ace_string'] { color: var(--terminal-value) !important; } -div [id^='jsonpathalert'] { +div [id^='xpathalert'] { color: rgb(244, 67, 54); border: 1px solid rgb(244, 67, 54); } diff --git a/src/pages/tools/sample.xml.json b/src/pages/tools/sample.xml.json new file mode 100644 index 0000000000000..c4935a5ff0468 --- /dev/null +++ b/src/pages/tools/sample.xml.json @@ -0,0 +1 @@ +{"xml":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHNvYXA6RW52ZWxvcGUKICAgIHhtbG5zOnNvYXA9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3NvYXAvZW52ZWxvcGUvIgogICAgeG1sbnM6eGhyPSJ1cm46Y29tLnh5bG9waG9uaWNoci9hcGkiPgogIDxzb2FwOkJvZHk+CiAgICA8eGhyOkdldEVtcGxveWVlc19SZXNwb25zZSB4aHI6dmVyc2lvbj0idjEyLjAiPgoKICAgICAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgIDwhLS0gUEFHSU5BVElPTiBNRVRBREFUQSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPgogICAgICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAtLT4KICAgICAgPHhocjpSZXNwb25zZV9GaWx0ZXI+CiAgICAgICAgPHhocjpFZmZlY3RpdmVfQXNfT2ZfRGF0ZT4yMDI2LTAzLTMwPC94aHI6RWZmZWN0aXZlX0FzX09mX0RhdGU+CiAgICAgICAgPHhocjpFZmZlY3RpdmVfQXNfT2ZfRGF0ZVRpbWU+MjAyNi0wMy0zMFQxMjowMDowMC4wMDAtMDc6MDA8L3hocjpFZmZlY3RpdmVfQXNfT2ZfRGF0ZVRpbWU+CiAgICAgICAgPHhocjpQYWdlPjE8L3hocjpQYWdlPgogICAgICAgIDx4aHI6UGFnZV9TaXplPjEwMDwveGhyOlBhZ2VfU2l6ZT4KICAgICAgPC94aHI6UmVzcG9uc2VfRmlsdGVyPgoKICAgICAgPHhocjpSZXNwb25zZV9TdW1tYXJ5PgogICAgICAgIDx4aHI6VG90YWxfUmVjb3Jkcz40PC94aHI6VG90YWxfUmVjb3Jkcz4KICAgICAgICA8eGhyOlRvdGFsX1BhZ2VzPjE8L3hocjpUb3RhbF9QYWdlcz4KICAgICAgICA8eGhyOlJlY29yZHNfT25fUGFnZT40PC94aHI6UmVjb3Jkc19Pbl9QYWdlPgogICAgICAgIDx4aHI6Q3VycmVudF9QYWdlPjE8L3hocjpDdXJyZW50X1BhZ2U+CiAgICAgIDwveGhyOlJlc3BvbnNlX1N1bW1hcnk+CgogICAgICA8eGhyOlJlc3BvbnNlX0RhdGE+CgogICAgICAgIDwhLS0gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IC0tPgogICAgICAgIDwhLS0gRU1QTE9ZRUUgMSDigJQgQWN0aXZlLCBGdWxsLVRpbWUsIFVTLWJhc2VkICAgICAgICAgICAgICAgICAgICAgLS0+CiAgICAgICAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgICAgPHhocjpFbXBsb3llZT4KICAgICAgICAgIDx4aHI6RW1wbG95ZWVfUmVmZXJlbmNlPgogICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmE0YzllMTdmMmI2ZDQ4YTM5MDFlN2M1ZjgzZDJiMGE2PC94aHI6SUQ+CiAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkVtcGxveWVlX051bWJlciI+RU1QLTIwNDgxNzwveGhyOklEPgogICAgICAgICAgPC94aHI6RW1wbG95ZWVfUmVmZXJlbmNlPgoKICAgICAgICAgIDx4aHI6RW1wbG95ZWVfRGF0YT4KICAgICAgICAgICAgPHhocjpFbXBsb3llZV9OdW1iZXI+RU1QLTIwNDgxNzwveGhyOkVtcGxveWVlX051bWJlcj4KICAgICAgICAgICAgPHhocjpMb2dpbl9JRD5rcGF0ZWw8L3hocjpMb2dpbl9JRD4KCiAgICAgICAgICAgIDwhLS0gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgICAgICAgIDwhLS0gUEVSU09OQUwgREFUQSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPgogICAgICAgICAgICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IC0tPgogICAgICAgICAgICA8eGhyOlBlcnNvbmFsX0RhdGE+CgogICAgICAgICAgICAgIDx4aHI6TmFtZV9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpMZWdhbF9OYW1lPgogICAgICAgICAgICAgICAgICA8eGhyOk5hbWVfRGV0YWlsPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmJjMzNhYTMxNTJlYzQyZDQ5OTVmNDc5MWExMDZlZDA5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTIiPlVTPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTMiPlVTQTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VGl0bGU+TXMuPC94aHI6VGl0bGU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpGaXJzdF9OYW1lPkthdml0YTwveGhyOkZpcnN0X05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpNaWRkbGVfTmFtZT5SYW5pPC94aHI6TWlkZGxlX05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMYXN0X05hbWU+UGF0ZWw8L3hocjpMYXN0X05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpTdWZmaXgvPgogICAgICAgICAgICAgICAgICAgIDx4aHI6RGlzcGxheV9OYW1lPkthdml0YSBSYW5pIFBhdGVsPC94aHI6RGlzcGxheV9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6U29ydF9OYW1lPlBhdGVsLCBLYXZpdGEgUmFuaTwveGhyOlNvcnRfTmFtZT4KICAgICAgICAgICAgICAgICAgPC94aHI6TmFtZV9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpMZWdhbF9OYW1lPgogICAgICAgICAgICAgICAgPHhocjpQcmVmZXJyZWRfTmFtZT4KICAgICAgICAgICAgICAgICAgPHhocjpOYW1lX0RldGFpbD4KICAgICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5iYzMzYWEzMTUyZWM0MmQ0OTk1ZjQ3OTFhMTA2ZWQwOTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5VUzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Rmlyc3RfTmFtZT5LYXZpdGE8L3hocjpGaXJzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TGFzdF9OYW1lPlBhdGVsPC94aHI6TGFzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6RGlzcGxheV9OYW1lPkthdml0YSBQYXRlbDwveGhyOkRpc3BsYXlfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOlNvcnRfTmFtZT5QYXRlbCwgS2F2aXRhPC94aHI6U29ydF9OYW1lPgogICAgICAgICAgICAgICAgICA8L3hocjpOYW1lX0RldGFpbD4KICAgICAgICAgICAgICAgIDwveGhyOlByZWZlcnJlZF9OYW1lPgogICAgICAgICAgICAgIDwveGhyOk5hbWVfRGF0YT4KCiAgICAgICAgICAgICAgPHhocjpDb250YWN0X0RhdGE+CgogICAgICAgICAgICAgICAgPCEtLSBXb3JrIEVtYWlsIC0tPgogICAgICAgICAgICAgICAgPHhocjpFbWFpbD4KICAgICAgICAgICAgICAgICAgPHhocjpFbWFpbF9BZGRyZXNzPmthdml0YS5wYXRlbEBnbG9iYWxkeW5hbWljcy5jb208L3hocjpFbWFpbF9BZGRyZXNzPgogICAgICAgICAgICAgICAgICA8eGhyOlVzYWdlIHhocjpQdWJsaWM9InRydWUiPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9JbmZvIHhocjpQcmltYXJ5PSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZDBlMWYyYTNiNGM1ZDZlN2Y4YTliMGMxZDJlM2Y0YTU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVXNhZ2VfVHlwZV9Db2RlIj5XT1JLPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX0luZm8+CiAgICAgICAgICAgICAgICAgIDwveGhyOlVzYWdlPgogICAgICAgICAgICAgICAgPC94aHI6RW1haWw+CgogICAgICAgICAgICAgICAgPCEtLSBQZXJzb25hbCBFbWFpbCAtLT4KICAgICAgICAgICAgICAgIDx4aHI6RW1haWw+CiAgICAgICAgICAgICAgICAgIDx4aHI6RW1haWxfQWRkcmVzcz5rYXZpdGEuci5wYXRlbEBvdXRsb29rLmNvbTwveGhyOkVtYWlsX0FkZHJlc3M+CiAgICAgICAgICAgICAgICAgIDx4aHI6VXNhZ2UgeGhyOlB1YmxpYz0iZmFsc2UiPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9JbmZvIHhocjpQcmltYXJ5PSJmYWxzZSI+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmExYjJjM2Q0ZTVmNmE3YjhjOWQwZTFmMmEzYjRjNWQ2PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlVzYWdlX1R5cGVfQ29kZSI+SE9NRTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6VHlwZV9JbmZvPgogICAgICAgICAgICAgICAgICA8L3hocjpVc2FnZT4KICAgICAgICAgICAgICAgIDwveGhyOkVtYWlsPgoKICAgICAgICAgICAgICAgIDwhLS0gV29yayBQaG9uZSAtLT4KICAgICAgICAgICAgICAgIDx4aHI6UGhvbmU+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9Db2RlPjE8L3hocjpDb3VudHJ5X0NvZGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6QXJlYV9Db2RlPjQxNTwveGhyOkFyZWFfQ29kZT4KICAgICAgICAgICAgICAgICAgPHhocjpOdW1iZXI+NTU1LTAxMzI8L3hocjpOdW1iZXI+CiAgICAgICAgICAgICAgICAgIDx4aHI6RXh0ZW5zaW9uPjQ0MjA8L3hocjpFeHRlbnNpb24+CiAgICAgICAgICAgICAgICAgIDx4aHI6RGV2aWNlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZTRmNWE2YjdjOGQ5ZTBmMWEyYjNjNGQ1ZTZmN2E4Yjk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJEZXZpY2VfVHlwZV9Db2RlIj5MYW5kbGluZTwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpEZXZpY2VfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6VXNhZ2UgeGhyOlB1YmxpYz0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX0luZm8geGhyOlByaW1hcnk9InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5kMGUxZjJhM2I0YzVkNmU3ZjhhOWIwYzFkMmUzZjRhNTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJVc2FnZV9UeXBlX0NvZGUiPldPUks8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfSW5mbz4KICAgICAgICAgICAgICAgICAgPC94aHI6VXNhZ2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6Rm9ybWF0dGVkX051bWJlcj4rMSAoNDE1KSA1NTUtMDEzMiB4NDQyMDwveGhyOkZvcm1hdHRlZF9OdW1iZXI+CiAgICAgICAgICAgICAgICA8L3hocjpQaG9uZT4KCiAgICAgICAgICAgICAgICA8IS0tIE1vYmlsZSBQaG9uZSAtLT4KICAgICAgICAgICAgICAgIDx4aHI6UGhvbmU+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9Db2RlPjE8L3hocjpDb3VudHJ5X0NvZGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6QXJlYV9Db2RlPjY1MDwveGhyOkFyZWFfQ29kZT4KICAgICAgICAgICAgICAgICAgPHhocjpOdW1iZXI+NTU1LTAyNzg8L3hocjpOdW1iZXI+CiAgICAgICAgICAgICAgICAgIDx4aHI6RGV2aWNlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZjVhNmI3YzhkOWUwZjFhMmIzYzRkNWU2ZjdhOGI5YzA8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJEZXZpY2VfVHlwZV9Db2RlIj5Nb2JpbGU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6RGV2aWNlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOlVzYWdlIHhocjpQdWJsaWM9ImZhbHNlIj4KICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfSW5mbyB4aHI6UHJpbWFyeT0iZmFsc2UiPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5hMWIyYzNkNGU1ZjZhN2I4YzlkMGUxZjJhM2I0YzVkNjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJVc2FnZV9UeXBlX0NvZGUiPkhPTUU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfSW5mbz4KICAgICAgICAgICAgICAgICAgPC94aHI6VXNhZ2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6Rm9ybWF0dGVkX051bWJlcj4rMSAoNjUwKSA1NTUtMDI3ODwveGhyOkZvcm1hdHRlZF9OdW1iZXI+CiAgICAgICAgICAgICAgICA8L3hocjpQaG9uZT4KCiAgICAgICAgICAgICAgICA8IS0tIEhvbWUgQWRkcmVzcyAtLT4KICAgICAgICAgICAgICAgIDx4aHI6QWRkcmVzcz4KICAgICAgICAgICAgICAgICAgPHhocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmJjMzNhYTMxNTJlYzQyZDQ5OTVmNDc5MWExMDZlZDA5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5VUzwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpMYXN0X01vZGlmaWVkPjIwMjUtMDEtMTBUMDg6MTU6MDAuMDAwLTA4OjAwPC94aHI6TGFzdF9Nb2RpZmllZD4KICAgICAgICAgICAgICAgICAgPHhocjpMaW5lIHhocjpUeXBlPSJMSU5FXzEiPjE4NDcgTG9tYmFyZCBTdHJlZXQ8L3hocjpMaW5lPgogICAgICAgICAgICAgICAgICA8eGhyOkxpbmUgeGhyOlR5cGU9IkxJTkVfMiI+VW5pdCA2PC94aHI6TGluZT4KICAgICAgICAgICAgICAgICAgPHhocjpDaXR5PlNhbiBGcmFuY2lzY288L3hocjpDaXR5PgogICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5hOGI5YzBkMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkMzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlJlZ2lvbl9Db2RlIj5VU0EtQ0E8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UmVnaW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpSZWdpb25fTmFtZT5DYWxpZm9ybmlhPC94aHI6UmVnaW9uX05hbWU+CiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zdGFsX0NvZGU+OTQxMjM8L3hocjpQb3N0YWxfQ29kZT4KICAgICAgICAgICAgICAgICAgPHhocjpGb3JtYXR0ZWRfQWRkcmVzcz4xODQ3IExvbWJhcmQgU3RyZWV0LCBVbml0IDYsIFNhbiBGcmFuY2lzY28sIENBIDk0MTIzLCBVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2E8L3hocjpGb3JtYXR0ZWRfQWRkcmVzcz4KICAgICAgICAgICAgICAgICAgPHhocjpJc19CdXNpbmVzc19TaXRlX0RlZmF1bHQ+ZmFsc2U8L3hocjpJc19CdXNpbmVzc19TaXRlX0RlZmF1bHQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6VXNhZ2UgeGhyOlB1YmxpYz0iZmFsc2UiPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9JbmZvIHhocjpQcmltYXJ5PSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YTFiMmMzZDRlNWY2YTdiOGM5ZDBlMWYyYTNiNGM1ZDY8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVXNhZ2VfVHlwZV9Db2RlIj5IT01FPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX0luZm8+CiAgICAgICAgICAgICAgICAgIDwveGhyOlVzYWdlPgogICAgICAgICAgICAgICAgPC94aHI6QWRkcmVzcz4KCiAgICAgICAgICAgICAgPC94aHI6Q29udGFjdF9EYXRhPgoKICAgICAgICAgICAgICA8eGhyOkJpb2dyYXBoaWNhbF9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpEYXRlX29mX0JpcnRoPjE5OTAtMDQtMTg8L3hocjpEYXRlX29mX0JpcnRoPgogICAgICAgICAgICAgICAgPHhocjpHZW5kZXJfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjlhMGIxYzJkM2U0ZjVhNmI3YzhkOWUwZjFhMmIzYzRkPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdlbmRlcl9Db2RlIj5GZW1hbGU8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOkdlbmRlcl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfb2ZfQmlydGhfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmJjMzNhYTMxNTJlYzQyZDQ5OTVmNDc5MWExMDZlZDA5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfb2ZfQmlydGhfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgPHhocjpNYXJpdGFsX1N0YXR1c19SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YzRkNWU2ZjdhOGI5YzBkMWUyZjNhNGI1YzZkN2U4Zjk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTWFyaXRhbF9TdGF0dXNfQ29kZSI+TWFycmllZDwveGhyOklEPgogICAgICAgICAgICAgICAgPC94aHI6TWFyaXRhbF9TdGF0dXNfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgPHhocjpNYXJpdGFsX1N0YXR1c19EYXRlPjIwMjAtMDgtMTU8L3hocjpNYXJpdGFsX1N0YXR1c19EYXRlPgogICAgICAgICAgICAgIDwveGhyOkJpb2dyYXBoaWNhbF9EYXRhPgoKICAgICAgICAgICAgICA8eGhyOklkZW50aWZpY2F0aW9uX0RhdGE+CiAgICAgICAgICAgICAgICA8eGhyOk5hdGlvbmFsX0lEPgogICAgICAgICAgICAgICAgICA8eGhyOk5hdGlvbmFsX0lEX0RldGFpbD4KICAgICAgICAgICAgICAgICAgICA8eGhyOlZhbHVlPioqKi0qKi03ODkwPC94aHI6VmFsdWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZThmOWEwYjFjMmQzZTRmNWE2YjdjOGQ5ZTBmMWEyYjM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik5hdGlvbmFsX0lEX1R5cGUiPlVTQS1TU048L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5iYzMzYWEzMTUyZWM0MmQ0OTk1ZjQ3OTFhMTA2ZWQwOTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5VUzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SXNzdWVkX0RhdGU+MjAwOC0wNi0yMDwveGhyOklzc3VlZF9EYXRlPgogICAgICAgICAgICAgICAgICA8L3hocjpOYXRpb25hbF9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpOYXRpb25hbF9JRD4KICAgICAgICAgICAgICAgIDx4aHI6Q3VzdG9tX0lEPgogICAgICAgICAgICAgICAgICA8eGhyOkN1c3RvbV9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICAgICAgPHhocjpWYWx1ZT5CQURHRS0xMDQ4MjwveGhyOlZhbHVlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SURfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmYxYTJiM2M0ZDVlNmY3YThiOWMwZDFlMmYzYTRiNWM2PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJDdXN0b21fSURfVHlwZSI+QmFkZ2VfSUQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPC94aHI6Q3VzdG9tX0lEX0RldGFpbD4KICAgICAgICAgICAgICAgIDwveGhyOkN1c3RvbV9JRD4KICAgICAgICAgICAgICAgIDx4aHI6Q3VzdG9tX0lEPgogICAgICAgICAgICAgICAgICA8eGhyOkN1c3RvbV9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICAgICAgPHhocjpWYWx1ZT5QS1QtMDA5MTwveGhyOlZhbHVlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SURfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmEyYjNjNGQ1ZTZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJDdXN0b21fSURfVHlwZSI+UGFya2luZ19QZXJtaXQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPC94aHI6Q3VzdG9tX0lEX0RldGFpbD4KICAgICAgICAgICAgICAgIDwveGhyOkN1c3RvbV9JRD4KICAgICAgICAgICAgICA8L3hocjpJZGVudGlmaWNhdGlvbl9EYXRhPgoKICAgICAgICAgICAgPC94aHI6UGVyc29uYWxfRGF0YT4KCiAgICAgICAgICAgIDwhLS0gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgICAgICAgIDwhLS0gRU1QTE9ZTUVOVCBEQVRBICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPgogICAgICAgICAgICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IC0tPgogICAgICAgICAgICA8eGhyOkVtcGxveW1lbnRfRGF0YT4KICAgICAgICAgICAgICA8eGhyOkpvYl9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpQb3NpdGlvbj4KICAgICAgICAgICAgICAgICAgPHhocjpQb3NpdGlvbl9JRD5QT1MtMDA5MjEzPC94aHI6UG9zaXRpb25fSUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zaXRpb25fVGl0bGU+UHJpbmNpcGFsIERhdGEgRW5naW5lZXI8L3hocjpQb3NpdGlvbl9UaXRsZT4KICAgICAgICAgICAgICAgICAgPHhocjpCdXNpbmVzc19UaXRsZT5QcmluY2lwYWwgRGF0YSBFbmdpbmVlcjwveGhyOkJ1c2luZXNzX1RpdGxlPgogICAgICAgICAgICAgICAgICA8eGhyOlN0YXJ0X0RhdGU+MjAyNC0wMi0xMjwveGhyOlN0YXJ0X0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RGVmYXVsdF9XZWVrbHlfSG91cnM+NDA8L3hocjpEZWZhdWx0X1dlZWtseV9Ib3Vycz4KICAgICAgICAgICAgICAgICAgPHhocjpTY2hlZHVsZWRfV2Vla2x5X0hvdXJzPjQwPC94aHI6U2NoZWR1bGVkX1dlZWtseV9Ib3Vycz4KICAgICAgICAgICAgICAgICAgPHhocjpGVEVfUGVyY2VudGFnZT4xMDA8L3hocjpGVEVfUGVyY2VudGFnZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zaXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+N2JjNjY0MGM4YWY0NTljNmJmOTlkNGIwMmM1OWQwMDE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJQb3NpdGlvbl9JRCI+UE9TLTAwOTIxMzwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpQb3NpdGlvbl9SZWZlcmVuY2U+CgogICAgICAgICAgICAgICAgICA8eGhyOkVtcGxveWVlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZDRlNWY2YTdiOGM5ZDBlMWYyYTNiNGM1ZDZlN2Y4YTk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJFbXBsb3llZV9UeXBlX0NvZGUiPlJlZ3VsYXI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6RW1wbG95ZWVfVHlwZV9SZWZlcmVuY2U+CgogICAgICAgICAgICAgICAgICA8eGhyOkpvYl9Qcm9maWxlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Sm9iX1Byb2ZpbGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4xYTJiM2M0ZDVlNmY3YThiOWMwZDFlMmYzYTRiNWM2ZDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSm9iX1Byb2ZpbGVfQ29kZSI+SlAtREFUQS1FTkctUDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkpvYl9Qcm9maWxlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkpvYl9Qcm9maWxlX05hbWU+UHJpbmNpcGFsIERhdGEgRW5naW5lZXI8L3hocjpKb2JfUHJvZmlsZV9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TWFuYWdlbWVudF9MZXZlbF9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjJiM2M0ZDVlNmY3YThiOWMwZDFlMmYzYTRiNWM2ZDdlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJNYW5hZ2VtZW50X0xldmVsX0NvZGUiPkluZGl2aWR1YWxfQ29udHJpYnV0b3I8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpNYW5hZ2VtZW50X0xldmVsX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkpvYl9DYXRlZ29yeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjNjNGQ1ZTZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJKb2JfQ2F0ZWdvcnlfQ29kZSI+RW5naW5lZXJpbmc8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpKb2JfQ2F0ZWdvcnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Sm9iX0ZhbWlseV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjRkNWU2ZjdhOGI5YzBkMWUyZjNhNGI1YzZkN2U4ZjlhPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJKb2JfRmFtaWx5X0NvZGUiPkpGLURhdGEtRW5naW5lZXJpbmc8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpKb2JfRmFtaWx5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPC94aHI6Sm9iX1Byb2ZpbGU+CgogICAgICAgICAgICAgICAgICA8eGhyOldvcmtfTG9jYXRpb24+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMb2NhdGlvbl9OYW1lPlNhbiBGcmFuY2lzY28gSFE8L3hocjpMb2NhdGlvbl9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TG9jYXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj41ZTZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTG9jYXRpb25fQ29kZSI+TE9DLVNGLUhRPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TG9jYXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TG9jYXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMb2NhdGlvbl9UeXBlX0NvZGUiPk9mZmljZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkxvY2F0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6QWRkcmVzcz4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpMaW5lIHhocjpUeXBlPSJMSU5FXzEiPjM1MCBNaXNzaW9uIFN0cmVldDwveGhyOkxpbmU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOkxpbmUgeGhyOlR5cGU9IkxJTkVfMiI+Rmxvb3IgMjI8L3hocjpMaW5lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpDaXR5PlNhbiBGcmFuY2lzY288L3hocjpDaXR5PgogICAgICAgICAgICAgICAgICAgICAgPHhocjpSZWdpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJSZWdpb25fQ29kZSI+VVNBLUNBPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpSZWdpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpSZWdpb25fTmFtZT5DYWxpZm9ybmlhPC94aHI6UmVnaW9uX05hbWU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlBvc3RhbF9Db2RlPjk0MTA1PC94aHI6UG9zdGFsX0NvZGU+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6QWRkcmVzcz4KICAgICAgICAgICAgICAgICAgPC94aHI6V29ya19Mb2NhdGlvbj4KCiAgICAgICAgICAgICAgICAgIDx4aHI6UGF5X1JhdGVfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj43YThiOWMwZDFlMmYzYTRiNWM2ZDdlOGY5YTBiMWMyZDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlBheV9SYXRlX1R5cGVfQ29kZSI+U2FsYXJ5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOlBheV9SYXRlX1R5cGVfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpUaW1lX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+OGI5YzBkMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJUaW1lX1R5cGVfQ29kZSI+RnVsbF9UaW1lPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOlRpbWVfVHlwZV9SZWZlcmVuY2U+CgogICAgICAgICAgICAgICAgICA8eGhyOlN1cGVydmlzb3J5X09yZ19SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj45YzBkMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19Db2RlIj5FTkctREFUQS0wMDE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6U3VwZXJ2aXNvcnlfT3JnX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX0Fzc2lnbm1lbnRzPgogICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjBkMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19Db2RlIj5DQy03MTAwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkNvc3RfQ2VudGVyX0NvZGUiPkNDLTcxMDA8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9OYW1lPkVuZ2luZWVyaW5nIC0gRGF0YSBQbGF0Zm9ybTwveGhyOk9yZ2FuaXphdGlvbl9OYW1lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+MWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhNmI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX1R5cGVfQ29kZSI+Q29zdF9DZW50ZXI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb24+CiAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb24+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+MmYzYTRiNWM2ZDdlOGY5YTBiMWMyZDNlNGY1YTZiN2M8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX0NvZGUiPkNPTVAtR0Q8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iQ29tcGFueV9Db2RlIj5DT01QLUdEPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fTmFtZT5HbG9iYWwgRHluYW1pY3MgSW5jLjwveGhyOk9yZ2FuaXphdGlvbl9OYW1lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+M2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTRmNWE2YjdjOGQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX1R5cGVfQ29kZSI+Q29tcGFueTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbj4KICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj40YTViNmM3ZDhlOWYwYTFiMmMzZDRlNWY2YTdiOGM5ZDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJPcmdfQ29kZSI+UkVHLVdFU1Q8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iUmVnaW9uX09yZ19Db2RlIj5SRUctV0VTVDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX05hbWU+V2VzdGVybiBSZWdpb248L3hocjpPcmdhbml6YXRpb25fTmFtZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjViNmM3ZDhlOWYwYTFiMmMzZDRlNWY2YTdiOGM5ZDBlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19UeXBlX0NvZGUiPlJlZ2lvbjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbj4KICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX0Fzc2lnbm1lbnRzPgoKICAgICAgICAgICAgICAgIDwveGhyOlBvc2l0aW9uPgoKICAgICAgICAgICAgICAgIDx4aHI6TWFuYWdlcl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YWFiYmNjZGQxMTIyMzM0NDU1NjY3Nzg4OTkwMGFhYmI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfTnVtYmVyIj5FTVAtMTk4MDQ0PC94aHI6SUQ+CiAgICAgICAgICAgICAgICA8L3hocjpNYW5hZ2VyX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICA8eGhyOkVtcGxveW1lbnRfU3RhdHVzPgogICAgICAgICAgICAgICAgICA8eGhyOklzX0FjdGl2ZT50cnVlPC94aHI6SXNfQWN0aXZlPgogICAgICAgICAgICAgICAgICA8eGhyOkFjdGl2ZV9TdGF0dXNfRGF0ZT4yMDIyLTA4LTAxPC94aHI6QWN0aXZlX1N0YXR1c19EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkhpcmVfRGF0ZT4yMDIyLTA4LTAxPC94aHI6SGlyZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOk9yaWdpbmFsX0hpcmVfRGF0ZT4yMDIyLTA4LTAxPC94aHI6T3JpZ2luYWxfSGlyZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkVuZF9FbXBsb3ltZW50X0RhdGUvPgogICAgICAgICAgICAgICAgICA8eGhyOkNvbnRpbnVvdXNfU2VydmljZV9EYXRlPjIwMjItMDgtMDE8L3hocjpDb250aW51b3VzX1NlcnZpY2VfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpGaXJzdF9EYXlfb2ZfV29yaz4yMDIyLTA4LTAxPC94aHI6Rmlyc3RfRGF5X29mX1dvcms+CiAgICAgICAgICAgICAgICAgIDx4aHI6U2VuaW9yaXR5X0RhdGU+MjAyMi0wOC0wMTwveGhyOlNlbmlvcml0eV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkJlbmVmaXRzX1NlcnZpY2VfRGF0ZT4yMDIyLTA4LTAxPC94aHI6QmVuZWZpdHNfU2VydmljZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkNvbXBhbnlfU2VydmljZV9EYXRlPjIwMjItMDgtMDE8L3hocjpDb21wYW55X1NlcnZpY2VfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpJc19SZXRpcmVkPmZhbHNlPC94aHI6SXNfUmV0aXJlZD4KICAgICAgICAgICAgICAgICAgPHhocjpJc19UZXJtaW5hdGVkPmZhbHNlPC94aHI6SXNfVGVybWluYXRlZD4KICAgICAgICAgICAgICAgICAgPHhocjpJc19SZWhpcmU+ZmFsc2U8L3hocjpJc19SZWhpcmU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RGF5c19VbmVtcGxveWVkPjA8L3hocjpEYXlzX1VuZW1wbG95ZWQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6UHJvYmF0aW9uX1N0YXJ0X0RhdGU+MjAyMi0wOC0wMTwveGhyOlByb2JhdGlvbl9TdGFydF9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOlByb2JhdGlvbl9FbmRfRGF0ZT4yMDIzLTAyLTAxPC94aHI6UHJvYmF0aW9uX0VuZF9EYXRlPgogICAgICAgICAgICAgICAgPC94aHI6RW1wbG95bWVudF9TdGF0dXM+CgogICAgICAgICAgICAgIDwveGhyOkpvYl9EYXRhPgogICAgICAgICAgICA8L3hocjpFbXBsb3ltZW50X0RhdGE+CgogICAgICAgICAgPC94aHI6RW1wbG95ZWVfRGF0YT4KICAgICAgICA8L3hocjpFbXBsb3llZT4KCiAgICAgICAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgICAgPCEtLSBFTVBMT1lFRSAyIOKAlCBUZXJtaW5hdGVkIChWb2x1bnRhcnkgUmVzaWduYXRpb24pICAgICAgICAgICAgICAtLT4KICAgICAgICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAtLT4KICAgICAgICA8eGhyOkVtcGxveWVlPgogICAgICAgICAgPHhocjpFbXBsb3llZV9SZWZlcmVuY2U+CiAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+OGRkNzc2MWU5YmY1NGFjN2IwMTFlNWMyM2Q3MGZhOTI8L3hocjpJRD4KICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfTnVtYmVyIj5FTVAtMTg3MjkzPC94aHI6SUQ+CiAgICAgICAgICA8L3hocjpFbXBsb3llZV9SZWZlcmVuY2U+CgogICAgICAgICAgPHhocjpFbXBsb3llZV9EYXRhPgogICAgICAgICAgICA8eGhyOkVtcGxveWVlX051bWJlcj5FTVAtMTg3MjkzPC94aHI6RW1wbG95ZWVfTnVtYmVyPgogICAgICAgICAgICA8eGhyOkxvZ2luX0lEPnRjaGVuPC94aHI6TG9naW5fSUQ+CgogICAgICAgICAgICA8eGhyOlBlcnNvbmFsX0RhdGE+CiAgICAgICAgICAgICAgPHhocjpOYW1lX0RhdGE+CiAgICAgICAgICAgICAgICA8eGhyOkxlZ2FsX05hbWU+CiAgICAgICAgICAgICAgICAgIDx4aHI6TmFtZV9EZXRhaWw+CiAgICAgICAgICAgICAgICAgICAgPHhocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YmMzM2FhMzE1MmVjNDJkNDk5NWY0NzkxYTEwNmVkMDk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMyI+VVNBPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpGaXJzdF9OYW1lPlRhbzwveGhyOkZpcnN0X05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMYXN0X05hbWU+Q2hlbjwveGhyOkxhc3RfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkRpc3BsYXlfTmFtZT5UYW8gQ2hlbjwveGhyOkRpc3BsYXlfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOlNvcnRfTmFtZT5DaGVuLCBUYW88L3hocjpTb3J0X05hbWU+CiAgICAgICAgICAgICAgICAgIDwveGhyOk5hbWVfRGV0YWlsPgogICAgICAgICAgICAgICAgPC94aHI6TGVnYWxfTmFtZT4KICAgICAgICAgICAgICAgIDx4aHI6UHJlZmVycmVkX05hbWU+CiAgICAgICAgICAgICAgICAgIDx4aHI6TmFtZV9EZXRhaWw+CiAgICAgICAgICAgICAgICAgICAgPHhocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YmMzM2FhMzE1MmVjNDJkNDk5NWY0NzkxYTEwNmVkMDk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkZpcnN0X05hbWU+VGFvPC94aHI6Rmlyc3RfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkxhc3RfTmFtZT5DaGVuPC94aHI6TGFzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6RGlzcGxheV9OYW1lPlRhbyBDaGVuPC94aHI6RGlzcGxheV9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6U29ydF9OYW1lPkNoZW4sIFRhbzwveGhyOlNvcnRfTmFtZT4KICAgICAgICAgICAgICAgICAgPC94aHI6TmFtZV9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpQcmVmZXJyZWRfTmFtZT4KICAgICAgICAgICAgICA8L3hocjpOYW1lX0RhdGE+CgogICAgICAgICAgICAgIDx4aHI6Q29udGFjdF9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpFbWFpbD4KICAgICAgICAgICAgICAgICAgPHhocjpFbWFpbF9BZGRyZXNzPnRhby5jaGVuQGdsb2JhbGR5bmFtaWNzLmNvbTwveGhyOkVtYWlsX0FkZHJlc3M+CiAgICAgICAgICAgICAgICAgIDx4aHI6VXNhZ2UgeGhyOlB1YmxpYz0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX0luZm8geGhyOlByaW1hcnk9InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5kMGUxZjJhM2I0YzVkNmU3ZjhhOWIwYzFkMmUzZjRhNTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJVc2FnZV9UeXBlX0NvZGUiPldPUks8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfSW5mbz4KICAgICAgICAgICAgICAgICAgPC94aHI6VXNhZ2U+CiAgICAgICAgICAgICAgICA8L3hocjpFbWFpbD4KCiAgICAgICAgICAgICAgICA8eGhyOlBob25lPgogICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfQ29kZT4xPC94aHI6Q291bnRyeV9Db2RlPgogICAgICAgICAgICAgICAgICA8eGhyOkFyZWFfQ29kZT4zMTI8L3hocjpBcmVhX0NvZGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6TnVtYmVyPjU1NS0wNDkxPC94aHI6TnVtYmVyPgogICAgICAgICAgICAgICAgICA8eGhyOkRldmljZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmU0ZjVhNmI3YzhkOWUwZjFhMmIzYzRkNWU2ZjdhOGI5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRGV2aWNlX1R5cGVfQ29kZSI+TGFuZGxpbmU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6RGV2aWNlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOlVzYWdlIHhocjpQdWJsaWM9InRydWUiPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9JbmZvIHhocjpQcmltYXJ5PSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZDBlMWYyYTNiNGM1ZDZlN2Y4YTliMGMxZDJlM2Y0YTU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVXNhZ2VfVHlwZV9Db2RlIj5XT1JLPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX0luZm8+CiAgICAgICAgICAgICAgICAgIDwveGhyOlVzYWdlPgogICAgICAgICAgICAgICAgICA8eGhyOkZvcm1hdHRlZF9OdW1iZXI+KzEgKDMxMikgNTU1LTA0OTE8L3hocjpGb3JtYXR0ZWRfTnVtYmVyPgogICAgICAgICAgICAgICAgPC94aHI6UGhvbmU+CgogICAgICAgICAgICAgICAgPHhocjpBZGRyZXNzPgogICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YmMzM2FhMzE1MmVjNDJkNDk5NWY0NzkxYTEwNmVkMDk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTIiPlVTPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOkxhc3RfTW9kaWZpZWQ+MjAyNC0wMy0yMlQxMDo0NTowMC4wMDAtMDY6MDA8L3hocjpMYXN0X01vZGlmaWVkPgogICAgICAgICAgICAgICAgICA8eGhyOkxpbmUgeGhyOlR5cGU9IkxJTkVfMSI+NDQwIE5vcnRoIFdhYmFzaCBBdmVudWU8L3hocjpMaW5lPgogICAgICAgICAgICAgICAgICA8eGhyOkxpbmUgeGhyOlR5cGU9IkxJTkVfMiI+QXB0IDI3MDE8L3hocjpMaW5lPgogICAgICAgICAgICAgICAgICA8eGhyOkNpdHk+Q2hpY2FnbzwveGhyOkNpdHk+CiAgICAgICAgICAgICAgICAgIDx4aHI6UmVnaW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmMwZDFlMmYzYTRiNWM2ZDdlOGY5YTBiMWMyZDNlNGY1PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iUmVnaW9uX0NvZGUiPlVTQS1JTDwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpSZWdpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9OYW1lPklsbGlub2lzPC94aHI6UmVnaW9uX05hbWU+CiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zdGFsX0NvZGU+NjA2MTE8L3hocjpQb3N0YWxfQ29kZT4KICAgICAgICAgICAgICAgICAgPHhocjpGb3JtYXR0ZWRfQWRkcmVzcz40NDAgTm9ydGggV2FiYXNoIEF2ZW51ZSwgQXB0IDI3MDEsIENoaWNhZ28sIElMIDYwNjExLCBVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2E8L3hocjpGb3JtYXR0ZWRfQWRkcmVzcz4KICAgICAgICAgICAgICAgICAgPHhocjpJc19CdXNpbmVzc19TaXRlX0RlZmF1bHQ+ZmFsc2U8L3hocjpJc19CdXNpbmVzc19TaXRlX0RlZmF1bHQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6VXNhZ2UgeGhyOlB1YmxpYz0iZmFsc2UiPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9JbmZvIHhocjpQcmltYXJ5PSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YTFiMmMzZDRlNWY2YTdiOGM5ZDBlMWYyYTNiNGM1ZDY8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVXNhZ2VfVHlwZV9Db2RlIj5IT01FPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX0luZm8+CiAgICAgICAgICAgICAgICAgIDwveGhyOlVzYWdlPgogICAgICAgICAgICAgICAgPC94aHI6QWRkcmVzcz4KICAgICAgICAgICAgICA8L3hocjpDb250YWN0X0RhdGE+CgogICAgICAgICAgICAgIDx4aHI6QmlvZ3JhcGhpY2FsX0RhdGE+CiAgICAgICAgICAgICAgICA8eGhyOkRhdGVfb2ZfQmlydGg+MTk4NS0xMi0wOTwveGhyOkRhdGVfb2ZfQmlydGg+CiAgICAgICAgICAgICAgICA8eGhyOkdlbmRlcl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+MGExYjJjM2Q0ZTVmNmE3YjhjOWQwZTFmMmEzYjRjNWQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR2VuZGVyX0NvZGUiPk1hbGU8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOkdlbmRlcl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfb2ZfQmlydGhfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmRkNDRlZTU1ZmY2NjAwNzc4ODk5MDAxMTIyMzM0NGJiPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+Q048L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfb2ZfQmlydGhfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgPHhocjpNYXJpdGFsX1N0YXR1c19SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YzRkNWU2ZjdhOGI5YzBkMWUyZjNhNGI1YzZkN2U4Zjk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTWFyaXRhbF9TdGF0dXNfQ29kZSI+TWFycmllZDwveGhyOklEPgogICAgICAgICAgICAgICAgPC94aHI6TWFyaXRhbF9TdGF0dXNfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgPHhocjpNYXJpdGFsX1N0YXR1c19EYXRlPjIwMTUtMDUtMjA8L3hocjpNYXJpdGFsX1N0YXR1c19EYXRlPgogICAgICAgICAgICAgIDwveGhyOkJpb2dyYXBoaWNhbF9EYXRhPgoKICAgICAgICAgICAgICA8eGhyOklkZW50aWZpY2F0aW9uX0RhdGE+CiAgICAgICAgICAgICAgICA8eGhyOk5hdGlvbmFsX0lEPgogICAgICAgICAgICAgICAgICA8eGhyOk5hdGlvbmFsX0lEX0RldGFpbD4KICAgICAgICAgICAgICAgICAgICA8eGhyOlZhbHVlPioqKi0qKi0zNDU2PC94aHI6VmFsdWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZThmOWEwYjFjMmQzZTRmNWE2YjdjOGQ5ZTBmMWEyYjM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik5hdGlvbmFsX0lEX1R5cGUiPlVTQS1TU048L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5iYzMzYWEzMTUyZWM0MmQ0OTk1ZjQ3OTFhMTA2ZWQwOTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5VUzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8L3hocjpOYXRpb25hbF9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpOYXRpb25hbF9JRD4KICAgICAgICAgICAgICA8L3hocjpJZGVudGlmaWNhdGlvbl9EYXRhPgoKICAgICAgICAgICAgPC94aHI6UGVyc29uYWxfRGF0YT4KCiAgICAgICAgICAgIDx4aHI6RW1wbG95bWVudF9EYXRhPgogICAgICAgICAgICAgIDx4aHI6Sm9iX0RhdGE+CiAgICAgICAgICAgICAgICA8eGhyOlBvc2l0aW9uPgogICAgICAgICAgICAgICAgICA8eGhyOlBvc2l0aW9uX0lEPlBPUy0wMDY3NDQ8L3hocjpQb3NpdGlvbl9JRD4KICAgICAgICAgICAgICAgICAgPHhocjpQb3NpdGlvbl9UaXRsZT5NYXJrZXRpbmcgTWFuYWdlcjwveGhyOlBvc2l0aW9uX1RpdGxlPgogICAgICAgICAgICAgICAgICA8eGhyOkJ1c2luZXNzX1RpdGxlPlNlbmlvciBNYXJrZXRpbmcgTWFuYWdlcjwveGhyOkJ1c2luZXNzX1RpdGxlPgogICAgICAgICAgICAgICAgICA8eGhyOlN0YXJ0X0RhdGU+MjAyMy0wMy0wMTwveGhyOlN0YXJ0X0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RW5kX0RhdGU+MjAyNi0wMS0xNTwveGhyOkVuZF9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkRlZmF1bHRfV2Vla2x5X0hvdXJzPjQwPC94aHI6RGVmYXVsdF9XZWVrbHlfSG91cnM+CiAgICAgICAgICAgICAgICAgIDx4aHI6U2NoZWR1bGVkX1dlZWtseV9Ib3Vycz40MDwveGhyOlNjaGVkdWxlZF9XZWVrbHlfSG91cnM+CiAgICAgICAgICAgICAgICAgIDx4aHI6RlRFX1BlcmNlbnRhZ2U+MTAwPC94aHI6RlRFX1BlcmNlbnRhZ2U+CgogICAgICAgICAgICAgICAgICA8eGhyOlBvc2l0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmNjZDhlOWYwYTFiMmMzZDRlNWY2YTdiOGM5ZDBlMWYyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iUG9zaXRpb25fSUQiPlBPUy0wMDY3NDQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UG9zaXRpb25fUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpFbXBsb3llZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmQ0ZTVmNmE3YjhjOWQwZTFmMmEzYjRjNWQ2ZTdmOGE5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfVHlwZV9Db2RlIj5SZWd1bGFyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkVtcGxveWVlX1R5cGVfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpKb2JfUHJvZmlsZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkpvYl9Qcm9maWxlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YWExMWJiMjJjYzMzZGQ0NGVlNTVmZjY2MDA3Nzg4OTk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkpvYl9Qcm9maWxlX0NvZGUiPkpQLU1LVC1NR1I8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpKb2JfUHJvZmlsZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfUHJvZmlsZV9OYW1lPk1hcmtldGluZyBNYW5hZ2VyPC94aHI6Sm9iX1Byb2ZpbGVfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOk1hbmFnZW1lbnRfTGV2ZWxfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj42YzdkOGU5ZjBhMWIyYzNkNGU1ZjZhN2I4YzlkMGUxZjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTWFuYWdlbWVudF9MZXZlbF9Db2RlIj5NYW5hZ2VyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TWFuYWdlbWVudF9MZXZlbF9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfQ2F0ZWdvcnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5iYjIyY2MzM2RkNDRlZTU1ZmY2NjAwNzc4ODk5MDAxMTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSm9iX0NhdGVnb3J5X0NvZGUiPk1hcmtldGluZzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkpvYl9DYXRlZ29yeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfRmFtaWx5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+Y2MzM2RkNDRlZTU1ZmY2NjAwNzc4ODk5MDAxMTIyMzM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkpvYl9GYW1pbHlfQ29kZSI+SkYtTWFya2V0aW5nPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Sm9iX0ZhbWlseV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDwveGhyOkpvYl9Qcm9maWxlPgoKICAgICAgICAgICAgICAgICAgPHhocjpXb3JrX0xvY2F0aW9uPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TG9jYXRpb25fTmFtZT5DaGljYWdvIE9mZmljZTwveGhyOkxvY2F0aW9uX05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMb2NhdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmRkNDRlZTU1ZmY2NjAwNzc4ODk5MDAxMTIyMzM0NGFhPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMb2NhdGlvbl9Db2RlIj5MT0MtQ0hJLTAxPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TG9jYXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TG9jYXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMb2NhdGlvbl9UeXBlX0NvZGUiPk9mZmljZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkxvY2F0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6QWRkcmVzcz4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpMaW5lIHhocjpUeXBlPSJMSU5FXzEiPjIzMyBTb3V0aCBXYWNrZXIgRHJpdmU8L3hocjpMaW5lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpMaW5lIHhocjpUeXBlPSJMSU5FXzIiPlN1aXRlIDQ4MDA8L3hocjpMaW5lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpDaXR5PkNoaWNhZ288L3hocjpDaXR5PgogICAgICAgICAgICAgICAgICAgICAgPHhocjpSZWdpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJSZWdpb25fQ29kZSI+VVNBLUlMPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpSZWdpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpSZWdpb25fTmFtZT5JbGxpbm9pczwveGhyOlJlZ2lvbl9OYW1lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpQb3N0YWxfQ29kZT42MDYwNjwveGhyOlBvc3RhbF9Db2RlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkFkZHJlc3M+CiAgICAgICAgICAgICAgICAgIDwveGhyOldvcmtfTG9jYXRpb24+CgogICAgICAgICAgICAgICAgICA8eGhyOlBheV9SYXRlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+N2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJQYXlfUmF0ZV9UeXBlX0NvZGUiPlNhbGFyeTwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpQYXlfUmF0ZV9UeXBlX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6VGltZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjhiOWMwZDFlMmYzYTRiNWM2ZDdlOGY5YTBiMWMyZDNlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVGltZV9UeXBlX0NvZGUiPkZ1bGxfVGltZTwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpUaW1lX1R5cGVfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpTdXBlcnZpc29yeV9PcmdfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZWU1NWZmNjYwMDc3ODg5OTAwMTEyMjMzNDQ1NTY2YmI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJPcmdfQ29kZSI+TUtULUJSQU5ELTAwMTwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpTdXBlcnZpc29yeV9PcmdfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fQXNzaWdubWVudHM+CiAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb24+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZmY2NjAwNzc4ODk5MDAxMTIyMzM0NDU1NjY3Nzg4OTk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX0NvZGUiPkNDLTUyMDA8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iQ29zdF9DZW50ZXJfQ29kZSI+Q0MtNTIwMDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX05hbWU+TWFya2V0aW5nIC0gQnJhbmQ8L3hocjpPcmdhbml6YXRpb25fTmFtZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjFlMmYzYTRiNWM2ZDdlOGY5YTBiMWMyZDNlNGY1YTZiPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19UeXBlX0NvZGUiPkNvc3RfQ2VudGVyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uPgogICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTRmNWE2YjdjPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19Db2RlIj5DT01QLUdEPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkNvbXBhbnlfQ29kZSI+Q09NUC1HRDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX05hbWU+R2xvYmFsIER5bmFtaWNzIEluYy48L3hocjpPcmdhbml6YXRpb25fTmFtZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhNmI3YzhkPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19UeXBlX0NvZGUiPkNvbXBhbnk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb24+CiAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9Bc3NpZ25tZW50cz4KCiAgICAgICAgICAgICAgICA8L3hocjpQb3NpdGlvbj4KCiAgICAgICAgICAgICAgICA8eGhyOk1hbmFnZXJfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjExMjIzMzQ0NTU2Njc3ODg5OTAwMTFhYWJiY2NkZGVlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkVtcGxveWVlX051bWJlciI+RU1QLTE3NjAwMjwveGhyOklEPgogICAgICAgICAgICAgICAgPC94aHI6TWFuYWdlcl9SZWZlcmVuY2U+CgogICAgICAgICAgICAgICAgPHhocjpFbXBsb3ltZW50X1N0YXR1cz4KICAgICAgICAgICAgICAgICAgPHhocjpJc19BY3RpdmU+ZmFsc2U8L3hocjpJc19BY3RpdmU+CiAgICAgICAgICAgICAgICAgIDx4aHI6QWN0aXZlX1N0YXR1c19EYXRlPjIwMjEtMDktMTU8L3hocjpBY3RpdmVfU3RhdHVzX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6SGlyZV9EYXRlPjIwMjEtMDktMTU8L3hocjpIaXJlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6T3JpZ2luYWxfSGlyZV9EYXRlPjIwMjEtMDktMTU8L3hocjpPcmlnaW5hbF9IaXJlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RW5kX0VtcGxveW1lbnRfRGF0ZT4yMDI2LTAxLTE1PC94aHI6RW5kX0VtcGxveW1lbnRfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpDb250aW51b3VzX1NlcnZpY2VfRGF0ZT4yMDIxLTA5LTE1PC94aHI6Q29udGludW91c19TZXJ2aWNlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6Rmlyc3RfRGF5X29mX1dvcms+MjAyMS0wOS0xNTwveGhyOkZpcnN0X0RheV9vZl9Xb3JrPgogICAgICAgICAgICAgICAgICA8eGhyOlNlbmlvcml0eV9EYXRlPjIwMjEtMDktMTU8L3hocjpTZW5pb3JpdHlfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpCZW5lZml0c19TZXJ2aWNlX0RhdGU+MjAyMS0wOS0xNTwveGhyOkJlbmVmaXRzX1NlcnZpY2VfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpDb21wYW55X1NlcnZpY2VfRGF0ZT4yMDIxLTA5LTE1PC94aHI6Q29tcGFueV9TZXJ2aWNlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfUmV0aXJlZD5mYWxzZTwveGhyOklzX1JldGlyZWQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfVGVybWluYXRlZD50cnVlPC94aHI6SXNfVGVybWluYXRlZD4KICAgICAgICAgICAgICAgICAgPHhocjpUZXJtaW5hdGlvbl9EYXRlPjIwMjYtMDEtMTU8L3hocjpUZXJtaW5hdGlvbl9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOlBheV9UaHJvdWdoX0RhdGU+MjAyNi0wMS0zMTwveGhyOlBheV9UaHJvdWdoX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6VGVybWluYXRpb25fQ2F0ZWdvcnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YWFiYjExMjJjY2RkMzM0NGVlZmY1NTY2YWFiYjc3ODg8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJUZXJtaW5hdGlvbl9DYXRlZ29yeV9Db2RlIj5Wb2x1bnRhcnk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6VGVybWluYXRpb25fQ2F0ZWdvcnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOlByaW1hcnlfVGVybWluYXRpb25fUmVhc29uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmNjZGQzMzQ0ZWVmZjU1NjZhYWJiNzc4ODk5MDAxMTIyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVGVybWluYXRpb25fUmVhc29uX0NvZGUiPlJlc2lnbmF0aW9uX05ld19PcHBvcnR1bml0eTwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpQcmltYXJ5X1Rlcm1pbmF0aW9uX1JlYXNvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfUmVoaXJlPmZhbHNlPC94aHI6SXNfUmVoaXJlPgogICAgICAgICAgICAgICAgICA8eGhyOkRheXNfVW5lbXBsb3llZD4wPC94aHI6RGF5c19VbmVtcGxveWVkPgogICAgICAgICAgICAgICAgICA8eGhyOk5vdF9SZXR1cm5pbmc+dHJ1ZTwveGhyOk5vdF9SZXR1cm5pbmc+CiAgICAgICAgICAgICAgICAgIDx4aHI6UmVzaWduYXRpb25fRGF0ZT4yMDI1LTEyLTE1PC94aHI6UmVzaWduYXRpb25fRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpMYXN0X0RheV9vZl9Xb3JrPjIwMjYtMDEtMTQ8L3hocjpMYXN0X0RheV9vZl9Xb3JrPgogICAgICAgICAgICAgICAgICA8eGhyOkVsaWdpYmxlX2Zvcl9SZWhpcmVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZWVmZjU1NjZhYWJiNzc4ODk5MDAxMTIyY2NkZDMzNDQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJSZWhpcmVfRWxpZ2liaWxpdHlfQ29kZSI+WWVzPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkVsaWdpYmxlX2Zvcl9SZWhpcmVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgPC94aHI6RW1wbG95bWVudF9TdGF0dXM+CgogICAgICAgICAgICAgIDwveGhyOkpvYl9EYXRhPgogICAgICAgICAgICA8L3hocjpFbXBsb3ltZW50X0RhdGE+CgogICAgICAgICAgPC94aHI6RW1wbG95ZWVfRGF0YT4KICAgICAgICA8L3hocjpFbXBsb3llZT4KCiAgICAgICAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgICAgPCEtLSBFTVBMT1lFRSAzIOKAlCBBY3RpdmUsIE9uIExlYXZlIChQYXJlbnRhbCkgICAgICAgICAgICAgICAgICAgICAtLT4KICAgICAgICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAtLT4KICAgICAgICA8eGhyOkVtcGxveWVlPgogICAgICAgICAgPHhocjpFbXBsb3llZV9SZWZlcmVuY2U+CiAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZjdlNmQ1YzRiM2EyOTE4MDcwNjA1MDQwMzAyMDEwZmY8L3hocjpJRD4KICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfTnVtYmVyIj5FTVAtMjExMzA1PC94aHI6SUQ+CiAgICAgICAgICA8L3hocjpFbXBsb3llZV9SZWZlcmVuY2U+CgogICAgICAgICAgPHhocjpFbXBsb3llZV9EYXRhPgogICAgICAgICAgICA8eGhyOkVtcGxveWVlX051bWJlcj5FTVAtMjExMzA1PC94aHI6RW1wbG95ZWVfTnVtYmVyPgogICAgICAgICAgICA8eGhyOkxvZ2luX0lEPnNqb2hhbnNzb248L3hocjpMb2dpbl9JRD4KCiAgICAgICAgICAgIDx4aHI6UGVyc29uYWxfRGF0YT4KICAgICAgICAgICAgICA8eGhyOk5hbWVfRGF0YT4KICAgICAgICAgICAgICAgIDx4aHI6TGVnYWxfTmFtZT4KICAgICAgICAgICAgICAgICAgPHhocjpOYW1lX0RldGFpbD4KICAgICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5lZTQ0ZmY1NTAwNjY3Nzg4OTkxMTIyMzM0NDU1YWFiYjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5TRTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEzIj5TV0U8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkZpcnN0X05hbWU+U29maWE8L3hocjpGaXJzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TWlkZGxlX05hbWU+TGlubsOpYTwveGhyOk1pZGRsZV9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TGFzdF9OYW1lPkpvaGFuc3NvbjwveGhyOkxhc3RfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkRpc3BsYXlfTmFtZT5Tb2ZpYSBMaW5uw6lhIEpvaGFuc3NvbjwveGhyOkRpc3BsYXlfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOlNvcnRfTmFtZT5Kb2hhbnNzb24sIFNvZmlhIExpbm7DqWE8L3hocjpTb3J0X05hbWU+CiAgICAgICAgICAgICAgICAgIDwveGhyOk5hbWVfRGV0YWlsPgogICAgICAgICAgICAgICAgPC94aHI6TGVnYWxfTmFtZT4KICAgICAgICAgICAgICAgIDx4aHI6UHJlZmVycmVkX05hbWU+CiAgICAgICAgICAgICAgICAgIDx4aHI6TmFtZV9EZXRhaWw+CiAgICAgICAgICAgICAgICAgICAgPHhocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YmMzM2FhMzE1MmVjNDJkNDk5NWY0NzkxYTEwNmVkMDk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkZpcnN0X05hbWU+U29maWE8L3hocjpGaXJzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TGFzdF9OYW1lPkpvaGFuc3NvbjwveGhyOkxhc3RfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkRpc3BsYXlfTmFtZT5Tb2ZpYSBKb2hhbnNzb248L3hocjpEaXNwbGF5X05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpTb3J0X05hbWU+Sm9oYW5zc29uLCBTb2ZpYTwveGhyOlNvcnRfTmFtZT4KICAgICAgICAgICAgICAgICAgPC94aHI6TmFtZV9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpQcmVmZXJyZWRfTmFtZT4KICAgICAgICAgICAgICA8L3hocjpOYW1lX0RhdGE+CgogICAgICAgICAgICAgIDx4aHI6Q29udGFjdF9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpFbWFpbD4KICAgICAgICAgICAgICAgICAgPHhocjpFbWFpbF9BZGRyZXNzPnNvZmlhLmpvaGFuc3NvbkBnbG9iYWxkeW5hbWljcy5jb208L3hocjpFbWFpbF9BZGRyZXNzPgogICAgICAgICAgICAgICAgICA8eGhyOlVzYWdlIHhocjpQdWJsaWM9InRydWUiPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9JbmZvIHhocjpQcmltYXJ5PSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZDBlMWYyYTNiNGM1ZDZlN2Y4YTliMGMxZDJlM2Y0YTU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iVXNhZ2VfVHlwZV9Db2RlIj5XT1JLPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpUeXBlX0luZm8+CiAgICAgICAgICAgICAgICAgIDwveGhyOlVzYWdlPgogICAgICAgICAgICAgICAgPC94aHI6RW1haWw+CgogICAgICAgICAgICAgICAgPHhocjpFbWFpbD4KICAgICAgICAgICAgICAgICAgPHhocjpFbWFpbF9BZGRyZXNzPnNvZmlhLmpvaGFuc3NvbkBwcm90b24ubWU8L3hocjpFbWFpbF9BZGRyZXNzPgogICAgICAgICAgICAgICAgICA8eGhyOlVzYWdlIHhocjpQdWJsaWM9ImZhbHNlIj4KICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfSW5mbyB4aHI6UHJpbWFyeT0iZmFsc2UiPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5hMWIyYzNkNGU1ZjZhN2I4YzlkMGUxZjJhM2I0YzVkNjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJVc2FnZV9UeXBlX0NvZGUiPkhPTUU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfSW5mbz4KICAgICAgICAgICAgICAgICAgPC94aHI6VXNhZ2U+CiAgICAgICAgICAgICAgICA8L3hocjpFbWFpbD4KCiAgICAgICAgICAgICAgICA8eGhyOlBob25lPgogICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfQ29kZT4xPC94aHI6Q291bnRyeV9Db2RlPgogICAgICAgICAgICAgICAgICA8eGhyOkFyZWFfQ29kZT4yMDY8L3hocjpBcmVhX0NvZGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6TnVtYmVyPjU1NS0wODM0PC94aHI6TnVtYmVyPgogICAgICAgICAgICAgICAgICA8eGhyOkRldmljZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmY1YTZiN2M4ZDllMGYxYTJiM2M0ZDVlNmY3YThiOWMwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRGV2aWNlX1R5cGVfQ29kZSI+TW9iaWxlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkRldmljZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpVc2FnZSB4aHI6UHVibGljPSJmYWxzZSI+CiAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX0luZm8geGhyOlByaW1hcnk9InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5hMWIyYzNkNGU1ZjZhN2I4YzlkMGUxZjJhM2I0YzVkNjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJVc2FnZV9UeXBlX0NvZGUiPkhPTUU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfSW5mbz4KICAgICAgICAgICAgICAgICAgPC94aHI6VXNhZ2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6Rm9ybWF0dGVkX051bWJlcj4rMSAoMjA2KSA1NTUtMDgzNDwveGhyOkZvcm1hdHRlZF9OdW1iZXI+CiAgICAgICAgICAgICAgICA8L3hocjpQaG9uZT4KCiAgICAgICAgICAgICAgICA8eGhyOkFkZHJlc3M+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5iYzMzYWEzMTUyZWM0MmQ0OTk1ZjQ3OTFhMTA2ZWQwOTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6TGFzdF9Nb2RpZmllZD4yMDI1LTA2LTAxVDExOjAwOjAwLjAwMC0wODowMDwveGhyOkxhc3RfTW9kaWZpZWQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6TGluZSB4aHI6VHlwZT0iTElORV8xIj4zMDE0IE5FIDU1dGggU3RyZWV0PC94aHI6TGluZT4KICAgICAgICAgICAgICAgICAgPHhocjpDaXR5PlNlYXR0bGU8L3hocjpDaXR5PgogICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5kMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhNjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlJlZ2lvbl9Db2RlIj5VU0EtV0E8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UmVnaW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpSZWdpb25fTmFtZT5XYXNoaW5ndG9uPC94aHI6UmVnaW9uX05hbWU+CiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zdGFsX0NvZGU+OTgxMDU8L3hocjpQb3N0YWxfQ29kZT4KICAgICAgICAgICAgICAgICAgPHhocjpGb3JtYXR0ZWRfQWRkcmVzcz4zMDE0IE5FIDU1dGggU3RyZWV0LCBTZWF0dGxlLCBXQSA5ODEwNSwgVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhPC94aHI6Rm9ybWF0dGVkX0FkZHJlc3M+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfQnVzaW5lc3NfU2l0ZV9EZWZhdWx0PmZhbHNlPC94aHI6SXNfQnVzaW5lc3NfU2l0ZV9EZWZhdWx0PgogICAgICAgICAgICAgICAgICA8eGhyOlVzYWdlIHhocjpQdWJsaWM9ImZhbHNlIj4KICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfSW5mbyB4aHI6UHJpbWFyeT0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmExYjJjM2Q0ZTVmNmE3YjhjOWQwZTFmMmEzYjRjNWQ2PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlVzYWdlX1R5cGVfQ29kZSI+SE9NRTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6VHlwZV9JbmZvPgogICAgICAgICAgICAgICAgICA8L3hocjpVc2FnZT4KICAgICAgICAgICAgICAgIDwveGhyOkFkZHJlc3M+CiAgICAgICAgICAgICAgPC94aHI6Q29udGFjdF9EYXRhPgoKICAgICAgICAgICAgICA8eGhyOkJpb2dyYXBoaWNhbF9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpEYXRlX29mX0JpcnRoPjE5OTMtMDItMTQ8L3hocjpEYXRlX29mX0JpcnRoPgogICAgICAgICAgICAgICAgPHhocjpHZW5kZXJfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjlhMGIxYzJkM2U0ZjVhNmI3YzhkOWUwZjFhMmIzYzRkPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdlbmRlcl9Db2RlIj5GZW1hbGU8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOkdlbmRlcl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfb2ZfQmlydGhfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmVlNDRmZjU1MDA2Njc3ODg5OTExMjIzMzQ0NTVhYWJiPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+U0U8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfb2ZfQmlydGhfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgPHhocjpNYXJpdGFsX1N0YXR1c19SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZTZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTWFyaXRhbF9TdGF0dXNfQ29kZSI+RG9tZXN0aWNfUGFydG5lcnNoaXA8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOk1hcml0YWxfU3RhdHVzX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgIDx4aHI6TWFyaXRhbF9TdGF0dXNfRGF0ZT4yMDIzLTAxLTEwPC94aHI6TWFyaXRhbF9TdGF0dXNfRGF0ZT4KICAgICAgICAgICAgICA8L3hocjpCaW9ncmFwaGljYWxfRGF0YT4KCiAgICAgICAgICAgICAgPHhocjpJZGVudGlmaWNhdGlvbl9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpOYXRpb25hbF9JRD4KICAgICAgICAgICAgICAgICAgPHhocjpOYXRpb25hbF9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICAgICAgPHhocjpWYWx1ZT4qKiotKiotNTUxMjwveGhyOlZhbHVlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SURfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmU4ZjlhMGIxYzJkM2U0ZjVhNmI3YzhkOWUwZjFhMmIzPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJOYXRpb25hbF9JRF9UeXBlIj5VU0EtU1NOPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6SURfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YmMzM2FhMzE1MmVjNDJkNDk5NWY0NzkxYTEwNmVkMDk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPC94aHI6TmF0aW9uYWxfSURfRGV0YWlsPgogICAgICAgICAgICAgICAgPC94aHI6TmF0aW9uYWxfSUQ+CiAgICAgICAgICAgICAgICA8IS0tIE5vdGU6IGFsc28gaG9sZHMgYSBTd2VkaXNoIHBlcnNvbmFsIGlkZW50aXR5IG51bWJlciAtLT4KICAgICAgICAgICAgICAgIDx4aHI6TmF0aW9uYWxfSUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6TmF0aW9uYWxfSURfRGV0YWlsPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VmFsdWU+OTMwMjE0LVhYWFg8L3hocjpWYWx1ZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5hMGIxYzJkM2U0ZjVhNmI3YzhkOWUwZjFhMmIzYzRkNTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTmF0aW9uYWxfSURfVHlwZSI+U1dFLVBJTjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOklEX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmVlNDRmZjU1MDA2Njc3ODg5OTExMjIzMzQ0NTVhYWJiPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTIiPlNFPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJc3N1ZWRfRGF0ZT4xOTkzLTAyLTE0PC94aHI6SXNzdWVkX0RhdGU+CiAgICAgICAgICAgICAgICAgIDwveGhyOk5hdGlvbmFsX0lEX0RldGFpbD4KICAgICAgICAgICAgICAgIDwveGhyOk5hdGlvbmFsX0lEPgogICAgICAgICAgICAgIDwveGhyOklkZW50aWZpY2F0aW9uX0RhdGE+CgogICAgICAgICAgICA8L3hocjpQZXJzb25hbF9EYXRhPgoKICAgICAgICAgICAgPHhocjpFbXBsb3ltZW50X0RhdGE+CiAgICAgICAgICAgICAgPHhocjpKb2JfRGF0YT4KICAgICAgICAgICAgICAgIDx4aHI6UG9zaXRpb24+CiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zaXRpb25fSUQ+UE9TLTAxMDg4MTwveGhyOlBvc2l0aW9uX0lEPgogICAgICAgICAgICAgICAgICA8eGhyOlBvc2l0aW9uX1RpdGxlPlVYIFJlc2VhcmNoIExlYWQ8L3hocjpQb3NpdGlvbl9UaXRsZT4KICAgICAgICAgICAgICAgICAgPHhocjpCdXNpbmVzc19UaXRsZT5VWCBSZXNlYXJjaCBMZWFkPC94aHI6QnVzaW5lc3NfVGl0bGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6U3RhcnRfRGF0ZT4yMDI0LTA2LTAxPC94aHI6U3RhcnRfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpEZWZhdWx0X1dlZWtseV9Ib3Vycz40MDwveGhyOkRlZmF1bHRfV2Vla2x5X0hvdXJzPgogICAgICAgICAgICAgICAgICA8eGhyOlNjaGVkdWxlZF9XZWVrbHlfSG91cnM+MDwveGhyOlNjaGVkdWxlZF9XZWVrbHlfSG91cnM+CiAgICAgICAgICAgICAgICAgIDx4aHI6RlRFX1BlcmNlbnRhZ2U+MTAwPC94aHI6RlRFX1BlcmNlbnRhZ2U+CgogICAgICAgICAgICAgICAgICA8eGhyOlBvc2l0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjExMjJhYWJiMzM0NGNjZGQ1NTY2ZWVmZjc3ODhhMWIyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iUG9zaXRpb25fSUQiPlBPUy0wMTA4ODE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UG9zaXRpb25fUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpFbXBsb3llZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmQ0ZTVmNmE3YjhjOWQwZTFmMmEzYjRjNWQ2ZTdmOGE5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfVHlwZV9Db2RlIj5SZWd1bGFyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkVtcGxveWVlX1R5cGVfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpKb2JfUHJvZmlsZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkpvYl9Qcm9maWxlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YmIxMWNjMjJkZDMzZWU0NGZmNTUwMDY2Nzc4ODk5YWE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkpvYl9Qcm9maWxlX0NvZGUiPkpQLVVYUi1MRUFEPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Sm9iX1Byb2ZpbGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Sm9iX1Byb2ZpbGVfTmFtZT5VWCBSZXNlYXJjaCBMZWFkPC94aHI6Sm9iX1Byb2ZpbGVfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOk1hbmFnZW1lbnRfTGV2ZWxfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj42YzdkOGU5ZjBhMWIyYzNkNGU1ZjZhN2I4YzlkMGUxZjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTWFuYWdlbWVudF9MZXZlbF9Db2RlIj5NYW5hZ2VyPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TWFuYWdlbWVudF9MZXZlbF9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfQ2F0ZWdvcnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5jYzIyZGQzM2VlNDRmZjU1MDA2Njc3ODg5OTAwMTFiYjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSm9iX0NhdGVnb3J5X0NvZGUiPkRlc2lnbjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkpvYl9DYXRlZ29yeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfRmFtaWx5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZGQzM2VlNDRmZjU1MDA2Njc3ODg5OTAwMTEyMmNjYmI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkpvYl9GYW1pbHlfQ29kZSI+SkYtRGVzaWduLVJlc2VhcmNoPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Sm9iX0ZhbWlseV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDwveGhyOkpvYl9Qcm9maWxlPgoKICAgICAgICAgICAgICAgICAgPHhocjpXb3JrX0xvY2F0aW9uPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TG9jYXRpb25fTmFtZT5TZWF0dGxlIE9mZmljZTwveGhyOkxvY2F0aW9uX05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMb2NhdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmVlNDRmZjU1MDA2Njc3ODg5OTExMjIzMzQ0NTU2Njc3PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMb2NhdGlvbl9Db2RlIj5MT0MtU0VBLTAxPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TG9jYXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TG9jYXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMb2NhdGlvbl9UeXBlX0NvZGUiPk9mZmljZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkxvY2F0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6QWRkcmVzcz4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IklTT18zMTY2X0FscGhhMiI+VVM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpMaW5lIHhocjpUeXBlPSJMSU5FXzEiPjcwMSBQaWtlIFN0cmVldDwveGhyOkxpbmU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOkxpbmUgeGhyOlR5cGU9IkxJTkVfMiI+Rmxvb3IgODwveGhyOkxpbmU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOkNpdHk+U2VhdHRsZTwveGhyOkNpdHk+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlJlZ2lvbl9Db2RlIj5VU0EtV0E8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlJlZ2lvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9OYW1lPldhc2hpbmd0b248L3hocjpSZWdpb25fTmFtZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6UG9zdGFsX0NvZGU+OTgxMDE8L3hocjpQb3N0YWxfQ29kZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpBZGRyZXNzPgogICAgICAgICAgICAgICAgICA8L3hocjpXb3JrX0xvY2F0aW9uPgoKICAgICAgICAgICAgICAgICAgPHhocjpQYXlfUmF0ZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjdhOGI5YzBkMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iUGF5X1JhdGVfVHlwZV9Db2RlIj5TYWxhcnk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UGF5X1JhdGVfVHlwZV9SZWZlcmVuY2U+CgogICAgICAgICAgICAgICAgICA8eGhyOlRpbWVfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj44YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlRpbWVfVHlwZV9Db2RlIj5GdWxsX1RpbWU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6VGltZV9UeXBlX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6U3VwZXJ2aXNvcnlfT3JnX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmZmNTUwMDY2Nzc4ODk5MDAxMTIyMzM0NDU1NjY3N2FhPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX0NvZGUiPkRFUy1SRVNFQVJDSC0wMDE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6U3VwZXJ2aXNvcnlfT3JnX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX0Fzc2lnbm1lbnRzPgogICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjAwNjY3Nzg4OTkwMDExMjIzMzQ0NTU2Njc3ODg5OTAwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19Db2RlIj5DQy04MzAwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkNvc3RfQ2VudGVyX0NvZGUiPkNDLTgzMDA8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9OYW1lPkRlc2lnbiAtIFJlc2VhcmNoPC94aHI6T3JnYW5pemF0aW9uX05hbWU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4xZTJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTRmNWE2YjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJPcmdfVHlwZV9Db2RlIj5Db3N0X0NlbnRlcjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbj4KICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbj4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4yZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhNmI3YzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJPcmdfQ29kZSI+Q09NUC1HRDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJDb21wYW55X0NvZGUiPkNPTVAtR0Q8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9OYW1lPkdsb2JhbCBEeW5hbWljcyBJbmMuPC94aHI6T3JnYW5pemF0aW9uX05hbWU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4zYTRiNWM2ZDdlOGY5YTBiMWMyZDNlNGY1YTZiN2M4ZDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJPcmdfVHlwZV9Db2RlIj5Db21wYW55PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uPgogICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb25fQXNzaWdubWVudHM+CgogICAgICAgICAgICAgICAgPC94aHI6UG9zaXRpb24+CgogICAgICAgICAgICAgICAgPHhocjpNYW5hZ2VyX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4yMjMzNDQ1NTY2Nzc4ODk5YWFiYjAwMTFjY2RkZWVmZjwveGhyOklEPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJFbXBsb3llZV9OdW1iZXIiPkVNUC0yMDE0NDA8L3hocjpJRD4KICAgICAgICAgICAgICAgIDwveGhyOk1hbmFnZXJfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgIDx4aHI6RW1wbG95bWVudF9TdGF0dXM+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfQWN0aXZlPnRydWU8L3hocjpJc19BY3RpdmU+CiAgICAgICAgICAgICAgICAgIDx4aHI6QWN0aXZlX1N0YXR1c19EYXRlPjIwMjMtMDQtMTA8L3hocjpBY3RpdmVfU3RhdHVzX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6SGlyZV9EYXRlPjIwMjMtMDQtMTA8L3hocjpIaXJlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6T3JpZ2luYWxfSGlyZV9EYXRlPjIwMjMtMDQtMTA8L3hocjpPcmlnaW5hbF9IaXJlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RW5kX0VtcGxveW1lbnRfRGF0ZS8+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q29udGludW91c19TZXJ2aWNlX0RhdGU+MjAyMy0wNC0xMDwveGhyOkNvbnRpbnVvdXNfU2VydmljZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkZpcnN0X0RheV9vZl9Xb3JrPjIwMjMtMDQtMTA8L3hocjpGaXJzdF9EYXlfb2ZfV29yaz4KICAgICAgICAgICAgICAgICAgPHhocjpTZW5pb3JpdHlfRGF0ZT4yMDIzLTA0LTEwPC94aHI6U2VuaW9yaXR5X0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6QmVuZWZpdHNfU2VydmljZV9EYXRlPjIwMjMtMDQtMTA8L3hocjpCZW5lZml0c19TZXJ2aWNlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q29tcGFueV9TZXJ2aWNlX0RhdGU+MjAyMy0wNC0xMDwveGhyOkNvbXBhbnlfU2VydmljZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOklzX1JldGlyZWQ+ZmFsc2U8L3hocjpJc19SZXRpcmVkPgogICAgICAgICAgICAgICAgICA8eGhyOklzX1Rlcm1pbmF0ZWQ+ZmFsc2U8L3hocjpJc19UZXJtaW5hdGVkPgogICAgICAgICAgICAgICAgICA8eGhyOklzX1JlaGlyZT5mYWxzZTwveGhyOklzX1JlaGlyZT4KICAgICAgICAgICAgICAgICAgPHhocjpEYXlzX1VuZW1wbG95ZWQ+MDwveGhyOkRheXNfVW5lbXBsb3llZD4KICAgICAgICAgICAgICAgICAgPCEtLSBMZWF2ZSBvZiBBYnNlbmNlIGZpZWxkcyDigJQgb25seSBwcmVzZW50IHdoZW4gb24gbGVhdmUgLS0+CiAgICAgICAgICAgICAgICAgIDx4aHI6T25fTGVhdmU+dHJ1ZTwveGhyOk9uX0xlYXZlPgogICAgICAgICAgICAgICAgICA8eGhyOkxlYXZlX1N0YXJ0X0RhdGU+MjAyNi0wMi0wMzwveGhyOkxlYXZlX1N0YXJ0X0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RXhwZWN0ZWRfUmV0dXJuX0RhdGU+MjAyNi0wOC0wMzwveGhyOkV4cGVjdGVkX1JldHVybl9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkxlYXZlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+Nzc4ODk5MDAxMTIyMzM0NDU1NjY3N2FhYmJjY2RkMDA8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMZWF2ZV9UeXBlX0NvZGUiPlBhcmVudGFsX0xlYXZlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkxlYXZlX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8eGhyOkxlYXZlX1JlcXVlc3RfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ODg5OTAwMTEyMjMzNDQ1NTY2Nzc4OGFhYmJjY2RkMTE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMZWF2ZV9SZXF1ZXN0X0lEIj5MUi0yMDI2LTAwMDQxMjwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpMZWF2ZV9SZXF1ZXN0X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgIDwveGhyOkVtcGxveW1lbnRfU3RhdHVzPgoKICAgICAgICAgICAgICA8L3hocjpKb2JfRGF0YT4KICAgICAgICAgICAgPC94aHI6RW1wbG95bWVudF9EYXRhPgoKICAgICAgICAgIDwveGhyOkVtcGxveWVlX0RhdGE+CiAgICAgICAgPC94aHI6RW1wbG95ZWU+CgogICAgICAgIDwhLS0gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IC0tPgogICAgICAgIDwhLS0gRU1QTE9ZRUUgNCDigJQgQ29udGluZ2VudCBXb3JrZXIgKENvbnRyYWN0b3IpICAgICAgICAgICAgICAgICAgLS0+CiAgICAgICAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+CiAgICAgICAgPHhocjpFbXBsb3llZT4KICAgICAgICAgIDx4aHI6RW1wbG95ZWVfUmVmZXJlbmNlPgogICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwPC94aHI6SUQ+CiAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkNvbnRpbmdlbnRfV29ya2VyX051bWJlciI+Q1ctNDAwMDkxPC94aHI6SUQ+CiAgICAgICAgICA8L3hocjpFbXBsb3llZV9SZWZlcmVuY2U+CgogICAgICAgICAgPHhocjpFbXBsb3llZV9EYXRhPgogICAgICAgICAgICA8eGhyOkVtcGxveWVlX051bWJlcj5DVy00MDAwOTE8L3hocjpFbXBsb3llZV9OdW1iZXI+CiAgICAgICAgICAgIDx4aHI6TG9naW5fSUQ+bW5ha2FtdXJhLmV4dDwveGhyOkxvZ2luX0lEPgoKICAgICAgICAgICAgPHhocjpQZXJzb25hbF9EYXRhPgogICAgICAgICAgICAgIDx4aHI6TmFtZV9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpMZWdhbF9OYW1lPgogICAgICAgICAgICAgICAgICA8eGhyOk5hbWVfRGV0YWlsPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmZmMDAxMTIyMzM0NDU1NjY3Nzg4OTlhYWJiY2NkZGVlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTIiPkpQPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTMiPkpQTjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkNvdW50cnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Rmlyc3RfTmFtZT5NYXNhdG88L3hocjpGaXJzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TGFzdF9OYW1lPk5ha2FtdXJhPC94aHI6TGFzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6RGlzcGxheV9OYW1lPk1hc2F0byBOYWthbXVyYTwveGhyOkRpc3BsYXlfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOlNvcnRfTmFtZT5OYWthbXVyYSwgTWFzYXRvPC94aHI6U29ydF9OYW1lPgogICAgICAgICAgICAgICAgICA8L3hocjpOYW1lX0RldGFpbD4KICAgICAgICAgICAgICAgIDwveGhyOkxlZ2FsX05hbWU+CiAgICAgICAgICAgICAgICA8eGhyOlByZWZlcnJlZF9OYW1lPgogICAgICAgICAgICAgICAgICA8eGhyOk5hbWVfRGV0YWlsPgogICAgICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmJjMzNhYTMxNTJlYzQyZDQ5OTVmNDc5MWExMDZlZDA5PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJJU09fMzE2Nl9BbHBoYTIiPlVTPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpGaXJzdF9OYW1lPk1hc2E8L3hocjpGaXJzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6TGFzdF9OYW1lPk5ha2FtdXJhPC94aHI6TGFzdF9OYW1lPgogICAgICAgICAgICAgICAgICAgIDx4aHI6RGlzcGxheV9OYW1lPk1hc2EgTmFrYW11cmE8L3hocjpEaXNwbGF5X05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpTb3J0X05hbWU+TmFrYW11cmEsIE1hc2E8L3hocjpTb3J0X05hbWU+CiAgICAgICAgICAgICAgICAgIDwveGhyOk5hbWVfRGV0YWlsPgogICAgICAgICAgICAgICAgPC94aHI6UHJlZmVycmVkX05hbWU+CiAgICAgICAgICAgICAgPC94aHI6TmFtZV9EYXRhPgoKICAgICAgICAgICAgICA8eGhyOkNvbnRhY3RfRGF0YT4KICAgICAgICAgICAgICAgIDx4aHI6RW1haWw+CiAgICAgICAgICAgICAgICAgIDx4aHI6RW1haWxfQWRkcmVzcz5tYXNhdG8ubmFrYW11cmEuZXh0QGdsb2JhbGR5bmFtaWNzLmNvbTwveGhyOkVtYWlsX0FkZHJlc3M+CiAgICAgICAgICAgICAgICAgIDx4aHI6VXNhZ2UgeGhyOlB1YmxpYz0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX0luZm8geGhyOlByaW1hcnk9InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpUeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5kMGUxZjJhM2I0YzVkNmU3ZjhhOWIwYzFkMmUzZjRhNTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJVc2FnZV9UeXBlX0NvZGUiPldPUks8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOlR5cGVfSW5mbz4KICAgICAgICAgICAgICAgICAgPC94aHI6VXNhZ2U+CiAgICAgICAgICAgICAgICA8L3hocjpFbWFpbD4KCiAgICAgICAgICAgICAgICA8eGhyOlBob25lPgogICAgICAgICAgICAgICAgICA8eGhyOkNvdW50cnlfQ29kZT4xPC94aHI6Q291bnRyeV9Db2RlPgogICAgICAgICAgICAgICAgICA8eGhyOkFyZWFfQ29kZT40MDg8L3hocjpBcmVhX0NvZGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6TnVtYmVyPjU1NS0wNjEyPC94aHI6TnVtYmVyPgogICAgICAgICAgICAgICAgICA8eGhyOkRldmljZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmY1YTZiN2M4ZDllMGYxYTJiM2M0ZDVlNmY3YThiOWMwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRGV2aWNlX1R5cGVfQ29kZSI+TW9iaWxlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgIDwveGhyOkRldmljZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpVc2FnZSB4aHI6UHVibGljPSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfSW5mbyB4aHI6UHJpbWFyeT0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlR5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmQwZTFmMmEzYjRjNWQ2ZTdmOGE5YjBjMWQyZTNmNGE1PC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlVzYWdlX1R5cGVfQ29kZSI+V09SSzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6VHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6VHlwZV9JbmZvPgogICAgICAgICAgICAgICAgICA8L3hocjpVc2FnZT4KICAgICAgICAgICAgICAgICAgPHhocjpGb3JtYXR0ZWRfTnVtYmVyPisxICg0MDgpIDU1NS0wNjEyPC94aHI6Rm9ybWF0dGVkX051bWJlcj4KICAgICAgICAgICAgICAgIDwveGhyOlBob25lPgoKICAgICAgICAgICAgICAgIDwhLS0gTm90ZTogTm8gaG9tZSBhZGRyZXNzIG9uIGZpbGUgZm9yIGNvbnRpbmdlbnQgd29ya2VycyDigJQgY29tbW9uIHBhdHRlcm4gLS0+CgogICAgICAgICAgICAgIDwveGhyOkNvbnRhY3RfRGF0YT4KCiAgICAgICAgICAgICAgPHhocjpCaW9ncmFwaGljYWxfRGF0YT4KICAgICAgICAgICAgICAgIDx4aHI6RGF0ZV9vZl9CaXJ0aD4xOTg3LTA5LTMwPC94aHI6RGF0ZV9vZl9CaXJ0aD4KICAgICAgICAgICAgICAgIDx4aHI6R2VuZGVyX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4wYTFiMmMzZDRlNWY2YTdiOGM5ZDBlMWYyYTNiNGM1ZDwveGhyOklEPgogICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHZW5kZXJfQ29kZSI+TWFsZTwveGhyOklEPgogICAgICAgICAgICAgICAgPC94aHI6R2VuZGVyX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgIDx4aHI6Q291bnRyeV9vZl9CaXJ0aF9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+ZmYwMDExMjIzMzQ0NTU2Njc3ODg5OWFhYmJjY2RkZWU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5KUDwveGhyOklEPgogICAgICAgICAgICAgICAgPC94aHI6Q291bnRyeV9vZl9CaXJ0aF9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICA8IS0tIE5vIG1hcml0YWwgc3RhdHVzIOKAlCBub3QgY29sbGVjdGVkIGZvciBjb250aW5nZW50IHdvcmtlcnMgLS0+CiAgICAgICAgICAgICAgPC94aHI6QmlvZ3JhcGhpY2FsX0RhdGE+CgogICAgICAgICAgICAgIDx4aHI6SWRlbnRpZmljYXRpb25fRGF0YT4KICAgICAgICAgICAgICAgIDwhLS0gQ29udGluZ2VudCB3b3JrZXJzIG1heSBoYXZlIG5vIG5hdGlvbmFsIElEcyBvbiBmaWxlIC0tPgogICAgICAgICAgICAgICAgPHhocjpDdXN0b21fSUQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q3VzdG9tX0lEX0RldGFpbD4KICAgICAgICAgICAgICAgICAgICA8eGhyOlZhbHVlPlZFTkRPUi1URUNIU1RBUi0wMDkxPC94aHI6VmFsdWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRF9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YjNjNGQ1ZTZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZTg8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkN1c3RvbV9JRF9UeXBlIj5WZW5kb3JfV29ya2VyX0lEPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6SURfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDwveGhyOkN1c3RvbV9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpDdXN0b21fSUQ+CiAgICAgICAgICAgICAgICA8eGhyOkN1c3RvbV9JRD4KICAgICAgICAgICAgICAgICAgPHhocjpDdXN0b21fSURfRGV0YWlsPgogICAgICAgICAgICAgICAgICAgIDx4aHI6VmFsdWU+QkFER0UtRVhULTc3MjE8L3hocjpWYWx1ZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5mMWEyYjNjNGQ1ZTZmN2E4YjljMGQxZTJmM2E0YjVjNjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iQ3VzdG9tX0lEX1R5cGUiPkJhZGdlX0lEPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6SURfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDwveGhyOkN1c3RvbV9JRF9EZXRhaWw+CiAgICAgICAgICAgICAgICA8L3hocjpDdXN0b21fSUQ+CiAgICAgICAgICAgICAgPC94aHI6SWRlbnRpZmljYXRpb25fRGF0YT4KCiAgICAgICAgICAgIDwveGhyOlBlcnNvbmFsX0RhdGE+CgogICAgICAgICAgICA8eGhyOkVtcGxveW1lbnRfRGF0YT4KICAgICAgICAgICAgICA8eGhyOkpvYl9EYXRhPgogICAgICAgICAgICAgICAgPHhocjpQb3NpdGlvbj4KICAgICAgICAgICAgICAgICAgPHhocjpQb3NpdGlvbl9JRD5QT1MtQ1ctMDQxMjwveGhyOlBvc2l0aW9uX0lEPgogICAgICAgICAgICAgICAgICA8eGhyOlBvc2l0aW9uX1RpdGxlPlN0YWZmIEF1Z21lbnRhdGlvbiAtIERldk9wczwveGhyOlBvc2l0aW9uX1RpdGxlPgogICAgICAgICAgICAgICAgICA8eGhyOkJ1c2luZXNzX1RpdGxlPkRldk9wcyBFbmdpbmVlciAoQ29udHJhY3QpPC94aHI6QnVzaW5lc3NfVGl0bGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6U3RhcnRfRGF0ZT4yMDI1LTEwLTAxPC94aHI6U3RhcnRfRGF0ZT4KICAgICAgICAgICAgICAgICAgPHhocjpFbmRfRGF0ZT4yMDI2LTA5LTMwPC94aHI6RW5kX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6RGVmYXVsdF9XZWVrbHlfSG91cnM+NDA8L3hocjpEZWZhdWx0X1dlZWtseV9Ib3Vycz4KICAgICAgICAgICAgICAgICAgPHhocjpTY2hlZHVsZWRfV2Vla2x5X0hvdXJzPjQwPC94aHI6U2NoZWR1bGVkX1dlZWtseV9Ib3Vycz4KICAgICAgICAgICAgICAgICAgPHhocjpGVEVfUGVyY2VudGFnZT4xMDA8L3hocjpGVEVfUGVyY2VudGFnZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6UG9zaXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YWFiYjAwMTFjY2RkMjIzM2VlZmY0NDU1NjY3Nzg4Y2M8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJQb3NpdGlvbl9JRCI+UE9TLUNXLTA0MTI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UG9zaXRpb25fUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPHhocjpFbXBsb3llZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmU1ZjZhN2I4YzlkMGUxZjJhM2I0YzVkNmU3ZjhhOWIwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfVHlwZV9Db2RlIj5Db250aW5nZW50X1dvcmtlcjwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpFbXBsb3llZV9UeXBlX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6Sm9iX1Byb2ZpbGU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfUHJvZmlsZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPmNjMTFkZDIyZWUzM2ZmNDQwMDU1NjY3Nzg4OTkwMDExPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJKb2JfUHJvZmlsZV9Db2RlIj5KUC1ERVZPUFMtQ1c8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpKb2JfUHJvZmlsZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfUHJvZmlsZV9OYW1lPkRldk9wcyBFbmdpbmVlciAoQ29udHJhY3QpPC94aHI6Sm9iX1Byb2ZpbGVfTmFtZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOk1hbmFnZW1lbnRfTGV2ZWxfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4yYjNjNGQ1ZTZmN2E4YjljMGQxZTJmM2E0YjVjNmQ3ZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iTWFuYWdlbWVudF9MZXZlbF9Db2RlIj5JbmRpdmlkdWFsX0NvbnRyaWJ1dG9yPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TWFuYWdlbWVudF9MZXZlbF9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpKb2JfQ2F0ZWdvcnlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4zYzRkNWU2ZjdhOGI5YzBkMWUyZjNhNGI1YzZkN2U4ZjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSm9iX0NhdGVnb3J5X0NvZGUiPkVuZ2luZWVyaW5nPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6Sm9iX0NhdGVnb3J5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOkpvYl9GYW1pbHlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj5lZTQ0ZmY1NTAwNjY3Nzg4OTkwMDExMjIzMzQ0YWFiYjwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSm9iX0ZhbWlseV9Db2RlIj5KRi1JbmZyYXN0cnVjdHVyZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDwveGhyOkpvYl9GYW1pbHlfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICA8L3hocjpKb2JfUHJvZmlsZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6V29ya19Mb2NhdGlvbj4KICAgICAgICAgICAgICAgICAgICA8eGhyOkxvY2F0aW9uX05hbWU+U2FuIEZyYW5jaXNjbyBIUTwveGhyOkxvY2F0aW9uX05hbWU+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMb2NhdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjVlNmY3YThiOWMwZDFlMmYzYTRiNWM2ZDdlOGY5YTBiPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJMb2NhdGlvbl9Db2RlIj5MT0MtU0YtSFE8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICA8L3hocjpMb2NhdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpMb2NhdGlvbl9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+NmY3YThiOWMwZDFlMmYzYTRiNWM2ZDdlOGY5YTBiMWM8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkxvY2F0aW9uX1R5cGVfQ29kZSI+T2ZmaWNlPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPC94aHI6TG9jYXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpBZGRyZXNzPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpDb3VudHJ5X1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iSVNPXzMxNjZfQWxwaGEyIj5VUzwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6Q291bnRyeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOkxpbmUgeGhyOlR5cGU9IkxJTkVfMSI+MzUwIE1pc3Npb24gU3RyZWV0PC94aHI6TGluZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6TGluZSB4aHI6VHlwZT0iTElORV8yIj5GbG9vciAyMjwveGhyOkxpbmU+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOkNpdHk+U2FuIEZyYW5jaXNjbzwveGhyOkNpdHk+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlJlZ2lvbl9Db2RlIj5VU0EtQ0E8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOlJlZ2lvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOlJlZ2lvbl9OYW1lPkNhbGlmb3JuaWE8L3hocjpSZWdpb25fTmFtZT4KICAgICAgICAgICAgICAgICAgICAgIDx4aHI6UG9zdGFsX0NvZGU+OTQxMDU8L3hocjpQb3N0YWxfQ29kZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpBZGRyZXNzPgogICAgICAgICAgICAgICAgICA8L3hocjpXb3JrX0xvY2F0aW9uPgoKICAgICAgICAgICAgICAgICAgPHhocjpQYXlfUmF0ZV9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTRmPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iUGF5X1JhdGVfVHlwZV9Db2RlIj5Ib3VybHk8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6UGF5X1JhdGVfVHlwZV9SZWZlcmVuY2U+CgogICAgICAgICAgICAgICAgICA8eGhyOlRpbWVfVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj44YjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlRpbWVfVHlwZV9Db2RlIj5GdWxsX1RpbWU8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6VGltZV9UeXBlX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6U3VwZXJ2aXNvcnlfT3JnX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjljMGQxZTJmM2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTRmPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX0NvZGUiPkVORy1EQVRBLTAwMTwveGhyOklEPgogICAgICAgICAgICAgICAgICA8L3hocjpTdXBlcnZpc29yeV9PcmdfUmVmZXJlbmNlPgoKICAgICAgICAgICAgICAgICAgPCEtLSBWZW5kb3IgLyBTdGFmZmluZyBBZ2VuY3kgcmVmZXJlbmNlIOKAlCB1bmlxdWUgdG8gY29udGluZ2VudCB3b3JrZXJzIC0tPgogICAgICAgICAgICAgICAgICA8eGhyOlN0YWZmaW5nX0FnZW5jeV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iR0lEIj4xMTAwYWFiYjIyMzNjY2RkNDQ1NWVlZmY2Njc3ODgwMDwveGhyOklEPgogICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IlZlbmRvcl9Db2RlIj5WRU5ET1ItVEVDSFNUQVI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPC94aHI6U3RhZmZpbmdfQWdlbmN5X1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uX0Fzc2lnbm1lbnRzPgogICAgICAgICAgICAgICAgICAgIDx4aHI6T3JnYW5pemF0aW9uPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgICA8eGhyOklEIHhocjp0eXBlPSJHSUQiPjBkMWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9Ik9yZ19Db2RlIj5DQy03MTAwPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkNvc3RfQ2VudGVyX0NvZGUiPkNDLTcxMDA8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9OYW1lPkVuZ2luZWVyaW5nIC0gRGF0YSBQbGF0Zm9ybTwveGhyOk9yZ2FuaXphdGlvbl9OYW1lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+MWUyZjNhNGI1YzZkN2U4ZjlhMGIxYzJkM2U0ZjVhNmI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX1R5cGVfQ29kZSI+Q29zdF9DZW50ZXI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbl9UeXBlX1JlZmVyZW5jZT4KICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb24+CiAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb24+CiAgICAgICAgICAgICAgICAgICAgICA8eGhyOk9yZ2FuaXphdGlvbl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+MmYzYTRiNWM2ZDdlOGY5YTBiMWMyZDNlNGY1YTZiN2M8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX0NvZGUiPkNPTVAtR0Q8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iQ29tcGFueV9Db2RlIj5DT01QLUdEPC94aHI6SUQ+CiAgICAgICAgICAgICAgICAgICAgICA8L3hocjpPcmdhbml6YXRpb25fUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fTmFtZT5HbG9iYWwgRHluYW1pY3MgSW5jLjwveGhyOk9yZ2FuaXphdGlvbl9OYW1lPgogICAgICAgICAgICAgICAgICAgICAgPHhocjpPcmdhbml6YXRpb25fVHlwZV9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+M2E0YjVjNmQ3ZThmOWEwYjFjMmQzZTRmNWE2YjdjOGQ8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iT3JnX1R5cGVfQ29kZSI+Q29tcGFueTwveGhyOklEPgogICAgICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX1R5cGVfUmVmZXJlbmNlPgogICAgICAgICAgICAgICAgICAgIDwveGhyOk9yZ2FuaXphdGlvbj4KICAgICAgICAgICAgICAgICAgPC94aHI6T3JnYW5pemF0aW9uX0Fzc2lnbm1lbnRzPgoKICAgICAgICAgICAgICAgIDwveGhyOlBvc2l0aW9uPgoKICAgICAgICAgICAgICAgIDx4aHI6TWFuYWdlcl9SZWZlcmVuY2U+CiAgICAgICAgICAgICAgICAgIDx4aHI6SUQgeGhyOnR5cGU9IkdJRCI+YWFiYmNjZGQxMTIyMzM0NDU1NjY3Nzg4OTkwMGFhYmI8L3hocjpJRD4KICAgICAgICAgICAgICAgICAgPHhocjpJRCB4aHI6dHlwZT0iRW1wbG95ZWVfTnVtYmVyIj5FTVAtMTk4MDQ0PC94aHI6SUQ+CiAgICAgICAgICAgICAgICA8L3hocjpNYW5hZ2VyX1JlZmVyZW5jZT4KCiAgICAgICAgICAgICAgICA8eGhyOkVtcGxveW1lbnRfU3RhdHVzPgogICAgICAgICAgICAgICAgICA8eGhyOklzX0FjdGl2ZT50cnVlPC94aHI6SXNfQWN0aXZlPgogICAgICAgICAgICAgICAgICA8eGhyOkFjdGl2ZV9TdGF0dXNfRGF0ZT4yMDI1LTEwLTAxPC94aHI6QWN0aXZlX1N0YXR1c19EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkhpcmVfRGF0ZT4yMDI1LTEwLTAxPC94aHI6SGlyZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOk9yaWdpbmFsX0hpcmVfRGF0ZT4yMDI1LTEwLTAxPC94aHI6T3JpZ2luYWxfSGlyZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkVuZF9FbXBsb3ltZW50X0RhdGU+MjAyNi0wOS0zMDwveGhyOkVuZF9FbXBsb3ltZW50X0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q29udGludW91c19TZXJ2aWNlX0RhdGU+MjAyNS0xMC0wMTwveGhyOkNvbnRpbnVvdXNfU2VydmljZV9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkZpcnN0X0RheV9vZl9Xb3JrPjIwMjUtMTAtMDE8L3hocjpGaXJzdF9EYXlfb2ZfV29yaz4KICAgICAgICAgICAgICAgICAgPHhocjpTZW5pb3JpdHlfRGF0ZT4yMDI1LTEwLTAxPC94aHI6U2VuaW9yaXR5X0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6QmVuZWZpdHNfU2VydmljZV9EYXRlLz4KICAgICAgICAgICAgICAgICAgPHhocjpDb21wYW55X1NlcnZpY2VfRGF0ZT4yMDI1LTEwLTAxPC94aHI6Q29tcGFueV9TZXJ2aWNlX0RhdGU+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfUmV0aXJlZD5mYWxzZTwveGhyOklzX1JldGlyZWQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfVGVybWluYXRlZD5mYWxzZTwveGhyOklzX1Rlcm1pbmF0ZWQ+CiAgICAgICAgICAgICAgICAgIDx4aHI6SXNfUmVoaXJlPmZhbHNlPC94aHI6SXNfUmVoaXJlPgogICAgICAgICAgICAgICAgICA8eGhyOkRheXNfVW5lbXBsb3llZD4wPC94aHI6RGF5c19VbmVtcGxveWVkPgogICAgICAgICAgICAgICAgICA8IS0tIENvbnRyYWN0IEVuZCDigJQgb25seSBwcmVzZW50IGZvciBjb250aW5nZW50IHdvcmtlcnMgLS0+CiAgICAgICAgICAgICAgICAgIDx4aHI6Q29udHJhY3RfRW5kX0RhdGU+MjAyNi0wOS0zMDwveGhyOkNvbnRyYWN0X0VuZF9EYXRlPgogICAgICAgICAgICAgICAgICA8eGhyOkNvbnRyYWN0X1JlbmV3YWJsZT50cnVlPC94aHI6Q29udHJhY3RfUmVuZXdhYmxlPgogICAgICAgICAgICAgICAgPC94aHI6RW1wbG95bWVudF9TdGF0dXM+CgogICAgICAgICAgICAgIDwveGhyOkpvYl9EYXRhPgogICAgICAgICAgICA8L3hocjpFbXBsb3ltZW50X0RhdGE+CgogICAgICAgICAgPC94aHI6RW1wbG95ZWVfRGF0YT4KICAgICAgICA8L3hocjpFbXBsb3llZT4KCiAgICAgIDwveGhyOlJlc3BvbnNlX0RhdGE+CiAgICA8L3hocjpHZXRFbXBsb3llZXNfUmVzcG9uc2U+CiAgPC9zb2FwOkJvZHk+Cjwvc29hcDpFbnZlbG9wZT4="} \ No newline at end of file diff --git a/src/pages/tools/xpath-evaluator.tsx b/src/pages/tools/xpath-evaluator.tsx new file mode 100644 index 0000000000000..9f377a87706be --- /dev/null +++ b/src/pages/tools/xpath-evaluator.tsx @@ -0,0 +1,482 @@ +import React, {useEffect, useRef, useState} from 'react'; +import Layout from '@theme/Layout'; +import styles from './xpath.module.css'; +import Alert from '@mui/material/Alert'; +import Stack from '@mui/material/Stack'; +import Link from '@mui/material/Link'; +import TerminalFontSizeDropdown from '../../components/xpath/TerminalFontSizeDropdown'; +import InputTerminal from '../../components/xpath/InputTerminal'; +import type {HoverValuePayload} from '../../components/xpath/InputTerminal'; +import ResultTerminal from '../../components/xpath/ResultTerminal'; +import XPathRootInput from '../../components/xpath/XPathRootInput'; +import { + evaluateXPathMappings, + XPathEvaluationError, + type AttributeMappings, +} from '../../services/XPathService'; +import Button from '@mui/material/Button'; + +// Define the type for implementation options +type ImplementationType = 'XPath'; +type HoverXPathMatch = { + occurrence: number; + elementPath: string; + exactNodePath: string; +}; + +// Define the documentation links type +const documentationLinks: Record< + ImplementationType, + {url: string; text: string} +> = { + XPath: { + url: 'https://en.wikipedia.org/wiki/XPath', + text: 'XPath Documentation', + }, +}; +const sampleXmlFile = require('./sample.xml.json'); +let buffer = Buffer.from(sampleXmlFile.xml, 'base64'); +const sampleXml = buffer.toString(); + +const XPathEvaluator: React.FC = () => { + const [result, setResult] = useState(JSON.stringify([], null, 4)); + const [attributeMappingsInput, setAttributeMappingsInput] = useState( + JSON.stringify( + { + firstName: + 'xhr:Employee_Data/xhr:Personal_Data/xhr:Name_Data/xhr:Legal_Name/xhr:Name_Detail/xhr:First_Name', + lastName: + 'xhr:Employee_Data/xhr:Personal_Data/xhr:Name_Data/xhr:Legal_Name/xhr:Name_Detail/xhr:Last_Name', + employeeId: + "xhr:Employee_Reference/xhr:ID[@xhr:type='Employee_Number']", + phoneNumber: + 'xhr:Employee_Data/xhr:Personal_Data/xhr:Contact_Data/xhr:Phone/xhr:Formatted_Number', + workRegion: + "xhr:Employee_Data/xhr:Employment_Data/xhr:Worker_Job_Data/xhr:Position_Data/xhr:Business_Site_Summary_Data[xhr:Usage/xhr:Type_Info/@xhr:Primary='true']/xhr:Address/xhr:Region_Reference/xhr:ID[@xhr:type='Region_Code']", + ssnNationalId: + "xhr:Employee_Data/xhr:Personal_Data/xhr:Identification_Data/xhr:National_ID[xhr:National_ID_Detail/xhr:ID_Type_Reference/xhr:ID[@xhr:type='National_ID_Type']='USA-SSN']/xhr:National_ID_Detail/xhr:Value" + }, + null, + 2, + ), + ); + const [root, setRoot] = useState('//xhr:Response_Data/xhr:Employee'); + const [queryParseError, setQueryParseError] = useState(''); + const [isAttributeMappingsParseError, setIsAttributeMappingsParseError] = + useState(false); + const [fontSize, setFontSize] = useState('16'); + const implementation: ImplementationType = 'XPath'; + const inputXml = sampleXml; + const [localXml, setLocalXml] = useState(inputXml); + const [xmlParseError, setXmlParseError] = useState(false); + const [hoverXPathHintMessage, setHoverXPathHintMessage] = useState( + 'Hover an XML value to see its XPath.', + ); + const [hoverXPathMatches, setHoverXPathMatches] = useState( + [], + ); + const [isHoverLocked, setIsHoverLocked] = useState(false); + const [lockedHoverValue, setLockedHoverValue] = + useState(null); + const hoverClearTimeoutRef = useRef(null); + const lastRenderedHoverKeyRef = useRef(''); + + const getElementXPath = (element: Element): string => { + const segments: string[] = []; + let current: Element | null = element; + + while (current) { + segments.unshift(current.tagName); + current = current.parentElement; + } + + return `/${segments.join('/')}`; + }; + + const resolveXPathForValue = ( + xml: string, + hoveredNode: HoverValuePayload, + ): { + matches: HoverXPathMatch[]; + message: string; + } => { + const value = hoveredNode.value.trim(); + if (!value) { + return { + matches: [], + message: 'Hover an XML value to see its XPath.', + }; + } + + try { + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(xml, 'application/xml'); + if (xmlDoc.getElementsByTagName('parsererror').length > 0) { + return { + matches: [], + message: 'XPath hint unavailable (invalid XML).', + }; + } + + const matches: HoverXPathMatch[] = []; + const elements = Array.from(xmlDoc.getElementsByTagName('*')); + + for (const element of elements) { + const elementPath = getElementXPath(element); + + if (hoveredNode.nodeKind === 'attribute') { + for (const attribute of Array.from(element.attributes)) { + if (attribute.value === value) { + const exactNodePath = `${elementPath}/@${attribute.name}`; + matches.push({ + occurrence: matches.length + 1, + elementPath, + exactNodePath, + }); + } + } + } else { + for (const childNode of Array.from(element.childNodes)) { + if ( + childNode.nodeType === Node.TEXT_NODE && + childNode.textContent?.trim() === value + ) { + const exactNodePath = `${elementPath}/text()`; + matches.push({ + occurrence: matches.length + 1, + elementPath, + exactNodePath, + }); + } + } + } + } + + if (matches.length === 0) { + return { + matches: [], + message: `No XPath match found for "${value}".`, + }; + } + + const selectedIndex = Math.min( + Math.max(hoveredNode.occurrenceIndex, 0), + matches.length - 1, + ); + const selectedMatch = matches[selectedIndex]; + + return { + matches: [selectedMatch], + message: `Showing selected node match for "${value}" (${matches.length} total matches).`, + }; + } catch (_error) { + return { + matches: [], + message: 'XPath hint unavailable.', + }; + } + }; + + // Apply XPath query + const parseAttributeMappings = ( + mappingsJson: string, + ): AttributeMappings | null => { + try { + const parsed = JSON.parse(mappingsJson) as unknown; + + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + setQueryParseError( + 'Attribute mappings must be a JSON object (for example: {"id":"./id"}).', + ); + setIsAttributeMappingsParseError(true); + return null; + } + + const mappings: AttributeMappings = {}; + for (const [attributeId, expression] of Object.entries(parsed)) { + if (typeof expression !== 'string') { + setQueryParseError( + `Attribute mapping '${attributeId}' must be an XPath string value.`, + ); + setIsAttributeMappingsParseError(true); + return null; + } + mappings[attributeId] = expression; + } + + if (Object.keys(mappings).length === 0) { + setQueryParseError('Add at least one attribute mapping XPath pair.'); + setIsAttributeMappingsParseError(true); + return null; + } + + return mappings; + } catch (_error) { + setQueryParseError( + 'Attribute mappings must be valid JSON (for example: {"id":"./id"}).', + ); + setIsAttributeMappingsParseError(true); + return null; + } + }; + + // Apply XPath query + const applyXPathQuery = ( + xml: string, + root: string, + attributeMappingsJson: string, + ) => { + const attributeMappings = parseAttributeMappings(attributeMappingsJson); + if (!attributeMappings) { + setResult('[]'); + return; + } + + try { + let result: any; + + switch (implementation) { + case 'XPath': + // Evaluated entirely in the browser; no Lambda round trip. + result = evaluateXPathMappings(attributeMappings, root, xml); + break; + } + + setResult( + result.length > 0 || + typeof result === 'number' || + typeof result === 'object' || + typeof result === 'boolean' + ? JSON.stringify(result, null, 2) + : 'No match', + ); + setQueryParseError(''); + setIsAttributeMappingsParseError(false); + setXmlParseError(false); + } catch (error: any) { + setResult('No match'); + // Only flag the XML input terminal when the XML itself failed to + // parse; query/root-path syntax errors surface via the alert only. + setXmlParseError( + error instanceof XPathEvaluationError && error.kind === 'xml-parse', + ); + setQueryParseError(error.message || 'Error executing XPath query'); + } + }; + + // Handle input change + const handleXmlChange = (newxml: string) => { + setLocalXml(newxml); + setHoverXPathHintMessage('Hover over an XML value to see its XPath.'); + setHoverXPathMatches([]); + setIsHoverLocked(false); + setLockedHoverValue(null); + if (hoverClearTimeoutRef.current !== null) { + window.clearTimeout(hoverClearTimeoutRef.current); + hoverClearTimeoutRef.current = null; + } + lastRenderedHoverKeyRef.current = ''; + }; + + const handleXmlHoverValueChange = (hoveredNode: HoverValuePayload | null) => { + if (isHoverLocked) { + return; + } + if (hoverClearTimeoutRef.current !== null) { + window.clearTimeout(hoverClearTimeoutRef.current); + hoverClearTimeoutRef.current = null; + } + if (!hoveredNode) { + // Prevent visual jitter when the cursor briefly crosses XML punctuation. + hoverClearTimeoutRef.current = window.setTimeout(() => { + setHoverXPathHintMessage('Hover over an XML value to see its XPath.'); + setHoverXPathMatches([]); + lastRenderedHoverKeyRef.current = ''; + hoverClearTimeoutRef.current = null; + }, 120); + return; + } + const hoverKey = `${hoveredNode.nodeKind}:${hoveredNode.value}:${hoveredNode.occurrenceIndex}`; + if (lastRenderedHoverKeyRef.current === hoverKey) { + return; + } + const hoverData = resolveXPathForValue(localXml, hoveredNode); + setHoverXPathHintMessage(hoverData.message); + setHoverXPathMatches(hoverData.matches); + lastRenderedHoverKeyRef.current = hoverKey; + }; + + const handleXmlHoverLock = (hoveredNode: HoverValuePayload | null) => { + if (!hoveredNode) { + return; + } + if (hoverClearTimeoutRef.current !== null) { + window.clearTimeout(hoverClearTimeoutRef.current); + hoverClearTimeoutRef.current = null; + } + const hoverData = resolveXPathForValue(localXml, hoveredNode); + setHoverXPathHintMessage(`LOCKED: ${hoverData.message}`); + setHoverXPathMatches(hoverData.matches); + setIsHoverLocked(true); + setLockedHoverValue(hoveredNode); + }; + + const resetHoverLock = () => { + setIsHoverLocked(false); + setHoverXPathHintMessage('Hover an XML value to see its XPath.'); + setHoverXPathMatches([]); + setLockedHoverValue(null); + lastRenderedHoverKeyRef.current = ''; + }; + + useEffect(() => { + return () => { + if (hoverClearTimeoutRef.current !== null) { + window.clearTimeout(hoverClearTimeoutRef.current); + } + }; + }, []); + + // Handle root input change + const handleRootChange = (event: React.ChangeEvent) => { + setRoot(event.target.value); + }; + + // Run button handler + const handleRunQuery = () => { + applyXPathQuery(localXml, root, attributeMappingsInput); + }; + + return ( + +
+
+
+ + + + {documentationLinks[implementation] && ( + + {documentationLinks[implementation].text} + + )} + {queryParseError && ( +
+ + {queryParseError} + +
+ )} +
+ + + + + + +
+
+ + + + + + +
+
+ {isHoverLocked ? 'XPath Hover (Locked)' : 'XPath Hover'} + +
+
Click a selected XML value to lock output to that variable.
+
{hoverXPathHintMessage}
+
+ Exact selected node XPath +
+ {hoverXPathMatches.map((match, index) => ( +
+
+ Element path: {match.elementPath} +
+
+ Exact node path: {match.exactNodePath} +
+
+ ))} +
+
+
+
+ ); +}; + +export default XPathEvaluator; diff --git a/src/pages/tools/xpath.module.css b/src/pages/tools/xpath.module.css new file mode 100644 index 0000000000000..0748eedf6b06f --- /dev/null +++ b/src/pages/tools/xpath.module.css @@ -0,0 +1,168 @@ +.containerFluid { + margin: 20px; +} + +.actionBar { + margin-top: 2%; + margin-bottom: 2%; +} + +.alertContainer { + min-height: 50px; +} + +.inputTerminalContainer { + border: 3px solid red !important; + background: var(--terminal-background) !important; +} + +.terminalContainerDefault { + border: 3px solid var(--dev-card-background) !important; + background: var(--terminal-background) !important; +} + +a[id^='xpathDocumentationLink'] { + color: var(--link-color) !important; + text-decoration: underline !important; +} + +a[id^='xpathDocumentationLink']:hover { + text-decoration: none!important; +} + +li[class^='MuiButtonBase-root'] { + color: var(--ifm-primary-text-color); +} +div[class^='MuiFormControl-root'] { + color: var(--ifm-primary-text-color); +} +div[id^='terminal-font-size-select'], +div[id^='implementation-dropdown-select'] { + color: var(--ifm-primary-text-color); +} + +input[id^='outlined-basic-xpath-input'], +label[id^='outlined-basic-xpath-input-label'], +select[id^='terminal-font-size-select'], +label[id^='terminal-font-size-label'], +select[id^='implementation-dropdown-select'], +label[id^='implementation-dropdown-label'] { + color: var(--ifm-primary-text-color); +} +input[id^='outlined-basic-xpath-input'], +div[id^='terminal-font-size-select'], +div[id^='implementation-dropdown-select'] { + background: var(--terminal-background); +} +fieldset[class^='MuiOutlinedInput-notchedOutline css-1ll44ll-MuiOutlinedInput-notchedOutline'] { + border: 1.5px solid var(--terminal-background); +} +ul[class^='MuiList-root MuiList-padding MuiMenu-list css-1toxriw-MuiList-root-MuiMenu-list'] { + background-color: var(--terminal-background); +} +ul[class^='MuiMenu-list'] { + background-color: var(--terminal-background); +} +div[class^='MuiPaper-root'] { + background-color: var(--terminal-background) !important; +} + +span[class^='ace_variable'] { + color: var(--terminal-key) !important; +} +span[class^='ace_string'] { + color: var(--terminal-value) !important; +} + +div [id^='xpathalert'] { + color: rgb(244, 67, 54); + border: 1px solid rgb(244, 67, 54); +} + +.actionBar button { + min-width: 100px; +} + +.runButton { + color: var(--ifm-button-colors) !important; + border: 1px solid var(--ifm-button-colors) !important; + background-color: var(--dropdown-background) !important; +} + +.runButton:hover { + background-color: var(--ifm-button-colors) !important; + color: var(--text-on-primary) !important; + border: 1px solid var(--ifm-button-colors) !important; +} + +.hoverHint { + margin-top: 8px; + font-family: monospace; + font-size: 0.9rem; + color: var(--ifm-font-color-base); + word-break: break-word; + border: 1px solid transparent; + border-radius: 6px; + padding: 8px; + height: 240px; + overflow-y: scroll; + scrollbar-gutter: stable; + overflow-anchor: none; +} + +.hoverHintMatch { + margin-top: 8px; + padding: 8px; + border: 1px solid var(--dev-card-background); + border-radius: 4px; +} + +.hoverResultsSectionTitle { + margin-top: 10px; + font-weight: 700; + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.03em; +} + +.hoverHintLocked { + border-color: var(--ifm-color-warning); + box-shadow: 0 0 0 1px var(--ifm-color-warning); +} + +.hoverHeader { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 12px; + margin-bottom: 8px; +} + +.resetHoverButton { + border: 1px solid; + border-radius: 4px; + background: transparent; + font-size: 0.85rem; + padding: 4px 8px; +} + +.resetHoverButtonActive { + color: var(--ifm-color-warning-dark); + border-color: var(--ifm-color-warning-dark); + background-color: var(--ifm-color-warning-lightest); + cursor: pointer; +} + +.resetHoverButtonDisabled { + color: var(--ifm-color-emphasis-500); + border-color: var(--ifm-color-emphasis-300); + background-color: var(--ifm-color-emphasis-100); + cursor: not-allowed; +} + +:global(.ace_marker-layer .locked-hover-selection) { + position: absolute; + background-color: rgba(255, 193, 7, 0.35); + border-bottom: 2px solid var(--ifm-color-warning-dark); + z-index: 20; +} diff --git a/src/services/XPathService.ts b/src/services/XPathService.ts new file mode 100644 index 0000000000000..3210817051bc0 --- /dev/null +++ b/src/services/XPathService.ts @@ -0,0 +1,277 @@ +/* Copyright (c) 2026. SailPoint Technologies, Inc. All rights reserved. */ + +/** + * Client-side XPath evaluation service. + * + * This is a TypeScript port of the XML response parsing logic used by the + * Web Services connector (previously hosted as an AWS Lambda). It evaluates + * a root path against an XML document to produce a node list, then evaluates + * one or more attribute-mapping XPath expressions against each node to build + * resource objects — mirroring how the connector parses XML responses. + * + * It runs entirely in the browser. `@xmldom/xmldom` and `xpath` are pure + * JavaScript (no reliance on `window`/`document`), so this module is also + * safe to import during Docusaurus server-side rendering. + */ + +import {DOMParser, MIME_TYPE, onErrorStopParsing} from '@xmldom/xmldom'; +import * as xpath from 'xpath'; + +/** A single parsed resource: attribute-mapping name → extracted value(s). */ +export type XPathResource = Record; + +/** Attribute-mapping name → XPath expression (relative to each root node). */ +export type AttributeMappings = Record; + +/** Namespace prefix → URI. */ +export type NamespaceMappings = Record; + +/** Distinguishes XML parse failures from XPath evaluation failures. */ +export class XPathEvaluationError extends Error { + constructor( + message: string, + public readonly kind: 'xml-parse' | 'xpath', + ) { + super(message); + this.name = 'XPathEvaluationError'; + } +} + +const DEFAULT_ROOT_PATH = '/'; +const NS_TEMP_PREFIX = 'tempns'; +// Matches xmlns and xmlns:prefix declarations anywhere in the raw document +// text, capturing the prefix (group 1) and URI (group 2). +const REGEX_XMLNS_ATTRS_GROUP = /xmlns:?(\w*)="(\S*)"/g; + +/** + * Extract every namespace declaration from the raw XML text. Default + * (unprefixed) namespaces are assigned synthetic `tempns1`, `tempns2`, ... + * prefixes so they remain addressable in XPath 1.0, which has no concept of + * a default namespace in expressions. + */ +export function extractNamespaces(xmlContent: string): NamespaceMappings { + const namespaces: NamespaceMappings = {}; + let tempPrefixCount = 0; + if (xmlContent) { + for (const match of xmlContent.matchAll(REGEX_XMLNS_ATTRS_GROUP)) { + let prefix = match[1]; + const uri = match[2]; + if (!prefix) { + prefix = NS_TEMP_PREFIX + ++tempPrefixCount; + } + namespaces[prefix] = uri; + } + } + return namespaces; +} + +function normalizeRootPath(rootPath: string | null | undefined): string { + if (!rootPath) { + console.log('XPathService: Root path not configured. Setting to default.'); + return DEFAULT_ROOT_PATH; + } + if (rootPath === '//') { + console.log("XPathService: Root path found '//'. Overriding to '/'."); + return DEFAULT_ROOT_PATH; + } + return rootPath; +} + +/** + * Evaluate one attribute-mapping expression against one root node and store + * the result on the resource object. Errors here are logged and swallowed so + * that a single bad mapping does not prevent the remaining mappings from + * being extracted — matching the connector's lenient per-attribute behavior. + */ +function prepareResource( + resource: XPathResource, + node: Node, + path: string, + attributeMappingKey: string, + select: xpath.XPathSelect, +): void { + try { + const selected = select(path, node); + + if (Array.isArray(selected)) { + if (selected.length > 1) { + const childValues = selected.map((child) => child.textContent ?? ''); + resource[attributeMappingKey] = childValues; + // Salesforce SOAP responses repeat the element twice with + // identical values; collapse the duplicate to a single value. + if (path === 'sf:Id' && childValues[0] === childValues[1]) { + resource[attributeMappingKey] = childValues[0]; + } + } else if (selected.length === 1) { + resource[attributeMappingKey] = selected[0].textContent ?? ''; + } + // Zero matches: attribute intentionally omitted from the resource. + } else if (selected !== undefined && selected !== null) { + // Expressions like string(...), count(...), or boolean(...) return a + // primitive rather than a node list. + resource[attributeMappingKey] = String(selected); + } + } catch (error) { + console.log( + `XPathService: Error parsing value for attribute ${attributeMappingKey} using XPath ${path}:`, + error, + ); + } +} + +/** + * Parse an XML document and extract resource objects. + * + * @param rawXml XML document as a plain (not base64) string. + * @param rootPath XPath selecting the node(s) each resource is built + * from, e.g. `//xhr:Response_Data/xhr:Employee`. + * @param attributeMappings Attribute name → XPath relative to each root node. + * @param namespaceMappings Optional prefix → URI map. Namespaces declared in + * the document itself are always extracted and used; + * entries provided here take precedence on conflict. + * @returns One resource object per node matched by `rootPath`. + * @throws XPathEvaluationError on malformed XML (`kind: 'xml-parse'`) or an + * invalid root path expression (`kind: 'xpath'`). + */ +export function parseResources( + rawXml: string, + rootPath: string, + attributeMappings: AttributeMappings, + namespaceMappings: NamespaceMappings = {}, +): XPathResource[] { + const resources: XPathResource[] = []; + if (!rawXml) { + console.log( + 'XPathService: XML response is empty. Skipping resource parsing.', + ); + return resources; + } + + // Namespaces declared in the document are always available to expressions; + // caller-supplied mappings are merged on top so users can add or override + // prefixes. + const namespaces: NamespaceMappings = { + ...extractNamespaces(rawXml), + ...namespaceMappings, + }; + + let doc; + try { + // onErrorStopParsing makes the parser strict: malformed XML throws + // instead of producing a best-effort partial document. + const parser = new DOMParser({onError: onErrorStopParsing}); + doc = parser.parseFromString(rawXml, MIME_TYPE.XML_TEXT); + } catch (error) { + throw new XPathEvaluationError( + `XML parse error: ${error instanceof Error ? error.message : String(error)}`, + 'xml-parse', + ); + } + + const select = xpath.useNamespaces(namespaces); + + let nodes: xpath.SelectReturnType; + try { + // @xmldom/xmldom nodes implement the W3C DOM interfaces the xpath + // package operates on, but carry their own type declarations; the cast + // bridges the two declaration sets. + nodes = select(normalizeRootPath(rootPath), doc as unknown as Node); + } catch (error) { + throw new XPathEvaluationError( + `Invalid root path: ${error instanceof Error ? error.message : String(error)}`, + 'xpath', + ); + } + + if (!Array.isArray(nodes) || nodes.length === 0) { + console.log( + 'XPathService: Unable to find resource objects for provided root path', + ); + return resources; + } + + for (const node of nodes) { + const resource: XPathResource = {}; + let contextNode: Node | null = null; + + if (node.nodeType === node.ELEMENT_NODE) { + contextNode = node; + } else if (node.nodeType === node.DOCUMENT_NODE) { + contextNode = (node as Document).documentElement; + } + + if (contextNode) { + for (const [attributeMappingKey, path] of Object.entries( + attributeMappings, + )) { + prepareResource( + resource, + contextNode, + path, + attributeMappingKey, + select, + ); + } + } + resources.push(resource); + } + return resources; +} + +/** + * Convenience wrapper for the XPath Evaluator tool: evaluates a single XPath + * expression against each node matched by `rootPath`. + * + * Unlike the multi-mapping `parseResources` (which is lenient per attribute, + * matching the connector), a syntactically invalid query here throws an + * XPathEvaluationError so the tool can show the user an actionable message. + */ +export function evaluateXPath( + xPathQuery: string, + rootPath: string, + xmlData: string, + namespaceMappings: NamespaceMappings = {}, +): XPathResource[] { + return evaluateXPathMappings( + {'XPath Query Result': xPathQuery}, + rootPath, + xmlData, + namespaceMappings, + ); +} + +/** + * Convenience wrapper for the XPath Evaluator tool: evaluates one or more + * attribute-mapping XPath expressions against each node matched by `rootPath`. + */ +export function evaluateXPathMappings( + attributeMappings: AttributeMappings, + rootPath: string, + xmlData: string, + namespaceMappings: NamespaceMappings = {}, +): XPathResource[] { + for (const [attributeName, xPathQuery] of Object.entries(attributeMappings)) { + if (!xPathQuery || !xPathQuery.trim()) { + throw new XPathEvaluationError( + `XPath query for attribute '${attributeName}' is empty`, + 'xpath', + ); + } + + try { + // xpath.parse() is a documented public API of the xpath package, but is + // missing from its bundled type declarations (as of 0.0.34), hence the + // narrow cast. + (xpath as unknown as {parse: (expr: string) => unknown}).parse(xPathQuery); + } catch (error) { + throw new XPathEvaluationError( + `Invalid XPath query for attribute '${attributeName}': ${ + error instanceof Error ? error.message : String(error) + }`, + 'xpath', + ); + } + } + + return parseResources(xmlData, rootPath, attributeMappings, namespaceMappings); +}