[ { "id": "379c65a27117b46c", "type": "tab", "label": "Home", "disabled": false, "info": "\n" }, { "id": "42b9663b67dbd983", "type": "tab", "label": "Files", "disabled": false, "info": "" }, { "id": "4b5e055cd6b1e387", "type": "tab", "label": "Form Processing", "disabled": false, "info": "" }, { "id": "8179bf22c4c31682", "type": "tab", "label": "Functions", "disabled": false, "info": "# Functions\n\nContained within are reusable functions.", "env": [ { "name": "oidc", "value": "false", "type": "bool" } ] }, { "id": "104f7938a23fe82f", "type": "tab", "label": "ITSM: GLPI", "disabled": false, "info": "", "env": [] }, { "id": "f6f2187d.f17ca8", "type": "tab", "label": "GLPI: FormCreator Automation", "disabled": false, "info": "# GLPI: FormCreator Automation\nThis flow search for the forms from the GLPI Plugin formcreator.\nOn finding a form, creates a ticket from that form." }, { "id": "24deed6b10f37f8f", "type": "tab", "label": "Cron", "disabled": false, "info": "# Cron\n\nThis flow contains any tasks that need to be run automagically", "env": [] }, { "id": "8ad5fe68ad170e2d", "type": "group", "z": "42b9663b67dbd983", "name": "Form: Password Reset Questions", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true }, "nodes": [ "02c4b9524d361ade", "365ba07c1f4721ec", "50339f503fd4878d", "591e68e90f876dd1", "7e95892f2f3454b7", "9b89c2da58fccb8d", "99a3fa75430c37f7", "b2c917da9e845f7a", "5798e39cbc3730ae", "52dc13e1fdbf064d", "d460346f6ae1673b" ], "x": 154, "y": 919, "w": 1912, "h": 122 }, { "id": "ad0235dd3aa9eb7d", "type": "group", "z": "42b9663b67dbd983", "name": "Form: Password Reset", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true }, "nodes": [ "2dc375bf57ad8daa", "1ce803b83ecf1593", "f3b55ea2.f4d51", "bf098463143ac8ad", "457583335831f826", "317930c679e833d1" ], "x": 154, "y": 779, "w": 1092, "h": 82 }, { "id": "1c5c6c543ef047b6", "type": "group", "z": "42b9663b67dbd983", "name": "Home Page", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true }, "nodes": [ "0172c4a240b566fd", "2106525aa2ebda7d", "4ecc0631139b51e0", "2f628eec7ca4b343" ], "x": 154, "y": 399, "w": 812, "h": 82 }, { "id": "a64f4a2c837d5c3c", "type": "group", "z": "42b9663b67dbd983", "name": "Error Page", "style": { "stroke": "#ffC000", "fill": "#ffefbf", "label": true }, "nodes": [ "fd80fd11fc971e2c", "50d19d3ce5cf88f2", "e5ae19af5f6d6561", "781d23c946457b30", "9d93b8dfe83bf3ca", "e551d77d5412aced", "4ed718e1ae800bad" ], "x": 1314, "y": 19, "w": 812, "h": 127 }, { "id": "a8e6ecf8ae37659e", "type": "group", "z": "42b9663b67dbd983", "name": "HTML Page Template", "style": { "stroke": "#6f2fa0", "fill": "#dbcbe7", "label": true }, "nodes": [ "3ec10e706b7bdc9d", "8bdcaea510dbad1e", "6fc3fe2eef3733b0" ], "x": 154, "y": 19, "w": 692, "h": 82 }, { "id": "0abe2cea5975dcfd", "type": "group", "z": "42b9663b67dbd983", "name": "Account Details", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true }, "nodes": [ "e50f46892eabd2a5", "46ef4f0739d6c1b8", "1d661b2385de4b4a", "c9323e9dc74c9203" ], "x": 154, "y": 519, "w": 812, "h": 82 }, { "id": "07f2249ad4b7ccd0", "type": "group", "z": "42b9663b67dbd983", "name": "Change Password", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true }, "nodes": [ "b5cedc58894f707e", "54b1149ed3d047fe", "0c2e73371d4238a1", "dcfa3cfba4eb1356" ], "x": 154, "y": 639, "w": 812, "h": 82 }, { "id": "d3393ec35cb20a93", "type": "group", "z": "42b9663b67dbd983", "name": "", "style": { "label": true, "stroke": "#92d04f", "fill": "#e3f3d3" }, "nodes": [ "a702d39f0f3180de", "3502d9cf69680b66", "f1dcd5b6e32fb905" ], "x": 164, "y": 139, "w": 462, "h": 82 }, { "id": "3e330505ea1e9cba", "type": "group", "z": "42b9663b67dbd983", "name": "", "style": { "stroke": "#ff0000", "fill": "#ffbfbf", "label": true }, "nodes": [ "c8c3f9c8f2ee35ee", "602e7197835bba91", "b664f0b9e6c17ad6" ], "x": 694, "y": 239, "w": 492, "h": 82 }, { "id": "b447a1f691eb02df", "type": "group", "z": "42b9663b67dbd983", "name": "Logout", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true }, "nodes": [ "fb5301abffede979", "988765ea19236af0", "abcdd1bd3d9d1892", "c17fe14224b2a367" ], "x": 154, "y": 1099, "w": 752, "h": 82, "info": "# Logout\n\nThis group contains the `/logout` path.\nAs part of this groups glow, when navigated to. \nThe users cookie is set to expire and the user session is removed from the filesystem." }, { "id": "0d96945ec7d069cb", "type": "group", "z": "8179bf22c4c31682", "name": "Returns: dict, msg.hash", "style": { "label": true }, "nodes": [ "0eeaba70b043a226", "9c9c7bbd71c78d8e", "43eebf1623f29074", "8fadd3c4294a6939", "540882a95f65754c" ], "x": 114, "y": 79, "w": 972, "h": 109.5 }, { "id": "bcd2727d77a80ce3", "type": "group", "z": "8179bf22c4c31682", "name": "Returns: string, msg.filename", "style": { "label": true }, "nodes": [ "8c13bbcc86d93be8", "a35b8cc53c276d62", "858268a5d48a4486", "998b007182d85455", "0f2ff2f433d17eef" ], "x": 114, "y": 239, "w": 912, "h": 82 }, { "id": "3b96ab15b1a54e33", "type": "group", "z": "4b5e055cd6b1e387", "name": "Save Password Reset Questions", "style": { "stroke": "#ff0000", "fill": "#7fb7df", "label": true, "color": "#ffff00" }, "nodes": [ "bb8102ee0c070ff2", "629b7df0515c7d83", "a712f5e2056bbb1b", "e9f50265154e4b83", "1e3c2b23420d6e40", "cee76f9f914dd0fa", "fba98a197970c6ee", "edf62fa2ca3cd812", "5210f540af1eb2e5", "96836f5a4c7c756c", "6ec9911b7ad7d042", "3f128f23d72e0492", "7ce13238fa87d636", "8b70b96b1f62a785", "05accf0d9a6f0aa8" ], "x": 134, "y": 119, "w": 2312, "h": 182 }, { "id": "10a6c6b12749dda9", "type": "group", "z": "8179bf22c4c31682", "name": "Returns: string msg.payload", "style": { "label": true }, "nodes": [ "804feccd90b3276c", "869469819396a632", "c4e40d6f6678bb55", "e62119d30db09cce", "8e670403cf071aaf" ], "x": 114, "y": 359, "w": 1012, "h": 122 }, { "id": "9b1493c4ae19a935", "type": "group", "z": "8179bf22c4c31682", "name": "Workflow: ITSM Selection", "style": { "fill": "#e3f3d3", "label": true }, "nodes": [ "b8c9f1cf125efd2e", "f5cae04225998e3b", "002457f33834fc91", "d4d1ce730aa1c15b", "9858d84dc9d001be", "6840ab77f76439db" ], "x": 94, "y": 639, "w": 4744, "h": 834, "info": "# Input Format\n\n``` json\n{\n \"data\": {\n // contains the data for the action\n },\n \"action\": \"search\",\n \"action_for\": \"user\"\n}\n```" }, { "id": "a9d52eb951c5f037", "type": "group", "z": "4b5e055cd6b1e387", "name": "Password Reset", "style": { "stroke": "#ff0000", "fill": "#7fb7df", "label": true, "color": "#ffff00" }, "nodes": [ "aea0a3398dafab4c", "4cdbeaa8f5f3ddb7", "82ccba0e0a13970a", "d0dc259791aed430", "d1b4f7ad9e8ea4f0", "4cdebccc4a1f08ed", "9926c0ba3f91aca8", "02dc457b6549ba4e" ], "x": 128, "y": 333, "w": 2798, "h": 774, "info": "# Password Reset Form Processing\n\nThis group is responsible for processing the data from the password reset form. the basic workflow is as follows:\n\n- Form validation\n\n- LDAP User Search\n\n- ITSM User Search: if enabled searches for user within itsm system\n\n- ITSM Ticket: if enabled, creates ticket within ITSM system\n\n- Response: User notification\n" }, { "id": "bbd929c437c592ea", "type": "group", "z": "8179bf22c4c31682", "name": "Authentication", "style": { "stroke": "#6f2fa0", "fill": "#ffbfbf", "label": true, "color": "#777777" }, "nodes": [ "f17afdbfc8c07889", "6c790a65bbdc61a5", "bc039e4b516adf37", "627a72eee1e26ae6", "177a7aba70483ccb", "7225c45ad941c14f", "e80aabc47c664088", "724a142f28c3b6e4", "f9550cdd015b52ae", "cc33365c2aa59e35", "69f0d6271fe16536", "1552576e6e79e172", "3fa2f7ecc012d8c6", "a67892bd64d2ded4" ], "x": 94, "y": 1527, "w": 3012, "h": 1334, "info": "# Authentication\n\nThis group is responsible for ensuring the user is authorized to access the system. \nAny valid user account that authenticates to the system is authorized.\n\nFrom entry the next step in the process is cookie validation.\n\n## Input Data\n\nThis group has two paths for entry: \n\n1. Cookie Found - `msg.req.cookies.auth` key exists\n\n > Value is the session name.\n\n1. No Cookie Found - `msg.req.cookies.auth` key does not exist\n\n > User to be redirected to authentication method\n\n\n## Output Data\n\nThis group does not always not return data. \nData returned is only stored in `msg.session`.\n\n### Authenticated User\n\n`msg.session` is returned with the Authentication data contained. \n\nThis data will either be from a stored session (user authenticated previously) or be created via the authentication method.\nThere are two session types and they are `token` and `oauth2`. Session types are directly tied to the method of authentication.\n\n`msg.session` structure\n\n``` json\n{\n \"session\": {\n \"datetime\": \"{session expiry}\",\n \"type\": \"token\",\n \"user\"{\n \"username\": \"barny.gumble\",\n \"fname\": \"Barny\",\n \"lname\": \"Gumble\",\n \"mail\": \"barney.gumble@dinomail.com\"\n },\n \"oauth2\": {\n // Only if type=oauth2\n }\n }\n}\n\n```\n\n### Non-Authenticated User\n\nNo data is returned if the user is not authenticated. The absense of `msg.session` denotes an unauthenticated user.\n" }, { "id": "b994fe21efb223a9", "type": "group", "z": "379c65a27117b46c", "name": "Automagic: Config to global", "style": { "stroke": "#6f2fa0", "fill": "#92d04f", "label": true, "color": "#ffff00" }, "nodes": [ "c7ca92d48206b4b2", "de01a4559aecf1c4", "842ade29052f7e66", "957b63c9fc58a139", "02812e8708980b09", "e83ed4274d3959f3", "06b5d27bbf1e5b16", "32d8df5c0bb564cb", "fb7fea44905cf7a4", "2d4bed7c63632c6c" ], "x": 154, "y": 59, "w": 1032, "h": 182 }, { "id": "3b247f5e5d90963e", "type": "group", "z": "4b5e055cd6b1e387", "name": "Change Password", "style": { "stroke": "#ff0000", "fill": "#7fb7df", "label": true, "color": "#ffff00" }, "nodes": [ "f8ec4a6290dc7e20", "b75415bd2541b6df", "a6c8721721fc267e", "dba3741d6cc275c9", "1e614fa32322f125", "0c16bf9634323276" ], "x": 128, "y": 1133, "w": 4704, "h": 228, "info": "# Change User Password\n\nThis group contains the workflow to change a users password within LDAP.\n\nThe workflow has th following steps:\n\n1. Validate the form input\n\n1. Check that the new password fields match\n\n1. Confirm that the user entered \"Current Password\" matches what's in LDAP\n\n1. Change the users password within LDAP.\n" }, { "id": "9d9f0106c9ca9adf", "type": "group", "z": "379c65a27117b46c", "name": "HTTP Server", "style": { "stroke": "#6f2fa0", "fill": "#e3f3d3", "label": true, "color": "#000000" }, "nodes": [ "cf2a3f84cb26a12c", "755ff25cc29a08a1", "ec8733df4e619869", "8363d385051fc5c0", "5706252b01492258", "f3aa07300888f0a4", "923268ee62c6a7db", "f3aa07300888f0a4" ], "x": 148, "y": 313, "w": 2964, "h": 914, "info": "# HTTP Server\n\nThis group provides the entrypoint for the application. it's broken down into further sub-groups that have their own individual responsibilities for processing a part of the HTTP servers workflow." }, { "id": "b5d607bb9a62875f", "type": "group", "z": "24deed6b10f37f8f", "name": "Trigger", "style": { "stroke": "#92d04f", "fill": "#bfdbef", "label": true, "color": "#777777" }, "nodes": [ "8e0d9bd8043dd53b", "79e414f65b0e157b", "8f313772a6e82e96", "7e6699ce0159226a", "61115e9c6e619dae", "2d78bd7d0f411721", "47f68cd20a8a528b", "348b594ba5acb470", "2bcdbb78b4e9181f" ], "x": 54, "y": 99 }, { "id": "f7c0a5bee0e0df33", "type": "group", "z": "24deed6b10f37f8f", "name": "Task: Clean Expired Tokens", "style": { "stroke": "#6f2fa0", "fill": "#e3f3d3", "label": true, "color": "#777777" }, "nodes": [ "8c5bb81ae0b14703", "b2e1cdc1778fd936", "f4da55e70a4f8c2c", "44c01ba9bfc47ee8", "55d7ad6e4958f882", "bb5ccb49f1aa1036", "f5f9e14092781e29", "e25b155a2a29f16d", "0f30a271d9c71f74", "966779cca7297dec", "a3bd692422c0fcf5", "291408859782056d" ], "x": 1274, "y": 99 }, { "id": "e8558844b3710e7b", "type": "group", "z": "8179bf22c4c31682", "name": "Returns: string, msg.filename (Session File)", "style": { "label": true }, "nodes": [ "17276c106d99423c", "dacd02c9aec07af9", "745056010192e36a", "aade2f705a555f31", "1bc65c1f44b4a1ac", "b595d8148f247f69" ], "x": 114, "y": 519, "w": 992, "h": 82 }, { "id": "8f9d362a10096ca7", "type": "group", "z": "8179bf22c4c31682", "style": { "stroke": "#999999", "stroke-opacity": "1", "fill": "none", "fill-opacity": "1", "label": true, "label-position": "nw", "color": "#a4a4a4" }, "nodes": [], "x": 0, "y": 0, "w": 40, "h": 40 }, { "id": "aea0a3398dafab4c", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "Invalid User Response", "style": { "stroke": "#ff0000", "fill": "#e3f3d3", "label": true, "color": "#777777" }, "nodes": [ "72721ec69edf230f", "8eca6e69b809790c" ], "x": 2214, "y": 999, "w": 512, "h": 82 }, { "id": "9858d84dc9d001be", "type": "group", "z": "8179bf22c4c31682", "g": "9b1493c4ae19a935", "name": "GLPI", "style": { "fill": "#d1d1d1", "label": true }, "nodes": [ "160bc27f7530e52d", "4cdb1540cd4c8744", "0676d69c05236349", "edbb6827a8b33085", "ed0645c12f7435b2", "d7dbd3970c891c33" ], "x": 234, "y": 813, "w": 4578, "h": 634 }, { "id": "82ccba0e0a13970a", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "Respond: Success", "style": { "stroke": "#6f2fa0", "fill": "#e3f3d3", "label": true }, "nodes": [ "b1bc2e62654b04e2", "f125e4c474dd2e5c" ], "x": 2214, "y": 899, "w": 512, "h": 82 }, { "id": "d0dc259791aed430", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true }, "nodes": [ "9090daaf8a5892b0", "853e6c15b5317007", "142f9ce43cb63dd7", "c710ba5a1416cfd8", "073709e754dd98a3", "ec52cbc3aa0fec25", "13711f1826f83198" ], "x": 574, "y": 959, "w": 1432, "h": 122 }, { "id": "d1b4f7ad9e8ea4f0", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "ITSM: Create Ticket", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true }, "nodes": [ "8dd7c0779eac59f0", "00066fdae59433b8", "93434028042529b8", "ad66e8c05ee9a664", "dce8db9b841faf7f", "1a29880acc851ff5" ], "x": 834, "y": 819, "w": 912, "h": 122 }, { "id": "4cdebccc4a1f08ed", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "Search LDAP for user", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true, "color": "#777777" }, "nodes": [ "c66c2a0c3817433c", "c08e353c85cde934", "311e184a2397eb19", "faa5e7380a3092a2", "fe1f0a50300d9224", "b10e8a45ff44f80d", "0308c42b587c3794", "04818ddd8782b0a1", "5cfc1e5277013397" ], "x": 434, "y": 519, "w": 1752, "h": 122 }, { "id": "9926c0ba3f91aca8", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "ITSM Search", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true }, "nodes": [ "07ed8c85583c5a2e", "4a4676456c27f256", "a43bd1f944ef851c", "eeb2b5a4e44d0c24", "bc29c53d4ef04184", "68628b6f32ec8b74", "dbeedddce12963de", "445623ba528e5df1", "58d1108b52842808", "f6fc2010d0af1e33" ], "x": 574, "y": 659, "w": 1452, "h": 142 }, { "id": "f8ec4a6290dc7e20", "type": "group", "z": "4b5e055cd6b1e387", "g": "3b247f5e5d90963e", "name": "Fetch Users Current Password", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true, "color": "#777777" }, "nodes": [ "6ef14d9fb582d42e", "30264cfad476079a", "53fce6f461eec779", "553d0da331015252", "1619699cd34defb4", "815ce9e0380e642f" ], "x": 1074, "y": 1159, "w": 1072, "h": 122 }, { "id": "cf2a3f84cb26a12c", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "Methods", "style": { "stroke": "#001f60", "fill": "#ffbfbf", "label": true, "color": "#000000" }, "nodes": [ "c80657a01a03012d", "482740e98dda9d35", "1e0841f1.ac68fe", "5de0bbd4.6c8574", "28713941e03e2bf5", "adbfd4257ea1c230", "c6360f6028e1512c", "b174f7bc1d398a56", "3dc07bb0a7d4f647", "c58cfa3fc57972d1" ], "x": 174, "y": 339, "w": 572, "h": 202, "info": "# Methods\n\nThis sub-group is provides the http endpoints for the supported methods." }, { "id": "755ff25cc29a08a1", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "HTTP: Response", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true, "color": "#777777" }, "nodes": [ "564400f9ec708521", "e3043367c9a89a90", "7db929503cf13635", "3af3d2ae3286ffe0" ], "x": 2494, "y": 1079, "w": 572, "h": 122 }, { "id": "ec8733df4e619869", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "Fetch Content", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true, "color": "#000000" }, "nodes": [ "5c05dcd676fcb02a", "3ada862ebc07a99d", "eae031f35d9a1e9e", "4716d2916d6de31e", "6e74b4a9a6b2dac8", "6dc15589d8863139", "1b121b9ecdf14084", "ce290d371c7687b0", "f2026962fb8dbb44", "12a331c2a036a776", "68f30ef53ebc2074", "e2876b413d95adf9", "cad86e4a717ecb58", "333303604fa4ca01", "52395c2abfc3c4f5", "515f363d4f52f625", "f4f56319a112fd86", "1ee7757ab11df474", "51a40870ef7d7eec", "38b0e07a7e4cec42", "7f4255c2cbe633a5", "09cd31dda9fa3c50" ], "x": 994, "y": 559, "w": 1292, "h": 382, "info": "# Fetch Content\n\nThis sub-group is the third step in the http workflow.\n\nOnce authorized, this workflow fetches the html content to be displayed within the browser.\n" }, { "id": "8363d385051fc5c0", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "Process Forms", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true, "color": "#777777" }, "nodes": [ "9cbf4027b4ab1c04", "7c38c172df490c56", "75913f37.78e6e", "c0e5efefb8395690", "7b62ec12651e478a", "539d65720b0ff630", "0eb8679ee25c4a34", "3072b7c1fc0fd171", "64c99b312f9c601c", "9c92aaf02fee52b5", "b7fde07e47cc852e", "2189bf4e56868e51" ], "x": 994, "y": 979, "w": 1292, "h": 222, "info": "# Process Forms\n\nThis sub-group is the third step in the http workflow.\n\nThis sub-group is responsible for processing any forms that are sent to the server.\n" }, { "id": "5706252b01492258", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "Fetch Styles/JS", "style": { "stroke": "#0070c0", "fill": "#bfdbef", "label": true, "color": "#777777" }, "nodes": [ "acd5690f3865f156", "9f59194fecc0976a", "15721605aaae8a86", "eaeb9e2bfbe1dc95", "1b1ca0bd7037ed0f", "e72f08d8fc433bea", "d81c931de5a63675", "28ac8fd21056642c", "195e7631e8660db0", "e01b059fbd4cb54f", "dce9621aba915bd4", "31b86caaa955a0ee", "dc075811536fafda", "f5365376f49c255d" ], "x": 2374, "y": 559, "w": 712, "h": 422, "info": "# Fetch CSS / JS Files\n\nThis sub-group is the forth step in the http workflow, and specifically for HTTP/Get methods only.\n\nThis sub-group is responsible for fetching the appropriate CSS Style or JS Script that is required to fulfill the page request.\n" }, { "id": "f3aa07300888f0a4", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "HTTP Status Codes", "style": { "stroke": "#ffC000", "fill": "#ffffbf", "label": true, "color": "#777777" }, "nodes": [ "434d74f494db7cfc", "d17512b4de05ede1", "0ec392291c3fda2f", "c43678f82d52004f", "43603c3760e7ae56", "5ad10ea406e2d3a7", "c058f11dfd8d01b2" ], "x": 174, "y": 576.5, "w": 692, "h": 244.5 }, { "id": "923268ee62c6a7db", "type": "group", "z": "379c65a27117b46c", "g": "9d9f0106c9ca9adf", "name": "Authorization Check", "style": { "stroke": "#ff0000", "fill": "#ffcf3f", "label": true, "color": "#000000" }, "nodes": [ "2f1060b185e19215", "6728a85f5b044738", "46d8b11bdef459aa", "1c16492a7fe8e77b", "e282aea37a90acdc", "5f2f87eeebd5bf6e" ], "x": 994, "y": 339, "w": 932, "h": 162, "info": "# Authorization Check\n\nThis group is the second step within the http workflow. \n\nThis sub-group is responsible for ensuring that **ALL** requests to the http endpoint are authorized.\n" }, { "id": "02dc457b6549ba4e", "type": "group", "z": "4b5e055cd6b1e387", "g": "a9d52eb951c5f037", "name": "Form Validation", "style": { "stroke": "#ff0000", "fill": "#ffffbf", "label": true, "color": "#777777" }, "nodes": [ "cdde8116fcac6e5d", "0354e185d6df3087", "c7b7522a20abbb47", "3e44bc1a5e60ec3d" ], "x": 154, "y": 359, "w": 972, "h": 142, "info": "# Password Reset Form Processing\n\nThis sub-group is the fist step in processing the password reset form.\n\nfor the form workflow to continue processing the form, the form user details entered, must match the authenticated users details. The details **must** match, as without this matching and by design this form can reset the password of any user where the details are correcct." }, { "id": "dba3741d6cc275c9", "type": "group", "z": "4b5e055cd6b1e387", "g": "3b247f5e5d90963e", "name": "Form Validation", "style": { "label": true, "stroke": "#ff0000", "fill": "#ffffbf", "color": "#777777" }, "nodes": [ "98364b7271054017", "1df8ab6bb55ff621", "0239e19c34a9baaa", "0efd3333091c9999" ], "x": 154, "y": 1159, "w": 812, "h": 122, "info": "# Form Validation\n\nValidate the password change form." }, { "id": "1e614fa32322f125", "type": "group", "z": "4b5e055cd6b1e387", "g": "3b247f5e5d90963e", "name": "Check Current Password", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true, "color": "#777777" }, "nodes": [ "23292bc7d78b9d1d", "ffaae19e230436cf", "f17566766d0b5a53", "abef97c0bb13b432", "aab2d165deacdab6", "c57cf198943aef16" ], "x": 2214, "y": 1159, "w": 1152, "h": 122, "info": "# Check Current Password\n\nConfirm that the user entered \"current password\" matches the LDAP value" }, { "id": "0c16bf9634323276", "type": "group", "z": "4b5e055cd6b1e387", "g": "3b247f5e5d90963e", "name": "Change User Password", "style": { "stroke": "#ff0000", "fill": "#dbcbe7", "label": true, "color": "#777777" }, "nodes": [ "f093762ba0afe7d2", "53df7c8ab13e33de", "7b9797b6bc354e56", "e7fa19cf8785fd90", "f16ae7601e3dce19", "f8b9e1b1537129ec", "5897178ac3448e41" ], "x": 3394, "y": 1159, "w": 1412, "h": 122, "info": "# Change User Password\n\nChange the users password within LDAP" }, { "id": "177a7aba70483ccb", "type": "group", "z": "8179bf22c4c31682", "g": "bbd929c437c592ea", "name": "Cookie Validation", "style": { "stroke": "#ffC000", "fill": "#ffffbf", "label": true, "color": "#777777" }, "nodes": [ "bcaed4334222c14a" ], "x": 768, "y": 1553, "w": 1204, "h": 234 }, { "id": "cc33365c2aa59e35", "type": "group", "z": "8179bf22c4c31682", "g": "bbd929c437c592ea", "name": "Token", "style": { "stroke": "#0070c0", "fill": "#ffffbf", "label": true }, "nodes": [ "c10e09e4bfbddfd7", "53a5ee55ee916cec", "75c44e5f7f101beb", "a4bc5830daf9801a", "5851acefa1f1b5ff" ], "x": 774, "y": 1813, "w": 2072, "h": 334 }, { "id": "7225c45ad941c14f", "type": "group", "z": "8179bf22c4c31682", "g": "bbd929c437c592ea", "name": "Oauth2", "style": { "stroke": "#0070c0", "fill": "#ffffbf", "label": true, "color": "#777777" }, "nodes": [ "9f416bc258c1a60c", "bc5ca736a6e324e5", "8964a5bda9eb7113", "60a97c78327c3a6a", "8ad6190854001584", "21ec376b58ac0c54", "9f3711f96411e2cc", "f5e65e1ae7e8b812", "1e2dce9d25c567d6", "261436c730a46051", "97fb6e1471c0f7cd" ], "x": 774, "y": 2193, "w": 2078, "h": 394, "info": "# Oauth2 Authentication\n\n" }, { "id": "69f0d6271fe16536", "type": "group", "z": "8179bf22c4c31682", "g": "bbd929c437c592ea", "name": "Auth: Save Session", "style": { "stroke": "#0070c0", "fill": "#e3f3d3", "label": true, "color": "#777777" }, "nodes": [ "d24ebda198149601", "1380f91c814b8e2f", "c3a8957e4400e12f", "05880bb4ed6cab41", "10120b4cdade08c6", "3629b0bb901c20a7", "d43b2afbfaad2d31", "bcab3f1c2966f5aa", "150344ba8db2ceee", "4ff84724b26afc75", "3f5bfeb6ef2a9467", "5eaba17d961e2efb", "fb600cd457e87c43", "431bb2a5b956dd2c", "e2cbcdcc69e9ce21" ], "x": 234, "y": 2639, "w": 2352, "h": 182 }, { "id": "ed0645c12f7435b2", "type": "group", "z": "8179bf22c4c31682", "g": "9858d84dc9d001be", "name": "Create a Ticket", "style": { "fill": "#dbcbe7", "label": true }, "nodes": [ "d4de6eab89782579", "d20869bcacd7b0fd", "525cc01f4d41ae0b", "45d7aa8b4b386bb7", "2663cccd5d6ca575", "6492bc8146326691", "e363219f4309eedb", "c6c64453fc61e50f", "5eda003868c5e354", "2545718f1853e084", "1840577fd414a84d", "ed5a0fab59b28faa", "85fa24886e126df7", "246331e1c052e1f8", "e8f257b38aa4d749", "f57f557a25d166b7", "aa5626527a9df701", "5a961504d7ca5be3" ], "x": 754, "y": 1051.5, "w": 4032, "h": 369.5 }, { "id": "d7dbd3970c891c33", "type": "group", "z": "8179bf22c4c31682", "g": "9858d84dc9d001be", "name": "Search for User", "style": { "fill": "#dbcbe7", "label": true }, "nodes": [ "669724fdc876385d", "65c3e138bbcd8b3a", "269cbacf5274d6d8", "42f157ed01b737f4", "33d710f97adb5298", "6aac3151138c4af9", "587b497ce06d683f", "f76da20ac475cf64", "a9cfd4c1413c7ec6", "a888a2ed9a053acc" ], "x": 754, "y": 839, "w": 1412, "h": 182 }, { "id": "75c44e5f7f101beb", "type": "group", "z": "8179bf22c4c31682", "g": "cc33365c2aa59e35", "name": "Token Session", "style": { "label": true, "stroke": "#6f2fa0", "fill": "#bfdbef" }, "nodes": [ "42a1e057dda56f95", "366892fde876296f", "8b1fef39c34f5513", "95f44fbb0ddd39fc" ], "x": 1014, "y": 1839, "w": 672, "h": 122 }, { "id": "bcaed4334222c14a", "type": "group", "z": "8179bf22c4c31682", "g": "177a7aba70483ccb", "name": "Cookie Validation", "style": { "stroke": "#6f2fa0", "fill": "#bfdbef", "label": true, "color": "#777777" }, "nodes": [ "33f25da80ef87e72", "73b63d7562fe9cce", "e897aec8ea7c81c5", "9c05ca2751f619a7", "2dee51842e868755", "2a858bd15a2d257e", "f20711a44b43b7d4", "9cbf4beaceba5255", "da0811fbd7963934" ], "x": 794, "y": 1579, "w": 1152, "h": 182, "info": "# Cookie Validation\n\nThis path is always executed and is the first step in the authentication workflow. \n\nThis groups workflow is as follows:\n\n1. fetch the value of `msg.req.cookies.auth`\n\n * if empty/null. User needs to logon\n\n * value found, goto step 2\n\n2. open the session file using the value of `msg.req.cookies.auth`\n\n3. set `msg.session` with the contents of the file\n\n4. Route for further validation based off of type `oauth2` or `token`.\n\nthe existance of path `msg.req.cookies.auth` alludes to a user that has authenticated previously. \nWhilst this value could be guessed, it is highly unlikely.\n" }, { "id": "9f3711f96411e2cc", "type": "group", "z": "8179bf22c4c31682", "g": "7225c45ad941c14f", "name": "Oauth2: Fetch User Token", "style": { "stroke": "#ffC000", "fill": "#dbcbe7", "label": true, "color": "#777777" }, "nodes": [ "8b072412d6eea267", "07ee83c8d9bdbcb2", "a4a3bb52d2eaa071", "9d0d1d9a6c596428", "a49db4bcea29097d", "444cde06405f24e3" ], "x": 1294, "y": 2439, "w": 972, "h": 122 }, { "id": "f5e65e1ae7e8b812", "type": "group", "z": "8179bf22c4c31682", "g": "7225c45ad941c14f", "name": "Oauth2: Session", "style": { "stroke": "#6f2fa0", "fill": "#bfdbef", "label": true, "color": "#777777" }, "nodes": [ "55efe159b8d86e8f", "50e12d2b699abb59", "3254bbe21538dc25", "b371f5e8c32059f3", "e6f37f07e9217707", "68cdc18107b77029", "412814a194fb2e27", "a30dab395f333826", "7873f07f92e9be20", "36c7736ada06ef15", "54e638b390e13c61" ], "x": 1294, "y": 2219, "w": 1532, "h": 202 }, { "id": "5851acefa1f1b5ff", "type": "group", "z": "8179bf22c4c31682", "g": "cc33365c2aa59e35", "name": "Token: Generate", "style": { "stroke": "#0070c0", "fill": "#92d04f", "label": true, "color": "#000000" }, "nodes": [ "f08e22fcc829d7b2", "9bb0664a91ae9b97", "99a20ee6c80595d1", "0107c5fd18462084", "2f7615b7afa603aa", "e350059bd801a5ab", "cb10034e64c15167", "702a6efc7be81391", "1dc714dfeaa9a42d", "a68c08dfd9ce3d8c" ], "x": 1014, "y": 1999, "w": 1302, "h": 122, "info": "# Token Generate\n\nThis sub-group contains the nodes required to generate an authentication token.\n\nThere are two entrypoints for this group:\n\n1. _(Development)_ Click on the generate token to create one for a abritary user\n\n1. `Token: Generate` Link-In node. This is used for other flows which may require a token to be generated for a user. Details must be provided.\n\nThe latter is useful if you create a user with a random password and they need a method to be able to reset it.\n\n## Input Data\n\nthis node requires an object at path `msg.auth.user`.\n\n``` json\n\nmsg.auth.user = {\n \"username\": \"barny.gumble\",\n \"fname\": \"Barny\",\n \"lname\": \"Gumble\",\n \"mail\": \"barney.gumble@dinomail.com\"\n };\n\n```\n\n**NOTE:** _Missing any of the `json` attributes will prevent the user from resetting their password as all of these fields are required._\n" }, { "id": "85fa24886e126df7", "type": "group", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "name": "Ticket Solution", "style": { "stroke": "#6f2fa0", "fill": "#bfdbef", "label": true }, "nodes": [ "40208ed719417cac", "803a8b65fc7a5087", "96766518a046855d", "242b471ad711a4f1", "1305e2f195ec5ede", "285f57c0fee687a1" ], "x": 2234, "y": 1259, "w": 1472, "h": 82 }, { "id": "aa5626527a9df701", "type": "group", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "name": "Ticket Task", "style": { "stroke": "#6f2fa0", "fill": "#bfdbef", "label": true }, "nodes": [ "351440700b3e2ecc", "f17ccfa845461657" ], "x": 2228, "y": 1093, "w": 2204, "h": 134 }, { "id": "351440700b3e2ecc", "type": "group", "z": "8179bf22c4c31682", "g": "aa5626527a9df701", "name": "Create", "style": { "stroke": "#001f60", "fill": "#e3f3d3", "label": true, "color": "#777777" }, "nodes": [ "fb6750555645b873", "e0660324da4581dd" ], "x": 2254, "y": 1119, "w": 492, "h": 82 }, { "id": "f17ccfa845461657", "type": "group", "z": "8179bf22c4c31682", "g": "aa5626527a9df701", "name": "Update", "style": { "stroke": "#001f60", "fill": "#e3f3d3", "label": true, "color": "#777777" }, "nodes": [ "eacbafc05d06b95a", "76cd564b69443419", "ca1b9c48c3c0c522", "d64e9c631ee7ec87", "cafa50da13d9e5d9", "c2f8e99492223cfb", "fdf014eff1962329" ], "x": 2794, "y": 1119, "w": 1612, "h": 82 }, { "id": "cd68bc6f76082c33", "type": "group", "z": "42b9663b67dbd983", "name": "", "style": { "stroke": "#ff0000", "fill": "#ffbfbf", "label": true }, "nodes": [ "db9de7d9adf2c039", "2e8883be19eb130d", "65dc1dee26e42599" ], "x": 694, "y": 139, "w": 492, "h": 82 }, { "id": "5798e39cbc3730ae", "type": "junction", "z": "42b9663b67dbd983", "g": "8ad5fe68ad170e2d", "x": 1240, "y": 960, "wires": [ [ "365ba07c1f4721ec" ] ] }, { "id": "4ab2787bb0227121", "type": "junction", "z": "104f7938a23fe82f", "x": 820, "y": 220, "wires": [ [ "b3adfbc257af34d9" ] ] }, { "id": "f48665a4a0c87ccf", "type": "junction", "z": "104f7938a23fe82f", "x": 2220, "y": 280, "wires": [ [ "e65438fd63bf5834" ] ] }, { "id": "e2fdc9ac8f0f5378", "type": "junction", "z": "104f7938a23fe82f", "x": 1540, "y": 280, "wires": [ [ "f48665a4a0c87ccf" ] ] }, { "id": "b365499ab7271965", "type": "junction", "z": "104f7938a23fe82f", "x": 1900, "y": 180, "wires": [ [ "e6062222b53b3146" ] ] }, { "id": "e6062222b53b3146", "type": "junction", "z": "104f7938a23fe82f", "x": 2140, "y": 180, "wires": [ [ "f48665a4a0c87ccf" ] ] }, { "id": "4c730b98279aaca6", "type": "junction", "z": "104f7938a23fe82f", "x": 420, "y": 220, "wires": [ [ "4ab2787bb0227121", "0097abc4a9b09076" ] ] }, { "id": "a740ac24fa947f73", "type": "junction", "z": "104f7938a23fe82f", "x": 240, "y": 220, "wires": [ [ "ab1b24f61ae7f3bf", "4c730b98279aaca6" ] ] }, { "id": "ce93ad07095d87d3", "type": "junction", "z": "f6f2187d.f17ca8", "x": 1120, "y": 1920, "wires": [ [ "d4dcc73bbe878f42" ] ] }, { "id": "bab95cf5ba3d6045", "type": "junction", "z": "f6f2187d.f17ca8", "x": 820, "y": 1840, "wires": [ [ "d4dcc73bbe878f42", "836dca1c83616f32" ] ] }, { "id": "ce4de75bc712f124", "type": "junction", "z": "f6f2187d.f17ca8", "x": 820, "y": 1900, "wires": [ [ "ebb2a01cac9a803d", "607f24e3f91dff90" ] ] }, { "id": "607f24e3f91dff90", "type": "junction", "z": "f6f2187d.f17ca8", "x": 880, "y": 1920, "wires": [ [ "ce93ad07095d87d3" ] ] }, { "id": "ad563b1612f320ce", "type": "junction", "z": "f6f2187d.f17ca8", "x": 820, "y": 1940, "wires": [ [ "3944fbf533097cbb", "607f24e3f91dff90" ] ] }, { "id": "bf6a0883e2c6fa86", "type": "junction", "z": "f6f2187d.f17ca8", "x": 3520, "y": 700, "wires": [ [ "9b78dc70ba04be52", "7d597c9f95237aec" ] ] }, { "id": "e0b3838ab709561b", "type": "junction", "z": "f6f2187d.f17ca8", "x": 4720, "y": 420, "wires": [ [ "a06872fd8512eb8d", "7cd8e1fefd5dd694" ] ] }, { "id": "7d597c9f95237aec", "type": "junction", "z": "f6f2187d.f17ca8", "x": 3800, "y": 700, "wires": [ [ "7cd8e1fefd5dd694" ] ] }, { "id": "9b78dc70ba04be52", "type": "junction", "z": "f6f2187d.f17ca8", "x": 3800, "y": 740, "wires": [ [ "405728494cdf7f87" ] ] }, { "id": "7cd8e1fefd5dd694", "type": "junction", "z": "f6f2187d.f17ca8", "x": 4780, "y": 700, "wires": [ [ "bcdb9f8a74cd2414" ] ] }, { "id": "596b03adcd307cb4", "type": "junction", "z": "f6f2187d.f17ca8", "x": 4560, "y": 540, "wires": [ [ "7cd8e1fefd5dd694" ] ] }, { "id": "e5548020922347cc", "type": "junction", "z": "f6f2187d.f17ca8", "x": 3300, "y": 2120, "wires": [ [ "7bb0fa06d2b81ebf" ] ] }, { "id": "8fdb88fa979041c2", "type": "junction", "z": "f6f2187d.f17ca8", "x": 180, "y": 1620, "wires": [ [ "e370037f2b9ae9a6", "109cb443e3b18552" ] ] }, { "id": "56d5a39010b82e94", "type": "junction", "z": "f6f2187d.f17ca8", "x": 500, "y": 1420, "wires": [ [ "d5037ce5a29693fc" ] ] }, { "id": "eb6eecd9d940aecb", "type": "junction", "z": "f6f2187d.f17ca8", "x": 80, "y": 1500, "wires": [ [ "8fdb88fa979041c2" ] ] }, { "id": "46dd694a18a599c9", "type": "junction", "z": "f6f2187d.f17ca8", "x": 1040, "y": 1460, "wires": [ [ "eb6eecd9d940aecb" ] ] }, { "id": "facaa6a7395e5d7f", "type": "junction", "z": "f6f2187d.f17ca8", "x": 2600, "y": 2140, "wires": [ [ "f0b8ea2876129114", "4b51a5788a45d420", "f710a0c68b11ee76", "04d760f9b1988f4b", "baa846245c4d19de", "432e2ad61476d045" ] ] }, { "id": "e363219f4309eedb", "type": "junction", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "x": 2160, "y": 1240, "wires": [ [ "803a8b65fc7a5087" ] ] }, { "id": "2545718f1853e084", "type": "junction", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "x": 2160, "y": 1160, "wires": [ [ "fb6750555645b873" ] ] }, { "id": "53b1c5bbed90265f", "type": "junction", "z": "f6f2187d.f17ca8", "x": 820, "y": 1980, "wires": [ [ "0bf3afb49b551d9c", "ab69851f2d76cc5e" ] ] }, { "id": "ab69851f2d76cc5e", "type": "junction", "z": "f6f2187d.f17ca8", "x": 1060, "y": 1980, "wires": [ [ "ce93ad07095d87d3" ] ] }, { "id": "f57f557a25d166b7", "type": "junction", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "x": 4480, "y": 1340, "wires": [ [ "5eda003868c5e354", "e8f257b38aa4d749" ] ] }, { "id": "1840577fd414a84d", "type": "junction", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "x": 2160, "y": 1320, "wires": [ [ "c6c64453fc61e50f" ] ] }, { "id": "c6c64453fc61e50f", "type": "junction", "z": "8179bf22c4c31682", "g": "ed0645c12f7435b2", "x": 2260, "y": 1360, "wires": [ [ "5a961504d7ca5be3" ] ] }, { "id": "f4f56319a112fd86", "type": "junction", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "x": 1980, "y": 800, "wires": [ [ "68f30ef53ebc2074" ] ] }, { "id": "1ee7757ab11df474", "type": "junction", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "x": 1980, "y": 820, "wires": [ [ "12a331c2a036a776", "f2026962fb8dbb44" ] ] }, { "id": "51a40870ef7d7eec", "type": "junction", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "x": 1980, "y": 720, "wires": [ [ "cad86e4a717ecb58" ] ] }, { "id": "38b0e07a7e4cec42", "type": "junction", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "x": 1980, "y": 680, "wires": [ [ "333303604fa4ca01" ] ] }, { "id": "7f4255c2cbe633a5", "type": "junction", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "x": 1980, "y": 640, "wires": [ [ "52395c2abfc3c4f5" ] ] }, { "id": "09cd31dda9fa3c50", "type": "junction", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "x": 1980, "y": 600, "wires": [ [ "515f363d4f52f625" ] ] }, { "id": "195e7631e8660db0", "type": "junction", "z": "379c65a27117b46c", "g": "5706252b01492258", "x": 2800, "y": 680, "wires": [ [ "eaeb9e2bfbe1dc95", "15721605aaae8a86" ] ] }, { "id": "e01b059fbd4cb54f", "type": "junction", "z": "379c65a27117b46c", "g": "5706252b01492258", "x": 2800, "y": 720, "wires": [ [ "1b1ca0bd7037ed0f", "e72f08d8fc433bea" ] ] }, { "id": "dce9621aba915bd4", "type": "junction", "z": "379c65a27117b46c", "g": "5706252b01492258", "x": 2800, "y": 840, "wires": [ [ "28ac8fd21056642c", "d81c931de5a63675" ] ] }, { "id": "adbfd4257ea1c230", "type": "junction", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "x": 380, "y": 440, "wires": [ [ "c6360f6028e1512c" ] ] }, { "id": "966779cca7297dec", "type": "junction", "z": "24deed6b10f37f8f", "g": "f7c0a5bee0e0df33", "x": 2780, "y": 200, "wires": [ [ "0f30a271d9c71f74" ] ] }, { "id": "8d9762cb45d1a09d", "type": "junction", "z": "f6f2187d.f17ca8", "x": 3020, "y": 2040, "wires": [ [ "e5548020922347cc" ] ] }, { "id": "291408859782056d", "type": "junction", "z": "24deed6b10f37f8f", "g": "f7c0a5bee0e0df33", "x": 2280, "y": 200, "wires": [ [ "966779cca7297dec" ] ] }, { "id": "e83ed4274d3959f3", "type": "junction", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "x": 940, "y": 140, "wires": [ [ "de01a4559aecf1c4" ] ] }, { "id": "06b5d27bbf1e5b16", "type": "junction", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "x": 600, "y": 140, "wires": [ [ "957b63c9fc58a139", "fb7fea44905cf7a4" ] ] }, { "id": "e551d77d5412aced", "type": "junction", "z": "42b9663b67dbd983", "g": "a64f4a2c837d5c3c", "x": 1720, "y": 120, "wires": [ [ "4ed718e1ae800bad" ] ] }, { "id": "4ed718e1ae800bad", "type": "junction", "z": "42b9663b67dbd983", "g": "a64f4a2c837d5c3c", "x": 1860, "y": 120, "wires": [ [ "e5ae19af5f6d6561" ] ] }, { "id": "3f5bfeb6ef2a9467", "type": "junction", "z": "8179bf22c4c31682", "g": "69f0d6271fe16536", "x": 1500, "y": 2720, "wires": [ [ "3629b0bb901c20a7", "10120b4cdade08c6" ] ] }, { "id": "a67892bd64d2ded4", "type": "junction", "z": "8179bf22c4c31682", "g": "bbd929c437c592ea", "x": 500, "y": 1620, "wires": [ [ "3fa2f7ecc012d8c6" ] ] }, { "id": "f5365376f49c255d", "type": "junction", "z": "379c65a27117b46c", "g": "5706252b01492258", "x": 2800, "y": 800, "wires": [ [ "31b86caaa955a0ee", "dc075811536fafda" ] ] }, { "id": "160d0b5ed597dc51", "type": "ldap", "host": "ldap://ldap", "port": "389" }, { "id": "1e0841f1.ac68fe", "type": "http in", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "", "url": "*", "method": "get", "upload": false, "swaggerDoc": "", "x": 250, "y": 420, "wires": [ [ "c80657a01a03012d", "adbfd4257ea1c230" ] ] }, { "id": "1b121b9ecdf14084", "type": "switch", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Routing", "property": " $split(req._parsedUrl.pathname, '/', limit)[1]", "propertyType": "jsonata", "rules": [ { "t": "empty" }, { "t": "eq", "v": "details", "vt": "str" }, { "t": "eq", "v": "changepassword", "vt": "str" }, { "t": "eq", "v": "passwordreset", "vt": "str" }, { "t": "eq", "v": "passwordquestions", "vt": "str" }, { "t": "eq", "v": "logout", "vt": "str" }, { "t": "else" } ], "checkall": "false", "repair": false, "outputs": 7, "x": 1740, "y": 700, "wires": [ [ "09cd31dda9fa3c50" ], [ "7f4255c2cbe633a5" ], [ "38b0e07a7e4cec42" ], [ "51a40870ef7d7eec" ], [ "e2876b413d95adf9" ], [ "f4f56319a112fd86" ], [ "1ee7757ab11df474" ] ] }, { "id": "6dc15589d8863139", "type": "debug", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "HTTP / Get", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1750, "y": 620, "wires": [] }, { "id": "eae031f35d9a1e9e", "type": "change", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "", "rules": [ { "t": "set", "p": "client", "pt": "msg", "to": "req.connection.remoteAddress", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1480, "y": 700, "wires": [ [ "6dc15589d8863139", "1b121b9ecdf14084" ] ] }, { "id": "e2876b413d95adf9", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Page: Password Reset Questions", "mode": "link", "links": [ "02c4b9524d361ade", "b202e09db45b339a" ], "x": 2120, "y": 760, "wires": [], "l": true }, { "id": "cad86e4a717ecb58", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Page: Password Reset", "mode": "link", "links": [ "2dc375bf57ad8daa", "86d0cb173ed572b5" ], "x": 2160, "y": 720, "wires": [], "l": true }, { "id": "5de0bbd4.6c8574", "type": "http in", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "", "url": "*", "method": "post", "upload": false, "swaggerDoc": "", "x": 250, "y": 460, "wires": [ [ "482740e98dda9d35", "adbfd4257ea1c230" ] ] }, { "id": "75913f37.78e6e", "type": "json", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "", "property": "payload", "action": "obj", "pretty": false, "x": 1490, "y": 1080, "wires": [ [ "539d65720b0ff630" ] ] }, { "id": "482740e98dda9d35", "type": "debug", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "HTTP / Post", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 450, "y": 500, "wires": [] }, { "id": "3072b7c1fc0fd171", "type": "debug", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "debug 69", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1900, "y": 1140, "wires": [] }, { "id": "539d65720b0ff630", "type": "change", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "", "rules": [ { "t": "set", "p": "http", "pt": "msg", "to": "{}", "tot": "jsonata" }, { "t": "set", "p": "http.client", "pt": "msg", "to": "req.connection.remoteAddress", "tot": "msg" }, { "t": "move", "p": "payload", "pt": "msg", "to": "http.form", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1640, "y": 1080, "wires": [ [ "0eb8679ee25c4a34", "3072b7c1fc0fd171" ] ] }, { "id": "0eb8679ee25c4a34", "type": "switch", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "Routing", "property": " $split(req._parsedUrl.pathname, '/')[1]", "propertyType": "jsonata", "rules": [ { "t": "eq", "v": "passwordreset", "vt": "str" }, { "t": "eq", "v": "passwordquestions", "vt": "str" }, { "t": "eq", "v": "passwordchange", "vt": "str" }, { "t": "eq", "v": "updatedetails", "vt": "str" }, { "t": "else" } ], "checkall": "false", "repair": false, "outputs": 5, "x": 1900, "y": 1100, "wires": [ [ "b7fde07e47cc852e", "2189bf4e56868e51" ], [ "9c92aaf02fee52b5" ], [ "64c99b312f9c601c" ], [], [] ] }, { "id": "b7fde07e47cc852e", "type": "link out", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "Password Reset", "mode": "link", "links": [ "cdde8116fcac6e5d" ], "x": 2100, "y": 1060, "wires": [], "l": true }, { "id": "9c92aaf02fee52b5", "type": "link out", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "Password Reset Questions", "mode": "link", "links": [ "bb8102ee0c070ff2" ], "x": 2140, "y": 1100, "wires": [], "l": true }, { "id": "7db929503cf13635", "type": "link in", "z": "379c65a27117b46c", "g": "755ff25cc29a08a1", "name": "HTTP: Response", "links": [ "0c2e73371d4238a1", "1d661b2385de4b4a", "4ecc0631139b51e0", "50339f503fd4878d", "96836f5a4c7c756c", "988765ea19236af0", "b664f0b9e6c17ad6", "bf098463143ac8ad", "e5ae19af5f6d6561", "f1dcd5b6e32fb905", "4cdbeaa8f5f3ddb7", "b54c063d6519c463", "a6c8721721fc267e", "960bf96fa54c65c0" ], "x": 2600, "y": 1160, "wires": [ [ "3af3d2ae3286ffe0" ] ], "l": true }, { "id": "e3043367c9a89a90", "type": "http response", "z": "379c65a27117b46c", "g": "755ff25cc29a08a1", "name": "HTTP Response", "statusCode": "", "headers": {}, "x": 2940, "y": 1160, "wires": [] }, { "id": "564400f9ec708521", "type": "debug", "z": "379c65a27117b46c", "g": "755ff25cc29a08a1", "name": "HTTP / Response", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2930, "y": 1120, "wires": [] }, { "id": "9f59194fecc0976a", "type": "switch", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "File Name", "property": "$split(req.url, '/', limit)[$count($split(req.url, '/', limit)) + 1]\t\t", "propertyType": "jsonata", "rules": [ { "t": "eq", "v": "style.css", "vt": "str" }, { "t": "eq", "v": "common.js", "vt": "str" }, { "t": "eq", "v": "jquery.min.js", "vt": "str" }, { "t": "else" } ], "checkall": "false", "repair": false, "outputs": 4, "x": 2650, "y": 740, "wires": [ [ "195e7631e8660db0" ], [ "e01b059fbd4cb54f" ], [ "f5365376f49c255d" ], [ "dce9621aba915bd4" ] ] }, { "id": "eaeb9e2bfbe1dc95", "type": "link out", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "style.css", "mode": "link", "links": [ "3502d9cf69680b66" ], "x": 2960, "y": 640, "wires": [], "l": true }, { "id": "d81c931de5a63675", "type": "link out", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "HTTP/404", "mode": "link", "links": [ "4d40709eea926ab1" ], "x": 2970, "y": 900, "wires": [], "l": true }, { "id": "15721605aaae8a86", "type": "debug", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "CSS File", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2960, "y": 600, "wires": [] }, { "id": "28ac8fd21056642c", "type": "debug", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "HTTP / 404", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2970, "y": 940, "wires": [] }, { "id": "12a331c2a036a776", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Fetch Files", "mode": "link", "links": [ "acd5690f3865f156" ], "x": 2190, "y": 860, "wires": [], "l": true }, { "id": "acd5690f3865f156", "type": "link in", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "Fetch File", "links": [ "12a331c2a036a776" ], "x": 2460, "y": 860, "wires": [ [ "9f59194fecc0976a" ] ], "l": true }, { "id": "e72f08d8fc433bea", "type": "link out", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "common.js", "mode": "link", "links": [ "2e8883be19eb130d" ], "x": 2970, "y": 740, "wires": [], "l": true }, { "id": "1b1ca0bd7037ed0f", "type": "debug", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "JS File", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2950, "y": 700, "wires": [] }, { "id": "515f363d4f52f625", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Home", "mode": "link", "links": [ "0172c4a240b566fd", "d810b86dc7c722cd" ], "x": 2210, "y": 600, "wires": [], "l": true }, { "id": "333303604fa4ca01", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Page: Change Password", "mode": "link", "links": [ "b5cedc58894f707e", "2ccbf2d475489da8" ], "x": 2150, "y": 680, "wires": [], "l": true }, { "id": "52395c2abfc3c4f5", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Page: Account Details", "mode": "link", "links": [ "e50f46892eabd2a5", "a28d15c7a8dfdc85" ], "x": 2160, "y": 640, "wires": [], "l": true }, { "id": "68f30ef53ebc2074", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Page: Logout", "mode": "link", "links": [ "fb5301abffede979" ], "x": 2190, "y": 800, "wires": [], "l": true }, { "id": "2189bf4e56868e51", "type": "debug", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "debug 95", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2080, "y": 1020, "wires": [] }, { "id": "f2026962fb8dbb44", "type": "debug", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "debug 99", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2180, "y": 900, "wires": [] }, { "id": "ce290d371c7687b0", "type": "debug", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Not-Authorized", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1760, "y": 780, "wires": [] }, { "id": "c7ca92d48206b4b2", "type": "inject", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "Auto Read Config", "props": [ { "p": "filename", "v": "/usr/src/node-red/config.json", "vt": "str" } ], "repeat": "300", "crontab": "", "once": true, "onceDelay": "2", "topic": "", "x": 290, "y": 100, "wires": [ [ "2d4bed7c63632c6c" ] ] }, { "id": "de01a4559aecf1c4", "type": "debug", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "Config read", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1070, "y": 200, "wires": [] }, { "id": "842ade29052f7e66", "type": "change", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "global.config.glpi", "rules": [ { "t": "set", "p": "CurrentGlobalConfig", "pt": "msg", "to": "config", "tot": "global" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 850, "y": 200, "wires": [ [ "de01a4559aecf1c4" ] ] }, { "id": "64c99b312f9c601c", "type": "link out", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "Password: Change", "mode": "link", "links": [ "1df8ab6bb55ff621", "a36e4f9e4921b12a" ], "x": 2110, "y": 1140, "wires": [], "l": true }, { "id": "3ada862ebc07a99d", "type": "function", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Valid Path?", "func": "var validPath = null;\nvar http_404 = null;\n\nif ( String(msg.req.originalUrl).indexOf('?') > 0 ) {\n\n msg.http.path = String(msg.req.originalUrl).split('?')[0].split('/');\n\n}else{\n msg.http.path = String(msg.req.originalUrl).split('/');\n\n}\n\nif (\n msg.http.path[0] == global.get('config.http_path') ||\n msg.http.path[0] + '/' == global.get('config.http_path')\n) {\n\n validPath = msg;\n\n\n} else if (String(msg.req.originalUrl).indexOf('.') > 0 ) {\n\n validPath = msg;\n \n} else {\n\n http_404 = msg;\n\n}\n\nnode.send([validPath, http_404])\n", "outputs": 2, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1270, "y": 720, "wires": [ [ "eae031f35d9a1e9e" ], [ "4716d2916d6de31e", "6e74b4a9a6b2dac8" ] ], "outputLabels": [ "SelfService", "HTTP/404" ] }, { "id": "4716d2916d6de31e", "type": "link out", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "HTTP/404", "mode": "link", "links": [ "4d40709eea926ab1" ], "x": 1470, "y": 740, "wires": [], "l": true }, { "id": "6e74b4a9a6b2dac8", "type": "debug", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "HTTP / 404", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1470, "y": 780, "wires": [] }, { "id": "c80657a01a03012d", "type": "debug", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "HTTP / Get", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 450, "y": 380, "wires": [] }, { "id": "7c38c172df490c56", "type": "function", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "Valid Path?", "func": "var validPath = null;\nvar http_404 = null;\n\nif (String(msg.req.originalUrl).indexOf('?') > 0) {\n\n msg.http.path = String(msg.req.originalUrl).split('?')[0].split('/');\n\n} else {\n msg.http.path = String(msg.req.originalUrl).split('/');\n\n}\n\nif (\n msg.http.path[0] == global.get('config.http_path') ||\n msg.http.path[0] + '/' == global.get('config.http_path')\n) {\n\n validPath = msg;\n\n\n} else if (String(msg.req.originalUrl).indexOf('.') > 0) {\n\n validPath = msg;\n\n} else {\n\n http_404 = msg;\n\n}\n\nnode.send([validPath, http_404])\n", "outputs": 2, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1310, "y": 1100, "wires": [ [ "75913f37.78e6e" ], [ "c0e5efefb8395690", "7b62ec12651e478a" ] ], "outputLabels": [ "SelfService", "HTTP/404" ] }, { "id": "c0e5efefb8395690", "type": "link out", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "HTTP/404", "mode": "link", "links": [ "4d40709eea926ab1" ], "x": 1510, "y": 1120, "wires": [], "l": true }, { "id": "7b62ec12651e478a", "type": "debug", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "HTTP / 404", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 1510, "y": 1160, "wires": [] }, { "id": "1c16492a7fe8e77b", "type": "link out", "z": "379c65a27117b46c", "g": "923268ee62c6a7db", "name": "HTTP/GET", "mode": "link", "links": [ "5c05dcd676fcb02a" ], "x": 1810, "y": 380, "wires": [], "icon": "font-awesome/fa-unlock", "l": true }, { "id": "5c05dcd676fcb02a", "type": "link in", "z": "379c65a27117b46c", "g": "ec8733df4e619869", "name": "Process: HTTP/GET", "links": [ "1c16492a7fe8e77b" ], "x": 1110, "y": 720, "wires": [ [ "3ada862ebc07a99d" ] ], "icon": "font-awesome/fa-unlock", "l": true }, { "id": "e282aea37a90acdc", "type": "link out", "z": "379c65a27117b46c", "g": "923268ee62c6a7db", "name": "HTTP/POST", "mode": "link", "links": [ "9cbf4027b4ab1c04" ], "x": 1810, "y": 420, "wires": [], "icon": "font-awesome/fa-unlock", "l": true }, { "id": "9cbf4027b4ab1c04", "type": "link in", "z": "379c65a27117b46c", "g": "8363d385051fc5c0", "name": "Process: HTTP/POST", "links": [ "e282aea37a90acdc" ], "x": 1120, "y": 1100, "wires": [ [ "7c38c172df490c56" ] ], "icon": "font-awesome/fa-unlock", "l": true }, { "id": "d17512b4de05ede1", "type": "link out", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "HTTP/401", "mode": "link", "links": [ "fd80fd11fc971e2c" ], "x": 770, "y": 740, "wires": [], "icon": "font-awesome/fa-lock", "l": true }, { "id": "434d74f494db7cfc", "type": "link out", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "HTTP/404", "mode": "link", "links": [ "fd80fd11fc971e2c" ], "x": 770, "y": 780, "wires": [], "icon": "font-awesome/fa-question", "l": true }, { "id": "6728a85f5b044738", "type": "link call", "z": "379c65a27117b46c", "g": "923268ee62c6a7db", "name": "Authentication", "links": [ "f17afdbfc8c07889" ], "linkType": "static", "timeout": "30", "x": 1310, "y": 420, "wires": [ [ "46d8b11bdef459aa" ] ], "icon": "font-awesome/fa-lock" }, { "id": "46d8b11bdef459aa", "type": "function", "z": "379c65a27117b46c", "g": "923268ee62c6a7db", "name": "HTTP Method Routing", "func": "var http_get = null;\nvar http_post = null;\nvar statuscode = null;\n\nvar status = { fill: \"red\", shape: \"ring\", text: \"Incomplete\" };\n\nif (msg.hasOwnProperty('statusCode') ) {\n\n status.fill = \"yellow\";\n status.text = \"HTTP/\"+ msg.statusCode;\n\n statuscode = msg;\n\n \n} else {\n\n if (msg.hasOwnProperty('session')) {\n\n switch (String(msg.req.method).toLocaleLowerCase()) {\n\n case 'get':\n status.fill = \"green\";\n status.text = \"GET\";\n\n http_get = msg;\n break;\n\n case 'post':\n status.fill = \"green\";\n status.text = \"POST\";\n\n http_post = msg;\n break;\n\n default:\n status.fill = \"yellow\";\n status.text = \"unsupported\";\n\n msg.statusCode = 400;\n statuscode = msg;\n break;\n\n };\n\n } else { // no msg.session, force logon\n status.fill = \"yellow\";\n status.text = \"Not Authorized\";\n\n\n if (!msg.hasOwnProperty('statusCode')) {\n msg.statusCode = 401;\n // ToDo: add location header to auth method\n }\n\n statuscode = msg;\n\n }\n}\n\nnode.status(status);\n\nnode.send([\n http_get,\n http_post,\n statuscode\n]);\n", "outputs": 3, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1540, "y": 420, "wires": [ [ "1c16492a7fe8e77b" ], [ "e282aea37a90acdc" ], [ "5f2f87eeebd5bf6e" ] ], "outputLabels": [ "Get", "Post", "Non HTTP/20x" ], "icon": "node-red/arrow-in.svg" }, { "id": "2f1060b185e19215", "type": "link in", "z": "379c65a27117b46c", "g": "923268ee62c6a7db", "name": "Process: Authorized", "links": [ "28713941e03e2bf5", "2ed31116a1e83c99" ], "x": 1110, "y": 420, "wires": [ [ "6728a85f5b044738" ] ], "icon": "font-awesome/fa-lock", "l": true }, { "id": "0ec392291c3fda2f", "type": "link out", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "HTTP/400", "mode": "link", "links": [ "fd80fd11fc971e2c" ], "x": 770, "y": 700, "wires": [], "icon": "font-awesome/fa-exclamation-triangle", "l": true }, { "id": "5f2f87eeebd5bf6e", "type": "link out", "z": "379c65a27117b46c", "g": "923268ee62c6a7db", "name": "Non HTTP/20x", "mode": "link", "links": [ "5ad10ea406e2d3a7" ], "x": 1820, "y": 460, "wires": [], "icon": "font-awesome/fa-warning", "l": true }, { "id": "28713941e03e2bf5", "type": "link out", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "Authorized?", "mode": "link", "links": [ "2f1060b185e19215" ], "x": 650, "y": 380, "wires": [], "icon": "font-awesome/fa-lock", "l": true }, { "id": "3af3d2ae3286ffe0", "type": "change", "z": "379c65a27117b46c", "g": "755ff25cc29a08a1", "name": "", "rules": [ { "t": "delete", "p": "_event", "pt": "msg" }, { "t": "set", "p": "http.response_size", "pt": "msg", "to": "$length(msg.payload)\t", "tot": "jsonata" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 2760, "y": 1160, "wires": [ [ "e3043367c9a89a90", "564400f9ec708521" ] ] }, { "id": "c6360f6028e1512c", "type": "function", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "Details", "func": "var cont = null;\nvar callback = null;\nvar not_configured = null;\nvar http_404 = null\nvar status = {fill:\"red\",shape:\"ring\",text:\"Err: Incomplete\"};\n\nif( msg.req._parsedUrl.path == '/favicon.ico' ) {\n \n status.text = 'HTTP/404';\n status.fill = 'grey';\n\n msg.statusCode = 404;\n msg.payload = {};\n\n http_404 = msg;\n\n} else if (\n global.get(\"config\") == undefined ||\n (\n global.get(\"config\") != undefined &&\n global.get(\"config.auth_method\") == undefined\n )\n) {\n\n status.text = 'No Config';\n\n msg.statusCode = 400;\n\n not_configured = msg;\n\n} else {\n\n if ( \n Array(global.get(\"config.auth_method\")).includes('oauth2') &&\n global.get(\"config.oauth2\") == undefined\n ) {\n\n status.text = 'No OAuth2 Config';\n\n msg.statusCode = 400;\n\n not_configured = msg;\n\n }else{\n\n msg.http = {\n \"client\": msg.req.connection.remoteAddress,\n \"headers\": msg.req.headers,\n \"timestamp\": Date.now()\n }\n\n if (msg.req.params[\"0\"] == 'callback' ){\n\n status.fill = 'blue';\n status.text = 'Oauth2 Callback';\n\n callback = msg;\n\n }else{\n\n status.fill = 'green';\n status.text = 'Continue';\n\n cont = msg;\n\n }\n }\n}\nnode.status( status );\n\nnode.send([\n cont,\n callback,\n not_configured,\n http_404\n]);\n", "outputs": 4, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 470, "y": 440, "wires": [ [ "28713941e03e2bf5" ], [ "b174f7bc1d398a56" ], [ "3dc07bb0a7d4f647" ], [ "c58cfa3fc57972d1" ] ], "outputLabels": [ "Continue", "Oauth2 Callback", "Server Not Configured", "HTTP/404" ], "icon": "font-awesome/fa-info-circle", "info": "# Details\n\nAdds the HTTP request details to object `msg.http`. Also checks for favicon.ico and returns HTTP/404." }, { "id": "c43678f82d52004f", "type": "link out", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "HTTP/302", "mode": "link", "links": [ "fd80fd11fc971e2c" ], "x": 770, "y": 620, "wires": [], "icon": "font-awesome/fa-refresh", "l": true }, { "id": "43603c3760e7ae56", "type": "link out", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "HTTP/303", "mode": "link", "links": [ "fd80fd11fc971e2c" ], "x": 770, "y": 660, "wires": [], "icon": "font-awesome/fa-refresh", "l": true }, { "id": "5ad10ea406e2d3a7", "type": "link in", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "HTTP/StatusCode", "links": [ "5f2f87eeebd5bf6e", "5b97592fe62125c7", "3dc07bb0a7d4f647", "c58cfa3fc57972d1" ], "x": 290, "y": 640, "wires": [ [ "c058f11dfd8d01b2" ] ], "icon": "node-red/arrow-in.svg", "l": true }, { "id": "c058f11dfd8d01b2", "type": "switch", "z": "379c65a27117b46c", "g": "f3aa07300888f0a4", "name": "Route", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "302", "vt": "num" }, { "t": "eq", "v": "303", "vt": "num" }, { "t": "eq", "v": "400", "vt": "num" }, { "t": "eq", "v": "401", "vt": "num" }, { "t": "eq", "v": "404", "vt": "num" } ], "checkall": "true", "repair": false, "outputs": 5, "x": 490, "y": 640, "wires": [ [ "c43678f82d52004f" ], [ "43603c3760e7ae56" ], [ "0ec392291c3fda2f" ], [ "d17512b4de05ede1" ], [ "434d74f494db7cfc" ] ] }, { "id": "b174f7bc1d398a56", "type": "link out", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "Oauth2 call", "mode": "link", "links": [ "9f416bc258c1a60c" ], "x": 650, "y": 420, "wires": [], "icon": "font-awesome/fa-lock", "l": true }, { "id": "f57a5bd56ce68760", "type": "inject", "z": "379c65a27117b46c", "name": "Trigger: Oauth2 Config", "props": [ { "p": "payload" } ], "repeat": "300", "crontab": "", "once": true, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 3630, "y": 140, "wires": [ [] ] }, { "id": "957b63c9fc58a139", "type": "credentials", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "Oauth2", "props": [ { "value": "config.oauth.client_secret", "type": "global" }, { "value": "config.oauth.client_id", "type": "global" }, { "value": "config.oauth.url.token", "type": "global" }, { "value": "config.oauth.url.auth", "type": "global" }, { "value": "config.oauth.url.callback", "type": "global" } ], "x": 700, "y": 140, "wires": [ [ "02812e8708980b09" ] ], "info": "# Oauth2 Configuration\n\nThis node stores it's values within `flows_cred.json` and therefor takes advantage of encrypting the values.\n\n## Structure\n\n``` json\n\n{\n \"client_secret\": \"\",\n \"client_id\": \"\",\n \"url\": {\n \"token\": \"\",\n \"auth\": \"\",\n \"callback\": \"http://127.0.0.1:1881/callback\"\n }\n}\n\n```\n\n| item | type | description |\n|:---:|:---:|:---|\n| client_secret | `string` | client secret |\n| client_id | `string` | client id |\n| url.token | `string` | Token URL |\n| url.auth | `string` | Auth URL |\n| url.callback | `string` | Authentication Callback URL, this value must always be `{protocol}://{domain}/callback`. i.e. `http://127.0.0.1:1881/callback` |\n " }, { "id": "02812e8708980b09", "type": "change", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "global.config", "rules": [ { "t": "set", "p": "CurrentGlobalConfig", "pt": "msg", "to": "config", "tot": "global" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 830, "y": 140, "wires": [ [ "e83ed4274d3959f3" ] ] }, { "id": "3dc07bb0a7d4f647", "type": "link out", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "No Config", "mode": "link", "links": [ "5ad10ea406e2d3a7" ], "x": 640, "y": 460, "wires": [], "icon": "font-awesome/fa-hand-stop-o", "l": true }, { "id": "fb7fea44905cf7a4", "type": "credentials", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "GLPI", "props": [ { "value": "config.glpi.api_url", "type": "global" }, { "value": "config.glpi.authorization", "type": "global" }, { "value": "config.glpi.app_token", "type": "global" }, { "value": "config.glpi.category_id_automation_task", "type": "global" }, { "value": "config.glpi.debug_on", "type": "global" } ], "x": 710, "y": 200, "wires": [ [ "842ade29052f7e66" ] ], "info": "# GLPI Configuration\n\nThis node stores it's values within `flows_cred.json` and therefor takes advantage of encrypting the values.\n\n## Structure\n\n``` json\n\n{\n \"api_url\": \"http://glpi/apirest.php/\",\n \"authorization\": \"user_token ***\",\n \"app_token\": \"\",\n \"category_id_automation_task\": 0,\n \"debug_on\": false\n}\n\n```\n\n| item | type | description |\n|:---:|:---:|:---|\n| api_url | `string` | URL for the API `{protocol}://{domain}/apirest.php/` |\n| authorization | `string` | Auth token suffixed with `user_token` |\n| app_token | `string` | Application token |\n| category_id_automation_task | `int` | the category for this automation task to be applied to the ticket task |\n| debug_on | `bool` | Authentication Callback URL, this value must always be `{protocol}://{domain}/callback`. i.e. `http://127.0.0.1:1881/callback` |\n " }, { "id": "c58cfa3fc57972d1", "type": "link out", "z": "379c65a27117b46c", "g": "cf2a3f84cb26a12c", "name": "HTTP/404", "mode": "link", "links": [ "5ad10ea406e2d3a7" ], "x": 650, "y": 500, "wires": [], "icon": "font-awesome/fa-hand-stop-o", "l": true }, { "id": "2d4bed7c63632c6c", "type": "template", "z": "379c65a27117b46c", "g": "b994fe21efb223a9", "name": "General Config", "field": "config", "fieldType": "global", "format": "json", "syntax": "mustache", "template": "{\n \"auth_method\": [ \"oauth\", \"token\" ],\n \"developer_mode\": false,\n \"html\": {\n \"logo\": \"http://nofusscomputing.com/assets/nfc_revamp_dark.png\",\n \"logo_width\": 282,\n \"logo_height\": 90\n },\n \"http_path\": \"/\",\n \"itsm\": {\n \"api_url\": \"http://glpi/apirest.php/\",\n \"create_ticket\": true,\n \"create_ticket_task\": true,\n \"platform\": \"glpi\",\n \"search\": true,\n \"human_task_duration_time\": 300,\n \"ticket\": {\n \"approval_required\": 0,\n \"category_id\": 6,\n \"entity_id\": 1,\n \"requesttype_id\": 6,\n \"task_category_id\": 2\n }\n },\n \"paths\": {\n \"user_data\": \"data/users/\",\n \"token_sessions\": \"data/sessions/\"\n }\n}\n", "output": "json", "x": 480, "y": 100, "wires": [ [ "06b5d27bbf1e5b16" ] ] }, { "id": "31b86caaa955a0ee", "type": "debug", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "JS File", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2950, "y": 780, "wires": [] }, { "id": "dc075811536fafda", "type": "link out", "z": "379c65a27117b46c", "g": "5706252b01492258", "name": "jquery.min.js", "mode": "link", "links": [ "602e7197835bba91" ], "x": 2970, "y": 820, "wires": [], "l": true }, { "id": "02c4b9524d361ade", "type": "link in", "z": "42b9663b67dbd983", "g": "8ad5fe68ad170e2d", "name": "HTML: Password Reset Questions", "links": [ "e2876b413d95adf9", "28c74c7b39a06100" ], "x": 320, "y": 980, "wires": [ [ "7e95892f2f3454b7" ] ], "icon": "node-red/file.svg", "l": true }, { "id": "365ba07c1f4721ec", "type": "template", "z": "42b9663b67dbd983", "g": "8ad5fe68ad170e2d", "name": "HTML", "field": "html.body", "fieldType": "msg", "format": "html", "syntax": "mustache", "template": "
\n

Password reset Questions

\n\n
\n

For ensuring that only you can reset your password, you are required to provide three questions and answers. These questions will then as part of the self-service password reset process to confirm that it's you who is requesting the password reset.

\n

When choosing your questions, it's important to ensure that the questions that you use, only you would know the answers. This is to ensure that no one could guess the answers as only you would know the answers.

\n

In the fields below type out your question and answer, don't include punctuation or the use of any special characters. Valid characters are A-Z, a-z and 0-9. Any character entered into the form that are not part of this list will be removed.

\n
\n \n \n \n \n
\n\n
\n \n \n \n \n
\n\n
\n \n \n \n \n
\n\n

On Form submission, your answers will be hashed before storage. As such, no one will be able to view the answers, this includes you. This method however, still enables us to confirm an answer to a question as would occur during the password reset process.

\n\n \n
\n \n
\n\n
\n Results\n \n
\n
\n \n
\n", "output": "str", "x": 1670, "y": 960, "wires": [ [ "591e68e90f876dd1" ] ] }, { "id": "50339f503fd4878d", "type": "link out", "z": "42b9663b67dbd983", "g": "8ad5fe68ad170e2d", "name": "HTML Response", "mode": "link", "links": [ "7db929503cf13635" ], "x": 1950, "y": 960, "wires": [], "l": true }, { "id": "2dc375bf57ad8daa", "type": "link in", "z": "42b9663b67dbd983", "g": "ad0235dd3aa9eb7d", "name": "HTML: Password Reset", "links": [ "cad86e4a717ecb58" ], "x": 280, "y": 820, "wires": [ [ "317930c679e833d1" ] ], "icon": "node-red/file.svg", "l": true }, { "id": "1ce803b83ecf1593", "type": "change", "z": "42b9663b67dbd983", "g": "ad0235dd3aa9eb7d", "name": "", "rules": [ { "t": "move", "p": "payload", "pt": "msg", "to": "random", "tot": "msg" }, { "t": "set", "p": "client", "pt": "msg", "to": "req.connection.remoteAddress", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 720, "y": 820, "wires": [ [ "f3b55ea2.f4d51" ] ] }, { "id": "f3b55ea2.f4d51", "type": "template", "z": "42b9663b67dbd983", "g": "ad0235dd3aa9eb7d", "name": "HTML", "field": "html.body", "fieldType": "msg", "format": "handlebars", "syntax": "mustache", "template": "
\n

Self-Service Password Reset

\n\n
\n

To reset your password, ALL fields are Mandatory. On completing this form click 'submit' below. Results will be posted in the results window underneath the submit button.

\n \n \n\n \n \n\n \n \n\n \n \n\n

This is the first half of your password

\n \n\n \n
\n \n
\n\n
\n Results\n \n
\n
\n \n
\n", "x": 850, "y": 820, "wires": [ [ "457583335831f826" ] ] }, { "id": "bf098463143ac8ad", "type": "link out", "z": "42b9663b67dbd983", "g": "ad0235dd3aa9eb7d", "name": "HTML Response", "mode": "link", "links": [ "7db929503cf13635" ], "x": 1130, "y": 820, "wires": [], "l": true }, { "id": "a702d39f0f3180de", "type": "template", "z": "42b9663b67dbd983", "g": "d3393ec35cb20a93", "name": "CSS", "field": "payload", "fieldType": "msg", "format": "css", "syntax": "mustache", "template": "body {\n text-align: center;\n}\n\nfieldset {\n border-radius: 5px;\n /* background-color: #f2f2f2; */\n border-color: #ffffff;\n border-style: groove;\n /* padding: 20px; */\n}\n\nbody fieldset[id=form] {\n margin: 0 auto;\n background-color: #f2f2f2;\n}\n\nform {\n text-align: left;\n padding: 0px;\n}\n\nh2 {\n font-size: 20px;\n text-align: center;\n margin: 0;\n padding: 0;\n}\n\nform p {\n text-align: justify;\n margin: 0;\n padding: 10px;\n}\n\ninput[type=text], input[type=password], select {\n width: 100%;\n padding: 12px 20px;\n margin: 8px 0 20px 0;\n display: inline-block;\n border: 1px solid #ccc;\n border-radius: 4px;\n box-sizing: border-box;\n}\n\ninput[type=submit], button[id=navigation] {\n width: 100%;\n background-color: #4CAF50;\n color: white;\n padding: 14px 20px;\n margin: 8px 0;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n}\n\ninput[type=submit]:hover, button[id=navigation]:hover {\n background-color: #45a049;\n}\n\ninput[type=submit]:disabled {\n background-color: #455da0;\n pointer-events: none;\n}\n\nbody fieldset[id=response] {\n height: auto;\n min-height: 25px;\n width: 400px;\n margin: 0 auto;\n background-color: rgb(247, 240, 228);\n \n}\n\nlabel {\n font-size: 12pt;\n font-style: normal;\n font-weight: bold;\n color: #000000;\n text-align: left;\n}\n\n\n#labelDescription {\n color: #414141;\n\n}\n\ndiv[id=question_multicolumn] {\n margin: 0;\n padding: 0px;\n display: grid;\n grid-template-columns: 600px 200px;\n grid-template-rows: 25px;\n}", "x": 410, "y": 180, "wires": [ [ "f1dcd5b6e32fb905" ] ] }, { "id": "3502d9cf69680b66", "type": "link in", "z": "42b9663b67dbd983", "g": "d3393ec35cb20a93", "name": "style.css", "links": [ "eaeb9e2bfbe1dc95" ], "x": 250, "y": 180, "wires": [ [ "a702d39f0f3180de" ] ], "l": true }, { "id": "f1dcd5b6e32fb905", "type": "link out", "z": "42b9663b67dbd983", "g": "d3393ec35cb20a93", "name": "Return", "mode": "link", "links": [ "7db929503cf13635" ], "x": 550, "y": 180, "wires": [], "l": true }, { "id": "c8c3f9c8f2ee35ee", "type": "template", "z": "42b9663b67dbd983", "g": "3e330505ea1e9cba", "name": "JavaScript", "field": "payload", "fieldType": "msg", "format": "javascript", "syntax": "plain", "template": "/*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */\n!function (a, b) { \"object\" == typeof module && \"object\" == typeof module.exports ? module.exports = a.document ? b(a, !0) : function (a) { if (!a.document) throw new Error(\"jQuery requires a window with a document\"); return b(a) } : b(a) }(\"undefined\" != typeof window ? window : this, function (a, b) {\n var c = [], d = c.slice, e = c.concat, f = c.push, g = c.indexOf, h = {}, i = h.toString, j = h.hasOwnProperty, k = \"\".trim, l = {}, m = a.document, n = \"2.1.0\", o = function (a, b) { return new o.fn.init(a, b) }, p = /^-ms-/, q = /-([\\da-z])/gi, r = function (a, b) { return b.toUpperCase() }; o.fn = o.prototype = { jquery: n, constructor: o, selector: \"\", length: 0, toArray: function () { return d.call(this) }, get: function (a) { return null != a ? 0 > a ? this[a + this.length] : this[a] : d.call(this) }, pushStack: function (a) { var b = o.merge(this.constructor(), a); return b.prevObject = this, b.context = this.context, b }, each: function (a, b) { return o.each(this, a, b) }, map: function (a) { return this.pushStack(o.map(this, function (b, c) { return a.call(b, c, b) })) }, slice: function () { return this.pushStack(d.apply(this, arguments)) }, first: function () { return this.eq(0) }, last: function () { return this.eq(-1) }, eq: function (a) { var b = this.length, c = +a + (0 > a ? b : 0); return this.pushStack(c >= 0 && b > c ? [this[c]] : []) }, end: function () { return this.prevObject || this.constructor(null) }, push: f, sort: c.sort, splice: c.splice }, o.extend = o.fn.extend = function () { var a, b, c, d, e, f, g = arguments[0] || {}, h = 1, i = arguments.length, j = !1; for (\"boolean\" == typeof g && (j = g, g = arguments[h] || {}, h++), \"object\" == typeof g || o.isFunction(g) || (g = {}), h === i && (g = this, h--); i > h; h++)if (null != (a = arguments[h])) for (b in a) c = g[b], d = a[b], g !== d && (j && d && (o.isPlainObject(d) || (e = o.isArray(d))) ? (e ? (e = !1, f = c && o.isArray(c) ? c : []) : f = c && o.isPlainObject(c) ? c : {}, g[b] = o.extend(j, f, d)) : void 0 !== d && (g[b] = d)); return g }, o.extend({ expando: \"jQuery\" + (n + Math.random()).replace(/\\D/g, \"\"), isReady: !0, error: function (a) { throw new Error(a) }, noop: function () { }, isFunction: function (a) { return \"function\" === o.type(a) }, isArray: Array.isArray, isWindow: function (a) { return null != a && a === a.window }, isNumeric: function (a) { return a - parseFloat(a) >= 0 }, isPlainObject: function (a) { if (\"object\" !== o.type(a) || a.nodeType || o.isWindow(a)) return !1; try { if (a.constructor && !j.call(a.constructor.prototype, \"isPrototypeOf\")) return !1 } catch (b) { return !1 } return !0 }, isEmptyObject: function (a) { var b; for (b in a) return !1; return !0 }, type: function (a) { return null == a ? a + \"\" : \"object\" == typeof a || \"function\" == typeof a ? h[i.call(a)] || \"object\" : typeof a }, globalEval: function (a) { var b, c = eval; a = o.trim(a), a && (1 === a.indexOf(\"use strict\") ? (b = m.createElement(\"script\"), b.text = a, m.head.appendChild(b).parentNode.removeChild(b)) : c(a)) }, camelCase: function (a) { return a.replace(p, \"ms-\").replace(q, r) }, nodeName: function (a, b) { return a.nodeName && a.nodeName.toLowerCase() === b.toLowerCase() }, each: function (a, b, c) { var d, e = 0, f = a.length, g = s(a); if (c) { if (g) { for (; f > e; e++)if (d = b.apply(a[e], c), d === !1) break } else for (e in a) if (d = b.apply(a[e], c), d === !1) break } else if (g) { for (; f > e; e++)if (d = b.call(a[e], e, a[e]), d === !1) break } else for (e in a) if (d = b.call(a[e], e, a[e]), d === !1) break; return a }, trim: function (a) { return null == a ? \"\" : k.call(a) }, makeArray: function (a, b) { var c = b || []; return null != a && (s(Object(a)) ? o.merge(c, \"string\" == typeof a ? [a] : a) : f.call(c, a)), c }, inArray: function (a, b, c) { return null == b ? -1 : g.call(b, a, c) }, merge: function (a, b) { for (var c = +b.length, d = 0, e = a.length; c > d; d++)a[e++] = b[d]; return a.length = e, a }, grep: function (a, b, c) { for (var d, e = [], f = 0, g = a.length, h = !c; g > f; f++)d = !b(a[f], f), d !== h && e.push(a[f]); return e }, map: function (a, b, c) { var d, f = 0, g = a.length, h = s(a), i = []; if (h) for (; g > f; f++)d = b(a[f], f, c), null != d && i.push(d); else for (f in a) d = b(a[f], f, c), null != d && i.push(d); return e.apply([], i) }, guid: 1, proxy: function (a, b) { var c, e, f; return \"string\" == typeof b && (c = a[b], b = a, a = c), o.isFunction(a) ? (e = d.call(arguments, 2), f = function () { return a.apply(b || this, e.concat(d.call(arguments))) }, f.guid = a.guid = a.guid || o.guid++, f) : void 0 }, now: Date.now, support: l }), o.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function (a, b) { h[\"[object \" + b + \"]\"] = b.toLowerCase() }); function s(a) { var b = a.length, c = o.type(a); return \"function\" === c || o.isWindow(a) ? !1 : 1 === a.nodeType && b ? !0 : \"array\" === c || 0 === b || \"number\" == typeof b && b > 0 && b - 1 in a } var t = function (a) { var b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s = \"sizzle\" + -new Date, t = a.document, u = 0, v = 0, w = eb(), x = eb(), y = eb(), z = function (a, b) { return a === b && (j = !0), 0 }, A = \"undefined\", B = 1 << 31, C = {}.hasOwnProperty, D = [], E = D.pop, F = D.push, G = D.push, H = D.slice, I = D.indexOf || function (a) { for (var b = 0, c = this.length; c > b; b++)if (this[b] === a) return b; return -1 }, J = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\", K = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\", L = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\", M = L.replace(\"w\", \"w#\"), N = \"\\\\[\" + K + \"*(\" + L + \")\" + K + \"*(?:([*^$|!~]?=)\" + K + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + M + \")|)|)\" + K + \"*\\\\]\", O = \":(\" + L + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + N.replace(3, 8) + \")*)|.*)\\\\)|)\", P = new RegExp(\"^\" + K + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + K + \"+$\", \"g\"), Q = new RegExp(\"^\" + K + \"*,\" + K + \"*\"), R = new RegExp(\"^\" + K + \"*([>+~]|\" + K + \")\" + K + \"*\"), S = new RegExp(\"=\" + K + \"*([^\\\\]'\\\"]*?)\" + K + \"*\\\\]\", \"g\"), T = new RegExp(O), U = new RegExp(\"^\" + M + \"$\"), V = { ID: new RegExp(\"^#(\" + L + \")\"), CLASS: new RegExp(\"^\\\\.(\" + L + \")\"), TAG: new RegExp(\"^(\" + L.replace(\"w\", \"w*\") + \")\"), ATTR: new RegExp(\"^\" + N), PSEUDO: new RegExp(\"^\" + O), CHILD: new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + K + \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + K + \"*(?:([+-]|)\" + K + \"*(\\\\d+)|))\" + K + \"*\\\\)|)\", \"i\"), bool: new RegExp(\"^(?:\" + J + \")$\", \"i\"), needsContext: new RegExp(\"^\" + K + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + K + \"*((?:-\\\\d)?\\\\d*)\" + K + \"*\\\\)|)(?=[^-]|$)\", \"i\") }, W = /^(?:input|select|textarea|button)$/i, X = /^h\\d$/i, Y = /^[^{]+\\{\\s*\\[native \\w/, Z = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/, $ = /[+~]/, _ = /'|\\\\/g, ab = new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\" + K + \"?|(\" + K + \")|.)\", \"ig\"), bb = function (a, b, c) { var d = \"0x\" + b - 65536; return d !== d || c ? b : 0 > d ? String.fromCharCode(d + 65536) : String.fromCharCode(d >> 10 | 55296, 1023 & d | 56320) }; try { G.apply(D = H.call(t.childNodes), t.childNodes), D[t.childNodes.length].nodeType } catch (cb) { G = { apply: D.length ? function (a, b) { F.apply(a, H.call(b)) } : function (a, b) { var c = a.length, d = 0; while (a[c++] = b[d++]); a.length = c - 1 } } } function db(a, b, d, e) { var f, g, h, i, j, m, p, q, u, v; if ((b ? b.ownerDocument || b : t) !== l && k(b), b = b || l, d = d || [], !a || \"string\" != typeof a) return d; if (1 !== (i = b.nodeType) && 9 !== i) return []; if (n && !e) { if (f = Z.exec(a)) if (h = f[1]) { if (9 === i) { if (g = b.getElementById(h), !g || !g.parentNode) return d; if (g.id === h) return d.push(g), d } else if (b.ownerDocument && (g = b.ownerDocument.getElementById(h)) && r(b, g) && g.id === h) return d.push(g), d } else { if (f[2]) return G.apply(d, b.getElementsByTagName(a)), d; if ((h = f[3]) && c.getElementsByClassName && b.getElementsByClassName) return G.apply(d, b.getElementsByClassName(h)), d } if (c.qsa && (!o || !o.test(a))) { if (q = p = s, u = b, v = 9 === i && a, 1 === i && \"object\" !== b.nodeName.toLowerCase()) { m = ob(a), (p = b.getAttribute(\"id\")) ? q = p.replace(_, \"\\\\$&\") : b.setAttribute(\"id\", q), q = \"[id='\" + q + \"'] \", j = m.length; while (j--) m[j] = q + pb(m[j]); u = $.test(a) && mb(b.parentNode) || b, v = m.join(\",\") } if (v) try { return G.apply(d, u.querySelectorAll(v)), d } catch (w) { } finally { p || b.removeAttribute(\"id\") } } } return xb(a.replace(P, \"$1\"), b, d, e) } function eb() { var a = []; function b(c, e) { return a.push(c + \" \") > d.cacheLength && delete b[a.shift()], b[c + \" \"] = e } return b } function fb(a) { return a[s] = !0, a } function gb(a) { var b = l.createElement(\"div\"); try { return !!a(b) } catch (c) { return !1 } finally { b.parentNode && b.parentNode.removeChild(b), b = null } } function hb(a, b) { var c = a.split(\"|\"), e = a.length; while (e--) d.attrHandle[c[e]] = b } function ib(a, b) { var c = b && a, d = c && 1 === a.nodeType && 1 === b.nodeType && (~b.sourceIndex || B) - (~a.sourceIndex || B); if (d) return d; if (c) while (c = c.nextSibling) if (c === b) return -1; return a ? 1 : -1 } function jb(a) { return function (b) { var c = b.nodeName.toLowerCase(); return \"input\" === c && b.type === a } } function kb(a) { return function (b) { var c = b.nodeName.toLowerCase(); return (\"input\" === c || \"button\" === c) && b.type === a } } function lb(a) { return fb(function (b) { return b = +b, fb(function (c, d) { var e, f = a([], c.length, b), g = f.length; while (g--) c[e = f[g]] && (c[e] = !(d[e] = c[e])) }) }) } function mb(a) { return a && typeof a.getElementsByTagName !== A && a } c = db.support = {}, f = db.isXML = function (a) { var b = a && (a.ownerDocument || a).documentElement; return b ? \"HTML\" !== b.nodeName : !1 }, k = db.setDocument = function (a) { var b, e = a ? a.ownerDocument || a : t, g = e.defaultView; return e !== l && 9 === e.nodeType && e.documentElement ? (l = e, m = e.documentElement, n = !f(e), g && g !== g.top && (g.addEventListener ? g.addEventListener(\"unload\", function () { k() }, !1) : g.attachEvent && g.attachEvent(\"onunload\", function () { k() })), c.attributes = gb(function (a) { return a.className = \"i\", !a.getAttribute(\"className\") }), c.getElementsByTagName = gb(function (a) { return a.appendChild(e.createComment(\"\")), !a.getElementsByTagName(\"*\").length }), c.getElementsByClassName = Y.test(e.getElementsByClassName) && gb(function (a) { return a.innerHTML = \"
\", a.firstChild.className = \"i\", 2 === a.getElementsByClassName(\"i\").length }), c.getById = gb(function (a) { return m.appendChild(a).id = s, !e.getElementsByName || !e.getElementsByName(s).length }), c.getById ? (d.find.ID = function (a, b) { if (typeof b.getElementById !== A && n) { var c = b.getElementById(a); return c && c.parentNode ? [c] : [] } }, d.filter.ID = function (a) { var b = a.replace(ab, bb); return function (a) { return a.getAttribute(\"id\") === b } }) : (delete d.find.ID, d.filter.ID = function (a) { var b = a.replace(ab, bb); return function (a) { var c = typeof a.getAttributeNode !== A && a.getAttributeNode(\"id\"); return c && c.value === b } }), d.find.TAG = c.getElementsByTagName ? function (a, b) { return typeof b.getElementsByTagName !== A ? b.getElementsByTagName(a) : void 0 } : function (a, b) { var c, d = [], e = 0, f = b.getElementsByTagName(a); if (\"*\" === a) { while (c = f[e++]) 1 === c.nodeType && d.push(c); return d } return f }, d.find.CLASS = c.getElementsByClassName && function (a, b) { return typeof b.getElementsByClassName !== A && n ? b.getElementsByClassName(a) : void 0 }, p = [], o = [], (c.qsa = Y.test(e.querySelectorAll)) && (gb(function (a) { a.innerHTML = \"\", a.querySelectorAll(\"[t^='']\").length && o.push(\"[*^$]=\" + K + \"*(?:''|\\\"\\\")\"), a.querySelectorAll(\"[selected]\").length || o.push(\"\\\\[\" + K + \"*(?:value|\" + J + \")\"), a.querySelectorAll(\":checked\").length || o.push(\":checked\") }), gb(function (a) { var b = e.createElement(\"input\"); b.setAttribute(\"type\", \"hidden\"), a.appendChild(b).setAttribute(\"name\", \"D\"), a.querySelectorAll(\"[name=d]\").length && o.push(\"name\" + K + \"*[*^$|!~]?=\"), a.querySelectorAll(\":enabled\").length || o.push(\":enabled\", \":disabled\"), a.querySelectorAll(\"*,:x\"), o.push(\",.*:\") })), (c.matchesSelector = Y.test(q = m.webkitMatchesSelector || m.mozMatchesSelector || m.oMatchesSelector || m.msMatchesSelector)) && gb(function (a) { c.disconnectedMatch = q.call(a, \"div\"), q.call(a, \"[s!='']:x\"), p.push(\"!=\", O) }), o = o.length && new RegExp(o.join(\"|\")), p = p.length && new RegExp(p.join(\"|\")), b = Y.test(m.compareDocumentPosition), r = b || Y.test(m.contains) ? function (a, b) { var c = 9 === a.nodeType ? a.documentElement : a, d = b && b.parentNode; return a === d || !(!d || 1 !== d.nodeType || !(c.contains ? c.contains(d) : a.compareDocumentPosition && 16 & a.compareDocumentPosition(d))) } : function (a, b) { if (b) while (b = b.parentNode) if (b === a) return !0; return !1 }, z = b ? function (a, b) { if (a === b) return j = !0, 0; var d = !a.compareDocumentPosition - !b.compareDocumentPosition; return d ? d : (d = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1, 1 & d || !c.sortDetached && b.compareDocumentPosition(a) === d ? a === e || a.ownerDocument === t && r(t, a) ? -1 : b === e || b.ownerDocument === t && r(t, b) ? 1 : i ? I.call(i, a) - I.call(i, b) : 0 : 4 & d ? -1 : 1) } : function (a, b) { if (a === b) return j = !0, 0; var c, d = 0, f = a.parentNode, g = b.parentNode, h = [a], k = [b]; if (!f || !g) return a === e ? -1 : b === e ? 1 : f ? -1 : g ? 1 : i ? I.call(i, a) - I.call(i, b) : 0; if (f === g) return ib(a, b); c = a; while (c = c.parentNode) h.unshift(c); c = b; while (c = c.parentNode) k.unshift(c); while (h[d] === k[d]) d++; return d ? ib(h[d], k[d]) : h[d] === t ? -1 : k[d] === t ? 1 : 0 }, e) : l }, db.matches = function (a, b) { return db(a, null, null, b) }, db.matchesSelector = function (a, b) { if ((a.ownerDocument || a) !== l && k(a), b = b.replace(S, \"='$1']\"), !(!c.matchesSelector || !n || p && p.test(b) || o && o.test(b))) try { var d = q.call(a, b); if (d || c.disconnectedMatch || a.document && 11 !== a.document.nodeType) return d } catch (e) { } return db(b, l, null, [a]).length > 0 }, db.contains = function (a, b) { return (a.ownerDocument || a) !== l && k(a), r(a, b) }, db.attr = function (a, b) { (a.ownerDocument || a) !== l && k(a); var e = d.attrHandle[b.toLowerCase()], f = e && C.call(d.attrHandle, b.toLowerCase()) ? e(a, b, !n) : void 0; return void 0 !== f ? f : c.attributes || !n ? a.getAttribute(b) : (f = a.getAttributeNode(b)) && f.specified ? f.value : null }, db.error = function (a) { throw new Error(\"Syntax error, unrecognized expression: \" + a) }, db.uniqueSort = function (a) { var b, d = [], e = 0, f = 0; if (j = !c.detectDuplicates, i = !c.sortStable && a.slice(0), a.sort(z), j) { while (b = a[f++]) b === a[f] && (e = d.push(f)); while (e--) a.splice(d[e], 1) } return i = null, a }, e = db.getText = function (a) { var b, c = \"\", d = 0, f = a.nodeType; if (f) { if (1 === f || 9 === f || 11 === f) { if (\"string\" == typeof a.textContent) return a.textContent; for (a = a.firstChild; a; a = a.nextSibling)c += e(a) } else if (3 === f || 4 === f) return a.nodeValue } else while (b = a[d++]) c += e(b); return c }, d = db.selectors = { cacheLength: 50, createPseudo: fb, match: V, attrHandle: {}, find: {}, relative: { \">\": { dir: \"parentNode\", first: !0 }, \" \": { dir: \"parentNode\" }, \"+\": { dir: \"previousSibling\", first: !0 }, \"~\": { dir: \"previousSibling\" } }, preFilter: { ATTR: function (a) { return a[1] = a[1].replace(ab, bb), a[3] = (a[4] || a[5] || \"\").replace(ab, bb), \"~=\" === a[2] && (a[3] = \" \" + a[3] + \" \"), a.slice(0, 4) }, CHILD: function (a) { return a[1] = a[1].toLowerCase(), \"nth\" === a[1].slice(0, 3) ? (a[3] || db.error(a[0]), a[4] = +(a[4] ? a[5] + (a[6] || 1) : 2 * (\"even\" === a[3] || \"odd\" === a[3])), a[5] = +(a[7] + a[8] || \"odd\" === a[3])) : a[3] && db.error(a[0]), a }, PSEUDO: function (a) { var b, c = !a[5] && a[2]; return V.CHILD.test(a[0]) ? null : (a[3] && void 0 !== a[4] ? a[2] = a[4] : c && T.test(c) && (b = ob(c, !0)) && (b = c.indexOf(\")\", c.length - b) - c.length) && (a[0] = a[0].slice(0, b), a[2] = c.slice(0, b)), a.slice(0, 3)) } }, filter: { TAG: function (a) { var b = a.replace(ab, bb).toLowerCase(); return \"*\" === a ? function () { return !0 } : function (a) { return a.nodeName && a.nodeName.toLowerCase() === b } }, CLASS: function (a) { var b = w[a + \" \"]; return b || (b = new RegExp(\"(^|\" + K + \")\" + a + \"(\" + K + \"|$)\")) && w(a, function (a) { return b.test(\"string\" == typeof a.className && a.className || typeof a.getAttribute !== A && a.getAttribute(\"class\") || \"\") }) }, ATTR: function (a, b, c) { return function (d) { var e = db.attr(d, a); return null == e ? \"!=\" === b : b ? (e += \"\", \"=\" === b ? e === c : \"!=\" === b ? e !== c : \"^=\" === b ? c && 0 === e.indexOf(c) : \"*=\" === b ? c && e.indexOf(c) > -1 : \"$=\" === b ? c && e.slice(-c.length) === c : \"~=\" === b ? (\" \" + e + \" \").indexOf(c) > -1 : \"|=\" === b ? e === c || e.slice(0, c.length + 1) === c + \"-\" : !1) : !0 } }, CHILD: function (a, b, c, d, e) { var f = \"nth\" !== a.slice(0, 3), g = \"last\" !== a.slice(-4), h = \"of-type\" === b; return 1 === d && 0 === e ? function (a) { return !!a.parentNode } : function (b, c, i) { var j, k, l, m, n, o, p = f !== g ? \"nextSibling\" : \"previousSibling\", q = b.parentNode, r = h && b.nodeName.toLowerCase(), t = !i && !h; if (q) { if (f) { while (p) { l = b; while (l = l[p]) if (h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) return !1; o = p = \"only\" === a && !o && \"nextSibling\" } return !0 } if (o = [g ? q.firstChild : q.lastChild], g && t) { k = q[s] || (q[s] = {}), j = k[a] || [], n = j[0] === u && j[1], m = j[0] === u && j[2], l = n && q.childNodes[n]; while (l = ++n && l && l[p] || (m = n = 0) || o.pop()) if (1 === l.nodeType && ++m && l === b) { k[a] = [u, n, m]; break } } else if (t && (j = (b[s] || (b[s] = {}))[a]) && j[0] === u) m = j[1]; else while (l = ++n && l && l[p] || (m = n = 0) || o.pop()) if ((h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) && ++m && (t && ((l[s] || (l[s] = {}))[a] = [u, m]), l === b)) break; return m -= e, m === d || m % d === 0 && m / d >= 0 } } }, PSEUDO: function (a, b) { var c, e = d.pseudos[a] || d.setFilters[a.toLowerCase()] || db.error(\"unsupported pseudo: \" + a); return e[s] ? e(b) : e.length > 1 ? (c = [a, a, \"\", b], d.setFilters.hasOwnProperty(a.toLowerCase()) ? fb(function (a, c) { var d, f = e(a, b), g = f.length; while (g--) d = I.call(a, f[g]), a[d] = !(c[d] = f[g]) }) : function (a) { return e(a, 0, c) }) : e } }, pseudos: { not: fb(function (a) { var b = [], c = [], d = g(a.replace(P, \"$1\")); return d[s] ? fb(function (a, b, c, e) { var f, g = d(a, null, e, []), h = a.length; while (h--) (f = g[h]) && (a[h] = !(b[h] = f)) }) : function (a, e, f) { return b[0] = a, d(b, null, f, c), !c.pop() } }), has: fb(function (a) { return function (b) { return db(a, b).length > 0 } }), contains: fb(function (a) { return function (b) { return (b.textContent || b.innerText || e(b)).indexOf(a) > -1 } }), lang: fb(function (a) { return U.test(a || \"\") || db.error(\"unsupported lang: \" + a), a = a.replace(ab, bb).toLowerCase(), function (b) { var c; do if (c = n ? b.lang : b.getAttribute(\"xml:lang\") || b.getAttribute(\"lang\")) return c = c.toLowerCase(), c === a || 0 === c.indexOf(a + \"-\"); while ((b = b.parentNode) && 1 === b.nodeType); return !1 } }), target: function (b) { var c = a.location && a.location.hash; return c && c.slice(1) === b.id }, root: function (a) { return a === m }, focus: function (a) { return a === l.activeElement && (!l.hasFocus || l.hasFocus()) && !!(a.type || a.href || ~a.tabIndex) }, enabled: function (a) { return a.disabled === !1 }, disabled: function (a) { return a.disabled === !0 }, checked: function (a) { var b = a.nodeName.toLowerCase(); return \"input\" === b && !!a.checked || \"option\" === b && !!a.selected }, selected: function (a) { return a.parentNode && a.parentNode.selectedIndex, a.selected === !0 }, empty: function (a) { for (a = a.firstChild; a; a = a.nextSibling)if (a.nodeType < 6) return !1; return !0 }, parent: function (a) { return !d.pseudos.empty(a) }, header: function (a) { return X.test(a.nodeName) }, input: function (a) { return W.test(a.nodeName) }, button: function (a) { var b = a.nodeName.toLowerCase(); return \"input\" === b && \"button\" === a.type || \"button\" === b }, text: function (a) { var b; return \"input\" === a.nodeName.toLowerCase() && \"text\" === a.type && (null == (b = a.getAttribute(\"type\")) || \"text\" === b.toLowerCase()) }, first: lb(function () { return [0] }), last: lb(function (a, b) { return [b - 1] }), eq: lb(function (a, b, c) { return [0 > c ? c + b : c] }), even: lb(function (a, b) { for (var c = 0; b > c; c += 2)a.push(c); return a }), odd: lb(function (a, b) { for (var c = 1; b > c; c += 2)a.push(c); return a }), lt: lb(function (a, b, c) { for (var d = 0 > c ? c + b : c; --d >= 0;)a.push(d); return a }), gt: lb(function (a, b, c) { for (var d = 0 > c ? c + b : c; ++d < b;)a.push(d); return a }) } }, d.pseudos.nth = d.pseudos.eq; for (b in { radio: !0, checkbox: !0, file: !0, password: !0, image: !0 }) d.pseudos[b] = jb(b); for (b in { submit: !0, reset: !0 }) d.pseudos[b] = kb(b); function nb() { } nb.prototype = d.filters = d.pseudos, d.setFilters = new nb; function ob(a, b) { var c, e, f, g, h, i, j, k = x[a + \" \"]; if (k) return b ? 0 : k.slice(0); h = a, i = [], j = d.preFilter; while (h) { (!c || (e = Q.exec(h))) && (e && (h = h.slice(e[0].length) || h), i.push(f = [])), c = !1, (e = R.exec(h)) && (c = e.shift(), f.push({ value: c, type: e[0].replace(P, \" \") }), h = h.slice(c.length)); for (g in d.filter) !(e = V[g].exec(h)) || j[g] && !(e = j[g](e)) || (c = e.shift(), f.push({ value: c, type: g, matches: e }), h = h.slice(c.length)); if (!c) break } return b ? h.length : h ? db.error(a) : x(a, i).slice(0) } function pb(a) { for (var b = 0, c = a.length, d = \"\"; c > b; b++)d += a[b].value; return d } function qb(a, b, c) { var d = b.dir, e = c && \"parentNode\" === d, f = v++; return b.first ? function (b, c, f) { while (b = b[d]) if (1 === b.nodeType || e) return a(b, c, f) } : function (b, c, g) { var h, i, j = [u, f]; if (g) { while (b = b[d]) if ((1 === b.nodeType || e) && a(b, c, g)) return !0 } else while (b = b[d]) if (1 === b.nodeType || e) { if (i = b[s] || (b[s] = {}), (h = i[d]) && h[0] === u && h[1] === f) return j[2] = h[2]; if (i[d] = j, j[2] = a(b, c, g)) return !0 } } } function rb(a) { return a.length > 1 ? function (b, c, d) { var e = a.length; while (e--) if (!a[e](b, c, d)) return !1; return !0 } : a[0] } function sb(a, b, c, d, e) { for (var f, g = [], h = 0, i = a.length, j = null != b; i > h; h++)(f = a[h]) && (!c || c(f, d, e)) && (g.push(f), j && b.push(h)); return g } function tb(a, b, c, d, e, f) { return d && !d[s] && (d = tb(d)), e && !e[s] && (e = tb(e, f)), fb(function (f, g, h, i) { var j, k, l, m = [], n = [], o = g.length, p = f || wb(b || \"*\", h.nodeType ? [h] : h, []), q = !a || !f && b ? p : sb(p, m, a, h, i), r = c ? e || (f ? a : o || d) ? [] : g : q; if (c && c(q, r, h, i), d) { j = sb(r, n), d(j, [], h, i), k = j.length; while (k--) (l = j[k]) && (r[n[k]] = !(q[n[k]] = l)) } if (f) { if (e || a) { if (e) { j = [], k = r.length; while (k--) (l = r[k]) && j.push(q[k] = l); e(null, r = [], j, i) } k = r.length; while (k--) (l = r[k]) && (j = e ? I.call(f, l) : m[k]) > -1 && (f[j] = !(g[j] = l)) } } else r = sb(r === g ? r.splice(o, r.length) : r), e ? e(null, g, r, i) : G.apply(g, r) }) } function ub(a) { for (var b, c, e, f = a.length, g = d.relative[a[0].type], i = g || d.relative[\" \"], j = g ? 1 : 0, k = qb(function (a) { return a === b }, i, !0), l = qb(function (a) { return I.call(b, a) > -1 }, i, !0), m = [function (a, c, d) { return !g && (d || c !== h) || ((b = c).nodeType ? k(a, c, d) : l(a, c, d)) }]; f > j; j++)if (c = d.relative[a[j].type]) m = [qb(rb(m), c)]; else { if (c = d.filter[a[j].type].apply(null, a[j].matches), c[s]) { for (e = ++j; f > e; e++)if (d.relative[a[e].type]) break; return tb(j > 1 && rb(m), j > 1 && pb(a.slice(0, j - 1).concat({ value: \" \" === a[j - 2].type ? \"*\" : \"\" })).replace(P, \"$1\"), c, e > j && ub(a.slice(j, e)), f > e && ub(a = a.slice(e)), f > e && pb(a)) } m.push(c) } return rb(m) } function vb(a, b) { var c = b.length > 0, e = a.length > 0, f = function (f, g, i, j, k) { var m, n, o, p = 0, q = \"0\", r = f && [], s = [], t = h, v = f || e && d.find.TAG(\"*\", k), w = u += null == t ? 1 : Math.random() || .1, x = v.length; for (k && (h = g !== l && g); q !== x && null != (m = v[q]); q++) { if (e && m) { n = 0; while (o = a[n++]) if (o(m, g, i)) { j.push(m); break } k && (u = w) } c && ((m = !o && m) && p--, f && r.push(m)) } if (p += q, c && q !== p) { n = 0; while (o = b[n++]) o(r, s, g, i); if (f) { if (p > 0) while (q--) r[q] || s[q] || (s[q] = E.call(j)); s = sb(s) } G.apply(j, s), k && !f && s.length > 0 && p + b.length > 1 && db.uniqueSort(j) } return k && (u = w, h = t), r }; return c ? fb(f) : f } g = db.compile = function (a, b) { var c, d = [], e = [], f = y[a + \" \"]; if (!f) { b || (b = ob(a)), c = b.length; while (c--) f = ub(b[c]), f[s] ? d.push(f) : e.push(f); f = y(a, vb(e, d)) } return f }; function wb(a, b, c) { for (var d = 0, e = b.length; e > d; d++)db(a, b[d], c); return c } function xb(a, b, e, f) { var h, i, j, k, l, m = ob(a); if (!f && 1 === m.length) { if (i = m[0] = m[0].slice(0), i.length > 2 && \"ID\" === (j = i[0]).type && c.getById && 9 === b.nodeType && n && d.relative[i[1].type]) { if (b = (d.find.ID(j.matches[0].replace(ab, bb), b) || [])[0], !b) return e; a = a.slice(i.shift().value.length) } h = V.needsContext.test(a) ? 0 : i.length; while (h--) { if (j = i[h], d.relative[k = j.type]) break; if ((l = d.find[k]) && (f = l(j.matches[0].replace(ab, bb), $.test(i[0].type) && mb(b.parentNode) || b))) { if (i.splice(h, 1), a = f.length && pb(i), !a) return G.apply(e, f), e; break } } } return g(a, m)(f, b, !n, e, $.test(a) && mb(b.parentNode) || b), e } return c.sortStable = s.split(\"\").sort(z).join(\"\") === s, c.detectDuplicates = !!j, k(), c.sortDetached = gb(function (a) { return 1 & a.compareDocumentPosition(l.createElement(\"div\")) }), gb(function (a) { return a.innerHTML = \"\", \"#\" === a.firstChild.getAttribute(\"href\") }) || hb(\"type|href|height|width\", function (a, b, c) { return c ? void 0 : a.getAttribute(b, \"type\" === b.toLowerCase() ? 1 : 2) }), c.attributes && gb(function (a) { return a.innerHTML = \"\", a.firstChild.setAttribute(\"value\", \"\"), \"\" === a.firstChild.getAttribute(\"value\") }) || hb(\"value\", function (a, b, c) { return c || \"input\" !== a.nodeName.toLowerCase() ? void 0 : a.defaultValue }), gb(function (a) { return null == a.getAttribute(\"disabled\") }) || hb(J, function (a, b, c) { var d; return c ? void 0 : a[b] === !0 ? b.toLowerCase() : (d = a.getAttributeNode(b)) && d.specified ? d.value : null }), db }(a); o.find = t, o.expr = t.selectors, o.expr[\":\"] = o.expr.pseudos, o.unique = t.uniqueSort, o.text = t.getText, o.isXMLDoc = t.isXML, o.contains = t.contains; var u = o.expr.match.needsContext, v = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/, w = /^.[^:#\\[\\.,]*$/; function x(a, b, c) { if (o.isFunction(b)) return o.grep(a, function (a, d) { return !!b.call(a, d, a) !== c }); if (b.nodeType) return o.grep(a, function (a) { return a === b !== c }); if (\"string\" == typeof b) { if (w.test(b)) return o.filter(b, a, c); b = o.filter(b, a) } return o.grep(a, function (a) { return g.call(b, a) >= 0 !== c }) } o.filter = function (a, b, c) { var d = b[0]; return c && (a = \":not(\" + a + \")\"), 1 === b.length && 1 === d.nodeType ? o.find.matchesSelector(d, a) ? [d] : [] : o.find.matches(a, o.grep(b, function (a) { return 1 === a.nodeType })) }, o.fn.extend({ find: function (a) { var b, c = this.length, d = [], e = this; if (\"string\" != typeof a) return this.pushStack(o(a).filter(function () { for (b = 0; c > b; b++)if (o.contains(e[b], this)) return !0 })); for (b = 0; c > b; b++)o.find(a, e[b], d); return d = this.pushStack(c > 1 ? o.unique(d) : d), d.selector = this.selector ? this.selector + \" \" + a : a, d }, filter: function (a) { return this.pushStack(x(this, a || [], !1)) }, not: function (a) { return this.pushStack(x(this, a || [], !0)) }, is: function (a) { return !!x(this, \"string\" == typeof a && u.test(a) ? o(a) : a || [], !1).length } }); var y, z = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/, A = o.fn.init = function (a, b) { var c, d; if (!a) return this; if (\"string\" == typeof a) { if (c = \"<\" === a[0] && \">\" === a[a.length - 1] && a.length >= 3 ? [null, a, null] : z.exec(a), !c || !c[1] && b) return !b || b.jquery ? (b || y).find(a) : this.constructor(b).find(a); if (c[1]) { if (b = b instanceof o ? b[0] : b, o.merge(this, o.parseHTML(c[1], b && b.nodeType ? b.ownerDocument || b : m, !0)), v.test(c[1]) && o.isPlainObject(b)) for (c in b) o.isFunction(this[c]) ? this[c](b[c]) : this.attr(c, b[c]); return this } return d = m.getElementById(c[2]), d && d.parentNode && (this.length = 1, this[0] = d), this.context = m, this.selector = a, this } return a.nodeType ? (this.context = this[0] = a, this.length = 1, this) : o.isFunction(a) ? \"undefined\" != typeof y.ready ? y.ready(a) : a(o) : (void 0 !== a.selector && (this.selector = a.selector, this.context = a.context), o.makeArray(a, this)) }; A.prototype = o.fn, y = o(m); var B = /^(?:parents|prev(?:Until|All))/, C = { children: !0, contents: !0, next: !0, prev: !0 }; o.extend({ dir: function (a, b, c) { var d = [], e = void 0 !== c; while ((a = a[b]) && 9 !== a.nodeType) if (1 === a.nodeType) { if (e && o(a).is(c)) break; d.push(a) } return d }, sibling: function (a, b) { for (var c = []; a; a = a.nextSibling)1 === a.nodeType && a !== b && c.push(a); return c } }), o.fn.extend({ has: function (a) { var b = o(a, this), c = b.length; return this.filter(function () { for (var a = 0; c > a; a++)if (o.contains(this, b[a])) return !0 }) }, closest: function (a, b) { for (var c, d = 0, e = this.length, f = [], g = u.test(a) || \"string\" != typeof a ? o(a, b || this.context) : 0; e > d; d++)for (c = this[d]; c && c !== b; c = c.parentNode)if (c.nodeType < 11 && (g ? g.index(c) > -1 : 1 === c.nodeType && o.find.matchesSelector(c, a))) { f.push(c); break } return this.pushStack(f.length > 1 ? o.unique(f) : f) }, index: function (a) { return a ? \"string\" == typeof a ? g.call(o(a), this[0]) : g.call(this, a.jquery ? a[0] : a) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 }, add: function (a, b) { return this.pushStack(o.unique(o.merge(this.get(), o(a, b)))) }, addBack: function (a) { return this.add(null == a ? this.prevObject : this.prevObject.filter(a)) } }); function D(a, b) { while ((a = a[b]) && 1 !== a.nodeType); return a } o.each({ parent: function (a) { var b = a.parentNode; return b && 11 !== b.nodeType ? b : null }, parents: function (a) { return o.dir(a, \"parentNode\") }, parentsUntil: function (a, b, c) { return o.dir(a, \"parentNode\", c) }, next: function (a) { return D(a, \"nextSibling\") }, prev: function (a) { return D(a, \"previousSibling\") }, nextAll: function (a) { return o.dir(a, \"nextSibling\") }, prevAll: function (a) { return o.dir(a, \"previousSibling\") }, nextUntil: function (a, b, c) { return o.dir(a, \"nextSibling\", c) }, prevUntil: function (a, b, c) { return o.dir(a, \"previousSibling\", c) }, siblings: function (a) { return o.sibling((a.parentNode || {}).firstChild, a) }, children: function (a) { return o.sibling(a.firstChild) }, contents: function (a) { return a.contentDocument || o.merge([], a.childNodes) } }, function (a, b) { o.fn[a] = function (c, d) { var e = o.map(this, b, c); return \"Until\" !== a.slice(-5) && (d = c), d && \"string\" == typeof d && (e = o.filter(d, e)), this.length > 1 && (C[a] || o.unique(e), B.test(a) && e.reverse()), this.pushStack(e) } }); var E = /\\S+/g, F = {}; function G(a) { var b = F[a] = {}; return o.each(a.match(E) || [], function (a, c) { b[c] = !0 }), b } o.Callbacks = function (a) { a = \"string\" == typeof a ? F[a] || G(a) : o.extend({}, a); var b, c, d, e, f, g, h = [], i = !a.once && [], j = function (l) { for (b = a.memory && l, c = !0, g = e || 0, e = 0, f = h.length, d = !0; h && f > g; g++)if (h[g].apply(l[0], l[1]) === !1 && a.stopOnFalse) { b = !1; break } d = !1, h && (i ? i.length && j(i.shift()) : b ? h = [] : k.disable()) }, k = { add: function () { if (h) { var c = h.length; !function g(b) { o.each(b, function (b, c) { var d = o.type(c); \"function\" === d ? a.unique && k.has(c) || h.push(c) : c && c.length && \"string\" !== d && g(c) }) }(arguments), d ? f = h.length : b && (e = c, j(b)) } return this }, remove: function () { return h && o.each(arguments, function (a, b) { var c; while ((c = o.inArray(b, h, c)) > -1) h.splice(c, 1), d && (f >= c && f--, g >= c && g--) }), this }, has: function (a) { return a ? o.inArray(a, h) > -1 : !(!h || !h.length) }, empty: function () { return h = [], f = 0, this }, disable: function () { return h = i = b = void 0, this }, disabled: function () { return !h }, lock: function () { return i = void 0, b || k.disable(), this }, locked: function () { return !i }, fireWith: function (a, b) { return !h || c && !i || (b = b || [], b = [a, b.slice ? b.slice() : b], d ? i.push(b) : j(b)), this }, fire: function () { return k.fireWith(this, arguments), this }, fired: function () { return !!c } }; return k }, o.extend({ Deferred: function (a) { var b = [[\"resolve\", \"done\", o.Callbacks(\"once memory\"), \"resolved\"], [\"reject\", \"fail\", o.Callbacks(\"once memory\"), \"rejected\"], [\"notify\", \"progress\", o.Callbacks(\"memory\")]], c = \"pending\", d = { state: function () { return c }, always: function () { return e.done(arguments).fail(arguments), this }, then: function () { var a = arguments; return o.Deferred(function (c) { o.each(b, function (b, f) { var g = o.isFunction(a[b]) && a[b]; e[f[1]](function () { var a = g && g.apply(this, arguments); a && o.isFunction(a.promise) ? a.promise().done(c.resolve).fail(c.reject).progress(c.notify) : c[f[0] + \"With\"](this === d ? c.promise() : this, g ? [a] : arguments) }) }), a = null }).promise() }, promise: function (a) { return null != a ? o.extend(a, d) : d } }, e = {}; return d.pipe = d.then, o.each(b, function (a, f) { var g = f[2], h = f[3]; d[f[1]] = g.add, h && g.add(function () { c = h }, b[1 ^ a][2].disable, b[2][2].lock), e[f[0]] = function () { return e[f[0] + \"With\"](this === e ? d : this, arguments), this }, e[f[0] + \"With\"] = g.fireWith }), d.promise(e), a && a.call(e, e), e }, when: function (a) { var b = 0, c = d.call(arguments), e = c.length, f = 1 !== e || a && o.isFunction(a.promise) ? e : 0, g = 1 === f ? a : o.Deferred(), h = function (a, b, c) { return function (e) { b[a] = this, c[a] = arguments.length > 1 ? d.call(arguments) : e, c === i ? g.notifyWith(b, c) : --f || g.resolveWith(b, c) } }, i, j, k; if (e > 1) for (i = new Array(e), j = new Array(e), k = new Array(e); e > b; b++)c[b] && o.isFunction(c[b].promise) ? c[b].promise().done(h(b, k, c)).fail(g.reject).progress(h(b, j, i)) : --f; return f || g.resolveWith(k, c), g.promise() } }); var H; o.fn.ready = function (a) { return o.ready.promise().done(a), this }, o.extend({ isReady: !1, readyWait: 1, holdReady: function (a) { a ? o.readyWait++ : o.ready(!0) }, ready: function (a) { (a === !0 ? --o.readyWait : o.isReady) || (o.isReady = !0, a !== !0 && --o.readyWait > 0 || (H.resolveWith(m, [o]), o.fn.trigger && o(m).trigger(\"ready\").off(\"ready\"))) } }); function I() { m.removeEventListener(\"DOMContentLoaded\", I, !1), a.removeEventListener(\"load\", I, !1), o.ready() } o.ready.promise = function (b) { return H || (H = o.Deferred(), \"complete\" === m.readyState ? setTimeout(o.ready) : (m.addEventListener(\"DOMContentLoaded\", I, !1), a.addEventListener(\"load\", I, !1))), H.promise(b) }, o.ready.promise(); var J = o.access = function (a, b, c, d, e, f, g) { var h = 0, i = a.length, j = null == c; if (\"object\" === o.type(c)) { e = !0; for (h in c) o.access(a, b, h, c[h], !0, f, g) } else if (void 0 !== d && (e = !0, o.isFunction(d) || (g = !0), j && (g ? (b.call(a, d), b = null) : (j = b, b = function (a, b, c) { return j.call(o(a), c) })), b)) for (; i > h; h++)b(a[h], c, g ? d : d.call(a[h], h, b(a[h], c))); return e ? a : j ? b.call(a) : i ? b(a[0], c) : f }; o.acceptData = function (a) { return 1 === a.nodeType || 9 === a.nodeType || !+a.nodeType }; function K() { Object.defineProperty(this.cache = {}, 0, { get: function () { return {} } }), this.expando = o.expando + Math.random() } K.uid = 1, K.accepts = o.acceptData, K.prototype = { key: function (a) { if (!K.accepts(a)) return 0; var b = {}, c = a[this.expando]; if (!c) { c = K.uid++; try { b[this.expando] = { value: c }, Object.defineProperties(a, b) } catch (d) { b[this.expando] = c, o.extend(a, b) } } return this.cache[c] || (this.cache[c] = {}), c }, set: function (a, b, c) { var d, e = this.key(a), f = this.cache[e]; if (\"string\" == typeof b) f[b] = c; else if (o.isEmptyObject(f)) o.extend(this.cache[e], b); else for (d in b) f[d] = b[d]; return f }, get: function (a, b) { var c = this.cache[this.key(a)]; return void 0 === b ? c : c[b] }, access: function (a, b, c) { var d; return void 0 === b || b && \"string\" == typeof b && void 0 === c ? (d = this.get(a, b), void 0 !== d ? d : this.get(a, o.camelCase(b))) : (this.set(a, b, c), void 0 !== c ? c : b) }, remove: function (a, b) { var c, d, e, f = this.key(a), g = this.cache[f]; if (void 0 === b) this.cache[f] = {}; else { o.isArray(b) ? d = b.concat(b.map(o.camelCase)) : (e = o.camelCase(b), b in g ? d = [b, e] : (d = e, d = d in g ? [d] : d.match(E) || [])), c = d.length; while (c--) delete g[d[c]] } }, hasData: function (a) { return !o.isEmptyObject(this.cache[a[this.expando]] || {}) }, discard: function (a) { a[this.expando] && delete this.cache[a[this.expando]] } }; var L = new K, M = new K, N = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/, O = /([A-Z])/g; function P(a, b, c) { var d; if (void 0 === c && 1 === a.nodeType) if (d = \"data-\" + b.replace(O, \"-$1\").toLowerCase(), c = a.getAttribute(d), \"string\" == typeof c) { try { c = \"true\" === c ? !0 : \"false\" === c ? !1 : \"null\" === c ? null : +c + \"\" === c ? +c : N.test(c) ? o.parseJSON(c) : c } catch (e) { } M.set(a, b, c) } else c = void 0; return c } o.extend({ hasData: function (a) { return M.hasData(a) || L.hasData(a) }, data: function (a, b, c) { return M.access(a, b, c) }, removeData: function (a, b) { M.remove(a, b) }, _data: function (a, b, c) { return L.access(a, b, c) }, _removeData: function (a, b) { L.remove(a, b) } }), o.fn.extend({\n data: function (a, b) {\n var c, d, e, f = this[0], g = f && f.attributes; if (void 0 === a) {\n if (this.length && (e = M.get(f), 1 === f.nodeType && !L.get(f, \"hasDataAttrs\"))) {\n c = g.length;\n while (c--) d = g[c].name, 0 === d.indexOf(\"data-\") && (d = o.camelCase(d.slice(5)), P(f, d, e[d])); L.set(f, \"hasDataAttrs\", !0)\n } return e\n } return \"object\" == typeof a ? this.each(function () { M.set(this, a) }) : J(this, function (b) { var c, d = o.camelCase(a); if (f && void 0 === b) { if (c = M.get(f, a), void 0 !== c) return c; if (c = M.get(f, d), void 0 !== c) return c; if (c = P(f, d, void 0), void 0 !== c) return c } else this.each(function () { var c = M.get(this, d); M.set(this, d, b), -1 !== a.indexOf(\"-\") && void 0 !== c && M.set(this, a, b) }) }, null, b, arguments.length > 1, null, !0)\n }, removeData: function (a) { return this.each(function () { M.remove(this, a) }) }\n }), o.extend({ queue: function (a, b, c) { var d; return a ? (b = (b || \"fx\") + \"queue\", d = L.get(a, b), c && (!d || o.isArray(c) ? d = L.access(a, b, o.makeArray(c)) : d.push(c)), d || []) : void 0 }, dequeue: function (a, b) { b = b || \"fx\"; var c = o.queue(a, b), d = c.length, e = c.shift(), f = o._queueHooks(a, b), g = function () { o.dequeue(a, b) }; \"inprogress\" === e && (e = c.shift(), d--), e && (\"fx\" === b && c.unshift(\"inprogress\"), delete f.stop, e.call(a, g, f)), !d && f && f.empty.fire() }, _queueHooks: function (a, b) { var c = b + \"queueHooks\"; return L.get(a, c) || L.access(a, c, { empty: o.Callbacks(\"once memory\").add(function () { L.remove(a, [b + \"queue\", c]) }) }) } }), o.fn.extend({ queue: function (a, b) { var c = 2; return \"string\" != typeof a && (b = a, a = \"fx\", c--), arguments.length < c ? o.queue(this[0], a) : void 0 === b ? this : this.each(function () { var c = o.queue(this, a, b); o._queueHooks(this, a), \"fx\" === a && \"inprogress\" !== c[0] && o.dequeue(this, a) }) }, dequeue: function (a) { return this.each(function () { o.dequeue(this, a) }) }, clearQueue: function (a) { return this.queue(a || \"fx\", []) }, promise: function (a, b) { var c, d = 1, e = o.Deferred(), f = this, g = this.length, h = function () { --d || e.resolveWith(f, [f]) }; \"string\" != typeof a && (b = a, a = void 0), a = a || \"fx\"; while (g--) c = L.get(f[g], a + \"queueHooks\"), c && c.empty && (d++, c.empty.add(h)); return h(), e.promise(b) } }); var Q = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source, R = [\"Top\", \"Right\", \"Bottom\", \"Left\"], S = function (a, b) { return a = b || a, \"none\" === o.css(a, \"display\") || !o.contains(a.ownerDocument, a) }, T = /^(?:checkbox|radio)$/i; !function () { var a = m.createDocumentFragment(), b = a.appendChild(m.createElement(\"div\")); b.innerHTML = \"\", l.checkClone = b.cloneNode(!0).cloneNode(!0).lastChild.checked, b.innerHTML = \"\", l.noCloneChecked = !!b.cloneNode(!0).lastChild.defaultValue }(); var U = \"undefined\"; l.focusinBubbles = \"onfocusin\" in a; var V = /^key/, W = /^(?:mouse|contextmenu)|click/, X = /^(?:focusinfocus|focusoutblur)$/, Y = /^([^.]*)(?:\\.(.+)|)$/; function Z() { return !0 } function $() { return !1 } function _() { try { return m.activeElement } catch (a) { } } o.event = { global: {}, add: function (a, b, c, d, e) { var f, g, h, i, j, k, l, m, n, p, q, r = L.get(a); if (r) { c.handler && (f = c, c = f.handler, e = f.selector), c.guid || (c.guid = o.guid++), (i = r.events) || (i = r.events = {}), (g = r.handle) || (g = r.handle = function (b) { return typeof o !== U && o.event.triggered !== b.type ? o.event.dispatch.apply(a, arguments) : void 0 }), b = (b || \"\").match(E) || [\"\"], j = b.length; while (j--) h = Y.exec(b[j]) || [], n = q = h[1], p = (h[2] || \"\").split(\".\").sort(), n && (l = o.event.special[n] || {}, n = (e ? l.delegateType : l.bindType) || n, l = o.event.special[n] || {}, k = o.extend({ type: n, origType: q, data: d, handler: c, guid: c.guid, selector: e, needsContext: e && o.expr.match.needsContext.test(e), namespace: p.join(\".\") }, f), (m = i[n]) || (m = i[n] = [], m.delegateCount = 0, l.setup && l.setup.call(a, d, p, g) !== !1 || a.addEventListener && a.addEventListener(n, g, !1)), l.add && (l.add.call(a, k), k.handler.guid || (k.handler.guid = c.guid)), e ? m.splice(m.delegateCount++, 0, k) : m.push(k), o.event.global[n] = !0) } }, remove: function (a, b, c, d, e) { var f, g, h, i, j, k, l, m, n, p, q, r = L.hasData(a) && L.get(a); if (r && (i = r.events)) { b = (b || \"\").match(E) || [\"\"], j = b.length; while (j--) if (h = Y.exec(b[j]) || [], n = q = h[1], p = (h[2] || \"\").split(\".\").sort(), n) { l = o.event.special[n] || {}, n = (d ? l.delegateType : l.bindType) || n, m = i[n] || [], h = h[2] && new RegExp(\"(^|\\\\.)\" + p.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\"), g = f = m.length; while (f--) k = m[f], !e && q !== k.origType || c && c.guid !== k.guid || h && !h.test(k.namespace) || d && d !== k.selector && (\"**\" !== d || !k.selector) || (m.splice(f, 1), k.selector && m.delegateCount--, l.remove && l.remove.call(a, k)); g && !m.length && (l.teardown && l.teardown.call(a, p, r.handle) !== !1 || o.removeEvent(a, n, r.handle), delete i[n]) } else for (n in i) o.event.remove(a, n + b[j], c, d, !0); o.isEmptyObject(i) && (delete r.handle, L.remove(a, \"events\")) } }, trigger: function (b, c, d, e) { var f, g, h, i, k, l, n, p = [d || m], q = j.call(b, \"type\") ? b.type : b, r = j.call(b, \"namespace\") ? b.namespace.split(\".\") : []; if (g = h = d = d || m, 3 !== d.nodeType && 8 !== d.nodeType && !X.test(q + o.event.triggered) && (q.indexOf(\".\") >= 0 && (r = q.split(\".\"), q = r.shift(), r.sort()), k = q.indexOf(\":\") < 0 && \"on\" + q, b = b[o.expando] ? b : new o.Event(q, \"object\" == typeof b && b), b.isTrigger = e ? 2 : 3, b.namespace = r.join(\".\"), b.namespace_re = b.namespace ? new RegExp(\"(^|\\\\.)\" + r.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null, b.result = void 0, b.target || (b.target = d), c = null == c ? [b] : o.makeArray(c, [b]), n = o.event.special[q] || {}, e || !n.trigger || n.trigger.apply(d, c) !== !1)) { if (!e && !n.noBubble && !o.isWindow(d)) { for (i = n.delegateType || q, X.test(i + q) || (g = g.parentNode); g; g = g.parentNode)p.push(g), h = g; h === (d.ownerDocument || m) && p.push(h.defaultView || h.parentWindow || a) } f = 0; while ((g = p[f++]) && !b.isPropagationStopped()) b.type = f > 1 ? i : n.bindType || q, l = (L.get(g, \"events\") || {})[b.type] && L.get(g, \"handle\"), l && l.apply(g, c), l = k && g[k], l && l.apply && o.acceptData(g) && (b.result = l.apply(g, c), b.result === !1 && b.preventDefault()); return b.type = q, e || b.isDefaultPrevented() || n._default && n._default.apply(p.pop(), c) !== !1 || !o.acceptData(d) || k && o.isFunction(d[q]) && !o.isWindow(d) && (h = d[k], h && (d[k] = null), o.event.triggered = q, d[q](), o.event.triggered = void 0, h && (d[k] = h)), b.result } }, dispatch: function (a) { a = o.event.fix(a); var b, c, e, f, g, h = [], i = d.call(arguments), j = (L.get(this, \"events\") || {})[a.type] || [], k = o.event.special[a.type] || {}; if (i[0] = a, a.delegateTarget = this, !k.preDispatch || k.preDispatch.call(this, a) !== !1) { h = o.event.handlers.call(this, a, j), b = 0; while ((f = h[b++]) && !a.isPropagationStopped()) { a.currentTarget = f.elem, c = 0; while ((g = f.handlers[c++]) && !a.isImmediatePropagationStopped()) (!a.namespace_re || a.namespace_re.test(g.namespace)) && (a.handleObj = g, a.data = g.data, e = ((o.event.special[g.origType] || {}).handle || g.handler).apply(f.elem, i), void 0 !== e && (a.result = e) === !1 && (a.preventDefault(), a.stopPropagation())) } return k.postDispatch && k.postDispatch.call(this, a), a.result } }, handlers: function (a, b) { var c, d, e, f, g = [], h = b.delegateCount, i = a.target; if (h && i.nodeType && (!a.button || \"click\" !== a.type)) for (; i !== this; i = i.parentNode || this)if (i.disabled !== !0 || \"click\" !== a.type) { for (d = [], c = 0; h > c; c++)f = b[c], e = f.selector + \" \", void 0 === d[e] && (d[e] = f.needsContext ? o(e, this).index(i) >= 0 : o.find(e, this, null, [i]).length), d[e] && d.push(f); d.length && g.push({ elem: i, handlers: d }) } return h < b.length && g.push({ elem: this, handlers: b.slice(h) }), g }, props: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"), fixHooks: {}, keyHooks: { props: \"char charCode key keyCode\".split(\" \"), filter: function (a, b) { return null == a.which && (a.which = null != b.charCode ? b.charCode : b.keyCode), a } }, mouseHooks: { props: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"), filter: function (a, b) { var c, d, e, f = b.button; return null == a.pageX && null != b.clientX && (c = a.target.ownerDocument || m, d = c.documentElement, e = c.body, a.pageX = b.clientX + (d && d.scrollLeft || e && e.scrollLeft || 0) - (d && d.clientLeft || e && e.clientLeft || 0), a.pageY = b.clientY + (d && d.scrollTop || e && e.scrollTop || 0) - (d && d.clientTop || e && e.clientTop || 0)), a.which || void 0 === f || (a.which = 1 & f ? 1 : 2 & f ? 3 : 4 & f ? 2 : 0), a } }, fix: function (a) { if (a[o.expando]) return a; var b, c, d, e = a.type, f = a, g = this.fixHooks[e]; g || (this.fixHooks[e] = g = W.test(e) ? this.mouseHooks : V.test(e) ? this.keyHooks : {}), d = g.props ? this.props.concat(g.props) : this.props, a = new o.Event(f), b = d.length; while (b--) c = d[b], a[c] = f[c]; return a.target || (a.target = m), 3 === a.target.nodeType && (a.target = a.target.parentNode), g.filter ? g.filter(a, f) : a }, special: { load: { noBubble: !0 }, focus: { trigger: function () { return this !== _() && this.focus ? (this.focus(), !1) : void 0 }, delegateType: \"focusin\" }, blur: { trigger: function () { return this === _() && this.blur ? (this.blur(), !1) : void 0 }, delegateType: \"focusout\" }, click: { trigger: function () { return \"checkbox\" === this.type && this.click && o.nodeName(this, \"input\") ? (this.click(), !1) : void 0 }, _default: function (a) { return o.nodeName(a.target, \"a\") } }, beforeunload: { postDispatch: function (a) { void 0 !== a.result && (a.originalEvent.returnValue = a.result) } } }, simulate: function (a, b, c, d) { var e = o.extend(new o.Event, c, { type: a, isSimulated: !0, originalEvent: {} }); d ? o.event.trigger(e, null, b) : o.event.dispatch.call(b, e), e.isDefaultPrevented() && c.preventDefault() } }, o.removeEvent = function (a, b, c) { a.removeEventListener && a.removeEventListener(b, c, !1) }, o.Event = function (a, b) { return this instanceof o.Event ? (a && a.type ? (this.originalEvent = a, this.type = a.type, this.isDefaultPrevented = a.defaultPrevented || void 0 === a.defaultPrevented && a.getPreventDefault && a.getPreventDefault() ? Z : $) : this.type = a, b && o.extend(this, b), this.timeStamp = a && a.timeStamp || o.now(), void (this[o.expando] = !0)) : new o.Event(a, b) }, o.Event.prototype = { isDefaultPrevented: $, isPropagationStopped: $, isImmediatePropagationStopped: $, preventDefault: function () { var a = this.originalEvent; this.isDefaultPrevented = Z, a && a.preventDefault && a.preventDefault() }, stopPropagation: function () { var a = this.originalEvent; this.isPropagationStopped = Z, a && a.stopPropagation && a.stopPropagation() }, stopImmediatePropagation: function () { this.isImmediatePropagationStopped = Z, this.stopPropagation() } }, o.each({ mouseenter: \"mouseover\", mouseleave: \"mouseout\" }, function (a, b) { o.event.special[a] = { delegateType: b, bindType: b, handle: function (a) { var c, d = this, e = a.relatedTarget, f = a.handleObj; return (!e || e !== d && !o.contains(d, e)) && (a.type = f.origType, c = f.handler.apply(this, arguments), a.type = b), c } } }), l.focusinBubbles || o.each({ focus: \"focusin\", blur: \"focusout\" }, function (a, b) { var c = function (a) { o.event.simulate(b, a.target, o.event.fix(a), !0) }; o.event.special[b] = { setup: function () { var d = this.ownerDocument || this, e = L.access(d, b); e || d.addEventListener(a, c, !0), L.access(d, b, (e || 0) + 1) }, teardown: function () { var d = this.ownerDocument || this, e = L.access(d, b) - 1; e ? L.access(d, b, e) : (d.removeEventListener(a, c, !0), L.remove(d, b)) } } }), o.fn.extend({ on: function (a, b, c, d, e) { var f, g; if (\"object\" == typeof a) { \"string\" != typeof b && (c = c || b, b = void 0); for (g in a) this.on(g, b, c, a[g], e); return this } if (null == c && null == d ? (d = b, c = b = void 0) : null == d && (\"string\" == typeof b ? (d = c, c = void 0) : (d = c, c = b, b = void 0)), d === !1) d = $; else if (!d) return this; return 1 === e && (f = d, d = function (a) { return o().off(a), f.apply(this, arguments) }, d.guid = f.guid || (f.guid = o.guid++)), this.each(function () { o.event.add(this, a, d, c, b) }) }, one: function (a, b, c, d) { return this.on(a, b, c, d, 1) }, off: function (a, b, c) { var d, e; if (a && a.preventDefault && a.handleObj) return d = a.handleObj, o(a.delegateTarget).off(d.namespace ? d.origType + \".\" + d.namespace : d.origType, d.selector, d.handler), this; if (\"object\" == typeof a) { for (e in a) this.off(e, b, a[e]); return this } return (b === !1 || \"function\" == typeof b) && (c = b, b = void 0), c === !1 && (c = $), this.each(function () { o.event.remove(this, a, c, b) }) }, trigger: function (a, b) { return this.each(function () { o.event.trigger(a, b, this) }) }, triggerHandler: function (a, b) { var c = this[0]; return c ? o.event.trigger(a, b, c, !0) : void 0 } }); var ab = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi, bb = /<([\\w:]+)/, cb = /<|&#?\\w+;/, db = /<(?:script|style|link)/i, eb = /checked\\s*(?:[^=]|=\\s*.checked.)/i, fb = /^$|\\/(?:java|ecma)script/i, gb = /^true\\/(.*)/, hb = /^\\s*\\s*$/g, ib = { option: [1, \"\"], thead: [1, \"\", \"
\"], col: [2, \"\", \"
\"], tr: [2, \"\", \"
\"], td: [3, \"\", \"
\"], _default: [0, \"\", \"\"] }; ib.optgroup = ib.option, ib.tbody = ib.tfoot = ib.colgroup = ib.caption = ib.thead, ib.th = ib.td; function jb(a, b) { return o.nodeName(a, \"table\") && o.nodeName(11 !== b.nodeType ? b : b.firstChild, \"tr\") ? a.getElementsByTagName(\"tbody\")[0] || a.appendChild(a.ownerDocument.createElement(\"tbody\")) : a } function kb(a) { return a.type = (null !== a.getAttribute(\"type\")) + \"/\" + a.type, a } function lb(a) { var b = gb.exec(a.type); return b ? a.type = b[1] : a.removeAttribute(\"type\"), a } function mb(a, b) { for (var c = 0, d = a.length; d > c; c++)L.set(a[c], \"globalEval\", !b || L.get(b[c], \"globalEval\")) } function nb(a, b) { var c, d, e, f, g, h, i, j; if (1 === b.nodeType) { if (L.hasData(a) && (f = L.access(a), g = L.set(b, f), j = f.events)) { delete g.handle, g.events = {}; for (e in j) for (c = 0, d = j[e].length; d > c; c++)o.event.add(b, e, j[e][c]) } M.hasData(a) && (h = M.access(a), i = o.extend({}, h), M.set(b, i)) } } function ob(a, b) { var c = a.getElementsByTagName ? a.getElementsByTagName(b || \"*\") : a.querySelectorAll ? a.querySelectorAll(b || \"*\") : []; return void 0 === b || b && o.nodeName(a, b) ? o.merge([a], c) : c } function pb(a, b) { var c = b.nodeName.toLowerCase(); \"input\" === c && T.test(a.type) ? b.checked = a.checked : (\"input\" === c || \"textarea\" === c) && (b.defaultValue = a.defaultValue) } o.extend({ clone: function (a, b, c) { var d, e, f, g, h = a.cloneNode(!0), i = o.contains(a.ownerDocument, a); if (!(l.noCloneChecked || 1 !== a.nodeType && 11 !== a.nodeType || o.isXMLDoc(a))) for (g = ob(h), f = ob(a), d = 0, e = f.length; e > d; d++)pb(f[d], g[d]); if (b) if (c) for (f = f || ob(a), g = g || ob(h), d = 0, e = f.length; e > d; d++)nb(f[d], g[d]); else nb(a, h); return g = ob(h, \"script\"), g.length > 0 && mb(g, !i && ob(a, \"script\")), h }, buildFragment: function (a, b, c, d) { for (var e, f, g, h, i, j, k = b.createDocumentFragment(), l = [], m = 0, n = a.length; n > m; m++)if (e = a[m], e || 0 === e) if (\"object\" === o.type(e)) o.merge(l, e.nodeType ? [e] : e); else if (cb.test(e)) { f = f || k.appendChild(b.createElement(\"div\")), g = (bb.exec(e) || [\"\", \"\"])[1].toLowerCase(), h = ib[g] || ib._default, f.innerHTML = h[1] + e.replace(ab, \"<$1>\") + h[2], j = h[0]; while (j--) f = f.lastChild; o.merge(l, f.childNodes), f = k.firstChild, f.textContent = \"\" } else l.push(b.createTextNode(e)); k.textContent = \"\", m = 0; while (e = l[m++]) if ((!d || -1 === o.inArray(e, d)) && (i = o.contains(e.ownerDocument, e), f = ob(k.appendChild(e), \"script\"), i && mb(f), c)) { j = 0; while (e = f[j++]) fb.test(e.type || \"\") && c.push(e) } return k }, cleanData: function (a) { for (var b, c, d, e, f, g, h = o.event.special, i = 0; void 0 !== (c = a[i]); i++) { if (o.acceptData(c) && (f = c[L.expando], f && (b = L.cache[f]))) { if (d = Object.keys(b.events || {}), d.length) for (g = 0; void 0 !== (e = d[g]); g++)h[e] ? o.event.remove(c, e) : o.removeEvent(c, e, b.handle); L.cache[f] && delete L.cache[f] } delete M.cache[c[M.expando]] } } }), o.fn.extend({ text: function (a) { return J(this, function (a) { return void 0 === a ? o.text(this) : this.empty().each(function () { (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) && (this.textContent = a) }) }, null, a, arguments.length) }, append: function () { return this.domManip(arguments, function (a) { if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { var b = jb(this, a); b.appendChild(a) } }) }, prepend: function () { return this.domManip(arguments, function (a) { if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { var b = jb(this, a); b.insertBefore(a, b.firstChild) } }) }, before: function () { return this.domManip(arguments, function (a) { this.parentNode && this.parentNode.insertBefore(a, this) }) }, after: function () { return this.domManip(arguments, function (a) { this.parentNode && this.parentNode.insertBefore(a, this.nextSibling) }) }, remove: function (a, b) { for (var c, d = a ? o.filter(a, this) : this, e = 0; null != (c = d[e]); e++)b || 1 !== c.nodeType || o.cleanData(ob(c)), c.parentNode && (b && o.contains(c.ownerDocument, c) && mb(ob(c, \"script\")), c.parentNode.removeChild(c)); return this }, empty: function () { for (var a, b = 0; null != (a = this[b]); b++)1 === a.nodeType && (o.cleanData(ob(a, !1)), a.textContent = \"\"); return this }, clone: function (a, b) { return a = null == a ? !1 : a, b = null == b ? a : b, this.map(function () { return o.clone(this, a, b) }) }, html: function (a) { return J(this, function (a) { var b = this[0] || {}, c = 0, d = this.length; if (void 0 === a && 1 === b.nodeType) return b.innerHTML; if (\"string\" == typeof a && !db.test(a) && !ib[(bb.exec(a) || [\"\", \"\"])[1].toLowerCase()]) { a = a.replace(ab, \"<$1>\"); try { for (; d > c; c++)b = this[c] || {}, 1 === b.nodeType && (o.cleanData(ob(b, !1)), b.innerHTML = a); b = 0 } catch (e) { } } b && this.empty().append(a) }, null, a, arguments.length) }, replaceWith: function () { var a = arguments[0]; return this.domManip(arguments, function (b) { a = this.parentNode, o.cleanData(ob(this)), a && a.replaceChild(b, this) }), a && (a.length || a.nodeType) ? this : this.remove() }, detach: function (a) { return this.remove(a, !0) }, domManip: function (a, b) { a = e.apply([], a); var c, d, f, g, h, i, j = 0, k = this.length, m = this, n = k - 1, p = a[0], q = o.isFunction(p); if (q || k > 1 && \"string\" == typeof p && !l.checkClone && eb.test(p)) return this.each(function (c) { var d = m.eq(c); q && (a[0] = p.call(this, c, d.html())), d.domManip(a, b) }); if (k && (c = o.buildFragment(a, this[0].ownerDocument, !1, this), d = c.firstChild, 1 === c.childNodes.length && (c = d), d)) { for (f = o.map(ob(c, \"script\"), kb), g = f.length; k > j; j++)h = c, j !== n && (h = o.clone(h, !0, !0), g && o.merge(f, ob(h, \"script\"))), b.call(this[j], h, j); if (g) for (i = f[f.length - 1].ownerDocument, o.map(f, lb), j = 0; g > j; j++)h = f[j], fb.test(h.type || \"\") && !L.access(h, \"globalEval\") && o.contains(i, h) && (h.src ? o._evalUrl && o._evalUrl(h.src) : o.globalEval(h.textContent.replace(hb, \"\"))) } return this } }), o.each({ appendTo: \"append\", prependTo: \"prepend\", insertBefore: \"before\", insertAfter: \"after\", replaceAll: \"replaceWith\" }, function (a, b) { o.fn[a] = function (a) { for (var c, d = [], e = o(a), g = e.length - 1, h = 0; g >= h; h++)c = h === g ? this : this.clone(!0), o(e[h])[b](c), f.apply(d, c.get()); return this.pushStack(d) } }); var qb, rb = {}; function sb(b, c) { var d = o(c.createElement(b)).appendTo(c.body), e = a.getDefaultComputedStyle ? a.getDefaultComputedStyle(d[0]).display : o.css(d[0], \"display\"); return d.detach(), e } function tb(a) { var b = m, c = rb[a]; return c || (c = sb(a, b), \"none\" !== c && c || (qb = (qb || o(\"