瀏覽代碼

Merge branch 'features/jpath' of https://github.com/artemisbot/CyberChef into artemisbot-features/jpath

n1474335 8 年之前
父節點
當前提交
4b87d66131
共有 5 個文件被更改,包括 445 次插入0 次删除
  1. 2 0
      src/core/config/Categories.js
  2. 18 0
      src/core/config/OperationConfig.js
  3. 205 0
      src/core/lib/jsonpath.js
  4. 39 0
      src/core/operations/Code.js
  5. 181 0
      test/tests/operations/Code.js

+ 2 - 0
src/core/config/Categories.js

@@ -215,6 +215,7 @@ const Categories = [
             "Extract dates",
             "Regular expression",
             "XPath expression",
+            "JPath expression",
             "CSS selector",
             "Extract EXIF",
         ]
@@ -278,6 +279,7 @@ const Categories = [
             "CSS Beautify",
             "CSS Minify",
             "XPath expression",
+            "JPath expression",
             "CSS selector",
             "Strip HTML tags",
             "Diff",

+ 18 - 0
src/core/config/OperationConfig.js

@@ -2243,6 +2243,24 @@ const OperationConfig = {
             }
         ]
     },
+    "JPath expression": {
+        description: "Extract information from a JSON object with a JPath query.",
+        run: Code.runJpath,
+        inputType: "string",
+        outputType: "string",
+        args: [
+            {
+                name: "JPath",
+                type: "string",
+                value: Code.JPATH_INITIAL
+            },
+            {
+                name: "Result delimiter",
+                type: "binaryShortString",
+                value: Code.JPATH_DELIMITER
+            }
+        ]
+    },
     "CSS selector": {
         description: "Extract information from an HTML document with a CSS selector",
         run: Code.runCSSQuery,

文件差異過大導致無法顯示
+ 205 - 0
src/core/lib/jsonpath.js


+ 39 - 0
src/core/operations/Code.js

@@ -4,6 +4,7 @@ import Utils from "../Utils.js";
 import vkbeautify from "vkbeautify";
 import {DOMParser as dom} from "xmldom";
 import xpath from "xpath";
+import jpath from "../lib/jsonpath.js";
 import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js";
 
 
@@ -354,6 +355,44 @@ const Code = {
         return nodes.map(nodeToString).join(delimiter);
     },
 
+    /**
+     * @constant
+     * @default
+     */
+    JPATH_INITIAL: "",
+
+    /**
+     * @constant
+     * @default
+     */
+    JPATH_DELIMITER: "\\n",
+
+    /**
+     * XPath expression operation.
+     *
+     * @author Matt C (matt@artemisbot.uk)
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    runJpath: function(input, args) {
+        let query = args[0],
+            delimiter = args[1],
+            results,
+            obj;
+        try {
+            obj = JSON.parse(input);
+        } catch (err) {
+            return "Invalid input JSON.";
+        }
+        try {
+            results = jpath.query(obj, query);
+        } catch (e) {
+            return "Invalid JPath expression.";
+        }
+        return results.map(result => JSON.stringify(result)).join(delimiter);
+    },
+
 
     /**
      * @constant

+ 181 - 0
test/tests/operations/Code.js

@@ -2,12 +2,54 @@
  * Code tests.
  *
  * @author tlwr [toby@toby.codes]
+ * @author Matt C [matt@artemisbot.uk]
  *
  * @copyright Crown Copyright 2017
  * @license Apache-2.0
  */
 import TestRegister from "../../TestRegister.js";
 
+const JPATH_TEST_DATA = {
+    "store": {
+        "book": [{
+            "category": "reference",
+            "author": "Nigel Rees",
+            "title": "Sayings of the Century",
+            "price": 8.95
+        }, {
+            "category": "fiction",
+            "author": "Evelyn Waugh",
+            "title": "Sword of Honour",
+            "price": 12.99
+        }, {
+            "category": "fiction",
+            "author": "Herman Melville",
+            "title": "Moby Dick",
+            "isbn": "0-553-21311-3",
+            "price": 8.99
+        }, {
+            "category": "fiction",
+            "author": "J. R. R. Tolkien",
+            "title": "The Lord of the Rings",
+            "isbn": "0-395-19395-8",
+            "price": 22.99
+        }],
+        "bicycle": {
+            "color": "red",
+            "price": 19.95
+        },
+        "newspaper": [{
+            "format": "broadsheet",
+            "title": "Financial Times",
+            "price": 2.75
+        }, {
+            "format": "tabloid",
+            "title": "The Guardian",
+            "price": 2.00
+        }]
+    }
+};
+
 TestRegister.addTests([
     {
         name: "To Camel case (dumb)",
@@ -129,4 +171,143 @@ TestRegister.addTests([
             }
         ],
     },
+    {
+        name: "JPath Expression: Empty JSON",
+        input: "",
+        expectedOutput: "Invalid input JSON.",
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: Empty expression",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: "Invalid JPath expression.",
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: Fetch of values from specific object",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "\"Nigel Rees\"",
+            "\"Evelyn Waugh\"",
+            "\"Herman Melville\"",
+            "\"J. R. R. Tolkien\""
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$.store.book[*].author", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: Fetch of all values with matching key",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "\"Sayings of the Century\"",
+            "\"Sword of Honour\"",
+            "\"Moby Dick\"",
+            "\"The Lord of the Rings\"",
+            "\"Financial Times\"",
+            "\"The Guardian\""
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$..title", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: All data in object",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}]",
+            "{\"color\":\"red\",\"price\":19.95}",
+            "[{\"format\":\"broadsheet\",\"title\":\"Financial Times\",\"price\":2.75},{\"format\":\"tabloid\",\"title\":\"The Guardian\",\"price\":2}]"
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$.store.*", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: Last element in array",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: "{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}",
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$..book[-1:]", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: First 2 elements in array",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95}",
+            "{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99}"
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$..book[:2]", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: All elements in array with property",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}",
+            "{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}"
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$..book[?(@.isbn)]", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: All elements in array which meet condition",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99}",
+            "{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}",
+            "{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}"
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$..book[?(@.price<30 && @.category==\"fiction\")]", "\n"]
+            }
+        ],
+    },
+    {
+        name: "JPath Expression: All elements in object",
+        input: JSON.stringify(JPATH_TEST_DATA),
+        expectedOutput: [
+            "{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95}",
+            "{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}"
+        ].join("\n"),
+        recipeConfig: [
+            {
+                "op": "JPath expression",
+                "args": ["$..book[?(@.price<10)]", "\n"]
+            }
+        ],
+    },
 ]);

部分文件因文件數量過多而無法顯示