{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1745909478,
"reponame":"libwebsockets",
"desc":"libwebsockets lightweight C networking library",
"owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets",
"f":3,
"items": [
{"schema":"libjg2-1",
"cid":"cacf1654277d975f8426a930a5e32af3",
"commit": {"type":"commit",
"time": 1592625390,
"time_ofs": 60,
"oid_tree": { "oid": "70abeab486578448c30f4f4b9093b410e1df34e8", "alias": []},
"oid":{ "oid": "5a937fa830c536f52f2d8a6292190457e65a8dbd", "alias": []},
"msg": "lws_json_simple_find and lws_nstrstr",
"sig_commit": { "git_time": { "time": 1592625390, "offset": 60 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },
"sig_author": { "git_time": { "time": 1592561456, "offset": 60 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }},
"body": "lws_json_simple_find and lws_nstrstr\n\nString helpers for scanning non-NUL-delimited strings safely,\nand very cheap simple string match based JSON parse for cases\nthat make sense for it... for more complex cases, do a full\nJSON parse."
,
"diff": "diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h\nindex f71158a..e918550 100644\n--- a/include/libwebsockets/lws-misc.h\n+++ b/include/libwebsockets/lws-misc.h\n@@ -181,6 +181,68 @@ lws_strncpy(char *dest, const char *src, size_t size);\n \t\t\t\t(size_t)(size1 + 1) : (size_t)(destsize))\n \n /**\n+ * lws_nstrstr(): like strstr for length-based strings without terminating NUL\n+ *\n+ * \u005cparam buf: the string to search\n+ * \u005cparam len: the length of the string to search\n+ * \u005cparam name: the substring to search for\n+ * \u005cparam nl: the length of name\n+ *\n+ * Returns NULL if \u005cp name is not present in \u005cp buf. Otherwise returns the\n+ * address of the first instance of \u005cp name in \u005cp buf.\n+ *\n+ * Neither buf nor name need to be NUL-terminated.\n+ */\n+LWS_VISIBLE LWS_EXTERN const char *\n+lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl);\n+\n+/**\n+ * lws_json_simple_find(): dumb JSON string parser\n+ *\n+ * \u005cparam buf: the JSON to search\n+ * \u005cparam len: the length of the JSON to search\n+ * \u005cparam name: the name field to search the JSON for, eg, \u0022\u005c\u0022myname\u005c\u0022:\u0022\n+ * \u005cparam alen: set to the length of the argument part if non-NULL return\n+ *\n+ * Either returns NULL if \u005cp name is not present in buf, or returns a pointer\n+ * to the argument body of the first instance of \u005cp name, and sets *alen to the\n+ * length of the argument body.\n+ *\n+ * This can cheaply handle fishing out, eg, myarg from {\u0022myname\u0022: \u0022myarg\u0022} by\n+ * searching for \u0022\u005c\u0022myname\u005c\u0022:\u0022. It will return a pointer to myarg and set *alen\n+ * to 5. It equally handles args like \u0022myname\u0022: true, or \u0022myname\u0022:false, and\n+ * null or numbers are all returned as delimited strings.\n+ *\n+ * Anything more complicated like the value is a subobject or array, you should\n+ * parse it using a full parser like lejp. This is suitable is the JSON is\n+ * and will remain short and simple, and contains well-known names amongst other\n+ * extensible JSON members.\n+ */\n+LWS_VISIBLE LWS_EXTERN const char *\n+lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen);\n+\n+/**\n+ * lws_json_simple_strcmp(): dumb JSON string comparison\n+ *\n+ * \u005cparam buf: the JSON to search\n+ * \u005cparam len: the length of the JSON to search\n+ * \u005cparam name: the name field to search the JSON for, eg, \u0022\u005c\u0022myname\u005c\u0022:\u0022\n+ * \u005cparam comp: return a strcmp of this and the discovered argument\n+ *\n+ * Helper that combines lws_json_simple_find() with strcmp() if it was found.\n+ * If the \u005cp name was not found, returns -1. Otherwise returns a strcmp()\n+ * between what was found and \u005cp comp, ie, return 0 if they match or something\n+ * else if they don't.\n+ *\n+ * If the JSON is relatively simple and you want to target constrained\n+ * devices, this can be a good choice. If the JSON may be complex, you\n+ * should use a full JSON parser.\n+ */\n+LWS_VISIBLE LWS_EXTERN int\n+lws_json_simple_strcmp(const char *buf, size_t len, const char *name, const char *comp);\n+\n+\n+/**\n * lws_hex_to_byte_array(): convert hex string like 0123456789ab into byte data\n *\n * \u005cparam h: incoming NUL-terminated hex string\ndiff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c\nindex adecc1c..d034fe7 100644\n--- a/lib/core/libwebsockets.c\n+++ b/lib/core/libwebsockets.c\n@@ -345,6 +345,117 @@ lws_strdup(const char *s)\n \treturn d;\n }\n \n+const char *\n+lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl)\n+{\n+\tconst char *end \u003d buf + len - nl + 1;\n+\tsize_t n;\n+\n+\tif (nl \u003e len)\n+\t\t/* it cannot be found if the needle is longer than the haystack */\n+\t\treturn NULL;\n+\n+\twhile (buf \u003c end) {\n+\t\tif (*buf !\u003d name[0]) {\n+\t\t\tbuf++;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (nl \u003d\u003d 1)\n+\t\t\t/* single char match, we are done */\n+\t\t\treturn buf;\n+\n+\t\tif (buf[nl - 1] \u003d\u003d name[nl - 1]) {\n+\t\t\t/*\n+\t\t\t * This is looking interesting then... the first\n+\t\t\t * and last chars match, let's check the insides\n+\t\t\t */\n+\t\t\tn \u003d 1;\n+\t\t\twhile (n \u003c nl \u0026\u0026 buf[n] \u003d\u003d name[n])\n+\t\t\t\tn++;\n+\n+\t\t\tif (n \u003d\u003d nl)\n+\t\t\t\t/* it's a hit */\n+\t\t\t\treturn buf;\n+\t\t}\n+\n+\t\tbuf++;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+/*\n+ * name wants to be something like \u0022\u005c\u0022myname\u005c\u0022:\u0022\n+ */\n+\n+const char *\n+lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen)\n+{\n+\tsize_t nl \u003d strlen(name);\n+\tconst char *np \u003d lws_nstrstr(buf, len, name, nl),\n+\t\t *end \u003d buf + len, *as;\n+\tint qu \u003d 0;\n+\n+\tif (!np)\n+\t\treturn NULL;\n+\n+\tnp +\u003d nl;\n+\n+\twhile (np \u003c end \u0026\u0026 (*np \u003d\u003d ' ' || *np \u003d\u003d '\u005ct'))\n+\t\tnp++;\n+\n+\tif (np \u003e\u003d end - 1)\n+\t\treturn NULL;\n+\n+\t/*\n+\t * The arg could be lots of things after \u0022name\u0022: with JSON, commonly a\n+\t * string like \u0022mystring\u0022, true, false, null, [...] or {...} ... we want\n+\t * to handle common, simple cases cheaply with this; the user can choose\n+\t * a full JSON parser like lejp if it's complicated. So if no opening\n+\t * quote, return until a terminator like , ] }. If there's an opening\n+\t * quote, return until closing quote, handling escaped quotes.\n+\t */\n+\n+\tif (*np \u003d\u003d '\u005c\u0022') {\n+\t\tqu \u003d 1;\n+\t\tnp++;\n+\t}\n+\n+\tas \u003d np;\n+\twhile (np \u003c end \u0026\u0026\n+\t (!qu || *np !\u003d '\u005c\u0022') \u0026\u0026 /* end quote is EOT if quoted */\n+\t (qu || (*np !\u003d '}' \u0026\u0026 *np !\u003d ']' \u0026\u0026 *np !\u003d ',')) /* delimiters */\n+\t) {\n+\t\tif (qu \u0026\u0026 *np \u003d\u003d '\u005c\u005c') /* skip next char if quoted escape */\n+\t\t\tnp++;\n+\t\tnp++;\n+\t}\n+\n+\tif (np \u003d\u003d end)\n+\t\treturn NULL;\n+\n+\t*alen \u003d lws_ptr_diff(np, as);\n+\n+\treturn as;\n+}\n+\n+int\n+lws_json_simple_strcmp(const char *buf, size_t len, const char *name,\n+\t\t const char *comp)\n+{\n+\tsize_t al;\n+\tconst char *hit \u003d lws_json_simple_find(buf, len, name, \u0026al);\n+\n+\tif (!hit)\n+\t\treturn -1;\n+\n+\tif (al !\u003d strlen(comp))\n+\t\treturn -1;\n+\n+\treturn strncmp(hit, comp, al);\n+}\n+\n static const char *hex \u003d \u00220123456789ABCDEF\u0022;\n \n const char *\ndiff --git a/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/minimal-examples/api-tests/api-test-lws_tokenize/main.c\nindex 7682ede..e6d26d6 100644\n--- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c\n+++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c\n@@ -417,6 +417,73 @@ int main(int argc, const char **argv)\n \t\treturn 1;\n \t}\n \n+\t/* sanity check lws_nstrstr() */\n+\n+\t{\n+\t\tstatic const char *t1 \u003d \u0022abc123456\u0022;\n+\t\tconst char *mcp;\n+\n+\t\tmcp \u003d lws_nstrstr(t1, strlen(t1), \u0022abc\u0022, 3);\n+\t\tif (mcp !\u003d t1) {\n+\t\t\tlwsl_err(\u0022%s: lws_nstrstr 1 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tmcp \u003d lws_nstrstr(t1, strlen(t1), \u0022def\u0022, 3);\n+\t\tif (mcp !\u003d NULL) {\n+\t\t\tlwsl_err(\u0022%s: lws_nstrstr 2 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tmcp \u003d lws_nstrstr(t1, strlen(t1), \u0022456\u0022, 3);\n+\t\tif (mcp !\u003d t1 + 6) {\n+\t\t\tlwsl_err(\u0022%s: lws_nstrstr 3 failed: %p\u005cn\u0022, __func__, mcp);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tmcp \u003d lws_nstrstr(t1, strlen(t1), \u00221\u0022, 1);\n+\t\tif (mcp !\u003d t1 + 3) {\n+\t\t\tlwsl_err(\u0022%s: lws_nstrstr 4 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tmcp \u003d lws_nstrstr(t1, strlen(t1), \u0022abc1234567\u0022, 10);\n+\t\tif (mcp !\u003d NULL) {\n+\t\t\tlwsl_err(\u0022%s: lws_nstrstr 5 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\n+\t/* sanity check lws_json_simple_find() */\n+\n+\t{\n+\t\tstatic const char *t1 \u003d \u0022{\u005c\u0022myname1\u005c\u0022:true,\u0022\n+\t\t\t\t\t \u0022\u005c\u0022myname2\u005c\u0022:\u005c\u0022string\u005c\u0022, \u0022\n+\t\t\t\t\t \u0022\u005c\u0022myname3\u005c\u0022: 123}\u0022;\n+\t\tsize_t alen;\n+\t\tconst char *mcp;\n+\n+\t\tmcp \u003d lws_json_simple_find(t1, strlen(t1), \u0022\u005c\u0022myname1\u005c\u0022:\u0022, \u0026alen);\n+\t\tif (mcp !\u003d t1 + 11 || alen !\u003d 4) {\n+\t\t\tlwsl_err(\u0022%s: lws_json_simple_find 1 failed: (%d) %s\u005cn\u0022, __func__, (int)alen, mcp);\n+\t\t\treturn 1;\n+\t\t}\n+\n+\t\tmcp \u003d lws_json_simple_find(t1, strlen(t1), \u0022\u005c\u0022myname2\u005c\u0022:\u0022, \u0026alen);\n+\t\tif (mcp !\u003d t1 + 27 || alen !\u003d 6) {\n+\t\t\tlwsl_err(\u0022%s: lws_json_simple_find 2 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\n+\t\tmcp \u003d lws_json_simple_find(t1, strlen(t1), \u0022\u005c\u0022myname3\u005c\u0022:\u0022, \u0026alen);\n+\t\tif (mcp !\u003d t1 + 47 || alen !\u003d 3) {\n+\t\t\tlwsl_err(\u0022%s: lws_json_simple_find 3 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\n+\t\tmcp \u003d lws_json_simple_find(t1, strlen(t1), \u0022\u005c\u0022nope\u005c\u0022:\u0022, \u0026alen);\n+\t\tif (mcp !\u003d NULL) {\n+\t\t\tlwsl_err(\u0022%s: lws_json_simple_find 4 failed\u005cn\u0022, __func__);\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\n \tp \u003d lws_cmdline_option(argc, argv, \u0022-s\u0022);\n \n \tfor (n \u003d 0; n \u003c (int)LWS_ARRAY_SIZE(tests); n++) {\n","s":{"c":1745909478,"u": 9300}}
],"g": 10923,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}