diff options
author | Hannu Nyman <hannu.nyman@iki.fi> | 2017-03-15 16:11:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-15 16:11:29 +0200 |
commit | a8465cffb89c3ee3c49e84d2ee88f7027e8ed4f9 (patch) | |
tree | 5cb2e93483718a21293c497475be6d69346eb3c5 | |
parent | 55ed62eab7577231247f85034b6855aa91abf534 (diff) | |
parent | d0cb158e34c20d0a78dc23cfd5757d10430e121f (diff) |
Merge pull request #1025 from danrl/cshark
luci-app-cshark: initial commit
4 files changed, 463 insertions, 0 deletions
diff --git a/applications/luci-app-cshark/Makefile b/applications/luci-app-cshark/Makefile new file mode 100644 index 000000000..40b0e9fb7 --- /dev/null +++ b/applications/luci-app-cshark/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2017 Dan Luedtke <mail@danrl.com> +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Cloudshark capture tool Web UI +LUCI_DEPENDS:=+cshark +LUCI_PKGARCH:=all + +PKG_MAINTAINER:=Luka Perkov <luka@openwrt.org> + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/applications/luci-app-cshark/luasrc/controller/cshark.lua b/applications/luci-app-cshark/luasrc/controller/cshark.lua new file mode 100644 index 000000000..4d9bbba29 --- /dev/null +++ b/applications/luci-app-cshark/luasrc/controller/cshark.lua @@ -0,0 +1,125 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright (C) 2014, QA Cafe, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +]]-- + +module("luci.controller.cshark", package.seeall) + +function index() + page = node("admin", "network", "cloudshark") + page.target = cbi("admin_network/cshark") + page.title = _("CloudShark") + page.order = 70 + + page = entry({"admin", "network", "cshark_iface_dump_start"}, call("cshark_iface_dump_start"), nil) + page.leaf = true + + page = entry({"admin", "network", "cshark_iface_dump_stop"}, call("cshark_iface_dump_stop"), nil) + page.leaf = true + + page = entry({"admin", "network", "cshark_check_status"}, call("cshark_check_status"), nil) + page.leaf = true + + page = entry({"admin", "network", "cshark_link_list_get"}, call("cshark_link_list_get"), nil) + page.leaf = true + + page = entry({"admin", "network", "cshark_link_list_clear"}, call("cshark_link_list_clear"), nil) + page.leaf = true +end + +function cshark_iface_dump_start(ifname, value, flag, filter) + if ifname == nil or ifname == '' then + ifname = 'any' + end + if tonumber(value) == nil + then + value = '0' + end + if filter == nil or filter == '' then + filter = '' + end + + if flag == nil or flag == '' then + filter = 'T' + end + + luci.http.prepare_content("text/plain") + + local res = os.execute("(/sbin/cshark -i " .. ifname .. " -" .. flag .. " " .. value .. " -p /tmp/cshark-luci.pid " .. filter .. " > /tmp/cshark-luci.out 2>&1) &") + luci.http.write(tostring(res)) +end + +function cshark_iface_dump_stop() + luci.http.prepare_content("text/plain") + + local f = io.open("/tmp/cshark-luci.pid", "rb") + local pid = f:read("*all") + io.close(f) + + local res = os.execute("kill -TERM " .. pid) + luci.http.write(tostring(res)) +end + +function cshark_check_status() + + local msg = ""; + local status; + local f = io.open("/tmp/cshark-luci.pid","r") + if f ~= nil then + status = 1; + io.close(f) + else + status = 0; + end + + f = io.open("/tmp/cshark-luci.out","r") + if f ~= nil then + msg = f:read("*all") + io.close(f) + if msg ~= '' then + os.remove('/tmp/cshark-luci.out') + end + end + + luci.http.prepare_content("application/json") + + local res = {} + res["status"] = status; + res["msg"] = msg; + + luci.http.write_json(res) +end + +function cshark_link_list_get() + local uci = require("uci").cursor() + + luci.http.prepare_content("application/json") + + luci.http.write("[") + + local t = uci:get("cshark", "cshark", "entry") + if (t ~= nil) then + for i = #t, 1, -1 do + luci.http.write("[\"" .. t[i] .. "\"],") + end + end + + luci.http.write("[]]") +end + +function cshark_link_list_clear() + local uci = require("uci").cursor() + + uci:delete("cshark", "cshark", "entry") + uci:commit("cshark"); + + luci.http.status(200, "OK") +end diff --git a/applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua b/applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua new file mode 100644 index 000000000..8db95596f --- /dev/null +++ b/applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua @@ -0,0 +1,30 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright (C) 2014, QA Cafe, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +local fs = require "nixio.fs" + +m = Map("cshark", translate("CloudShark")) + +if fs.access("/etc/config/cshark") then + m:section(SimpleSection).template = "cshark" + + s = m:section(TypedSection, "cshark", translate("Options")) + s.anonymous = true + s.addremove = false + + s:option(Value, "url", translate("CloudShark URL")) + s:option(Value, "token", translate("CloudShark API token")) +end + +return m diff --git a/applications/luci-app-cshark/luasrc/view/cshark.htm b/applications/luci-app-cshark/luasrc/view/cshark.htm new file mode 100644 index 000000000..bc67f806c --- /dev/null +++ b/applications/luci-app-cshark/luasrc/view/cshark.htm @@ -0,0 +1,291 @@ +<%# +LuCI - Lua Configuration Interface + +Copyright (C) 2014, QA Cafe, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<fieldset class="cbi-section"> + <legend><%:Start network capture%></legend> + <div class="cbi-section-node"> + <table class="cbi-section-table"> + <tr> + <th><%:Interface%></th> + <th colspan='2'><%:seconds, packets, bytes%></th> + <th><%:Filter%></th> + <th><%:Actions%></th> + </tr> + <tr> + <td> + <select title="<%:Interface%>" style="width:auto" id="s_interfaces"> + <% + local nixio = require "nixio" + for k, v in ipairs(nixio.getifaddrs()) do + if v.family == "packet" then + %> + <option value="<%=v.name%>"><%=v.name%> </option> + <% + end + end + %> + <option value="any"><%:any%></option> + </select> + </td> + <td colspan='2'> + <input id="tx_value" type="text" value="0" /> + <select title="<%:timeout, bytes, seconds%>" id="s_value_type" style="width:auto"> + <option value="T"><%:seconds%></option> + <option value="P"><%:packets%></option> + <option value="S"><%:bytes%></option> + </select> + </td> + <td> + <input style="margin: 5px 0" type="text" title="<%:Filter%>" placeholder="filter" id="i_filter" /> + </td> + <td> + <input type="button" id="bt_action" data-action="start" value="<%:Start capture%>" class="cbi-button" /> + </td> + </tr> + </table> + </div> +</fieldset> + +<fieldset class="cbi-section"> + <span id="cshark-rc-output"></span> +</fieldset> + +<hr/> + +<fieldset class="cbi-section"> + <legend><%:Capture links%></legend> + <div class="cbi-section-node"> + <table id="t_link_list" class="cbi-section-table"> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:Capture URL%></th> + <th class="cbi-section-table-cell"><%:Capture time%></th> + </tr> + </table> + </div> +</fieldset> + +<fieldset class="cbi-section"> + <a href="https://support.cloudshark.org/openwrt/openwrt-cloudshark.html" target="_blank">Visit support.cloudshark.org for help.</a> +</fieldset> + +<hr/> + +<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript">//<![CDATA[ + + var capture_running = 0; + var pid_file = 0; + var bt_action = document.getElementById('bt_action'); + var a_clear_links = document.getElementById('a_clear_links'); + var output = document.getElementById('cshark-rc-output'); + var loader = '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" width="16" height="16" style="vertical-align:middle" /> '; + var msg = { 'start' : '<%:Waiting for capture to complete...%>', 'stop' : '<%:Waiting for upload to complete...%>' }; + var status_msg = msg['start']; + + function get_date(timestamp) + { + function pad_str(str) + { + return (str < 10) ? "0" + str : str; + } + + var current_date = new Date(timestamp * 1000); + return current_date.getFullYear() + "-" + + pad_str(current_date.getMonth() + 1) + "-" + + pad_str(current_date.getDate()) + " " + + pad_str(current_date.getHours()) + ":" + + pad_str(current_date.getMinutes()) + ":" + + pad_str(current_date.getSeconds()); + } + + bt_action.onclick = function() + { + var action = this.getAttribute("data-action"); + var csxhr = new XHR(); + + if (action == "stop") + { + update_status(action); + + bt_action.disabled = true; + + csxhr.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_iface_dump_stop', null, + function(x) + { + if (!x || x.responseText.trim() != "0") + { + update_status("failed", "Invalid response on stop."); + } + }); + + } + else if (action == "start") + { + + var s_interfaces = document.getElementById('s_interfaces'); + var s_value_type = document.getElementById('s_value_type'); + var i_filter = document.getElementById('i_filter'); + + var if_n = s_interfaces.selectedIndex; + var t_n = s_value_type.selectedIndex; + var ifname = s_interfaces.options[if_n].value.trim(); + var filter_val = i_filter.value.trim(); + var tx_val = document.getElementById('tx_value').value.trim(); + var type_val = s_value_type.options[t_n].value.trim(); + + if (type_val != 'P' && type_val != 'T' && type_val != 'S') type_val = 'T'; + + if (!ifname || !type_val) return; + + if (isNaN(tx_val)) return alert("<%:value for [seconds, packets, bytes] must be Integer%>"); + + update_status(action); + + csxhr.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_iface_dump_start/' + ifname + '/' + tx_val + '/' + type_val + '/'+ filter_val, null, + function(x) + { + if (!x) + update_status("failed", "Invalid response on start."); + else + update_status("running"); + }); + } + } + + function update_status(status, message) + { + switch (status) + { + case 'start': + case 'stop': + status_msg = msg[status]; + output.innerHTML = loader + status_msg; + break + + case 'running': + if (capture_running) break;; + + output.innerHTML = loader + status_msg; + + bt_action.value = '<%:Stop capture%>'; + bt_action.setAttribute('data-action', 'stop'); + capture_running = 1; + break; + + case 'completed': + case 'failed': + if (!capture_running) break; + + if (status == "completed") + { + link_list_update(); + } + + output.innerHTML = "<pre>" + message + "</pre>"; + bt_action.value = '<%:Start capture%>'; + bt_action.setAttribute('data-action', 'start'); + bt_action.disabled = false; + capture_running = 0; + break; + } + } + + + function check_status() + { + + XHR.poll(3, '<%=luci.dispatcher.build_url("admin", "network")%>/cshark_check_status', null, + function(x, data) + { + if (!x) + { + if (capture_running) + update_status("failed", "Invalid response when fetching status."); + + return; + } + console.log(data) + + update_status( (data.status == 1) && "running" || "completed", data.msg); + }) + } + + function link_list_clear() + { + var csxhr_del = new XHR(); + csxhr_del.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_link_list_clear', null, + function(x) + { + if (!x) + return false; + + link_list_update(); + }); + } + + + function link_list_update() + { + var t_link = document.getElementById("t_link_list"); + if (!t_link) return; + + var row_count = t_link.rows.length; + while(--row_count) t_link.deleteRow(row_count); + + var cell = t_link.insertRow(-1).insertCell(0); + cell.colSpan = 2; + cell.innerHTML = loader; + + var csxhr_link = new XHR(); + csxhr_link.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_link_list_get', null, + function(x, entries) + { + var row = t_link.deleteRow(1); + + if (!x) return; + + if (!entries || !entries.length) + { + var cell = t_link.insertRow(-1).insertCell(0); + cell.colSpan = 2; + cell.innerHTML = '<em><br />There are no captures available yet.</em>'; + + return; + } + + for (var i = 0, len = entries.length; i < len ; i++) + { + var entry = entries[i][0]; + if (!entry) continue; + + var data = entry.split(","); + var url = data[0]; + var timestamp = data[1]; + + var row = t_link.insertRow(-1); + row.insertCell(0).innerHTML = '<a href="'+url+'" target="_blank">'+url+'</a>'; + row.insertCell(1).innerHTML = get_date(timestamp); + } + + var cell = t_link.insertRow(-1).insertCell(0); + cell.colSpan = 2; + cell.style.textAlign="center"; + cell.innerHTML = '<input type="button" onclick="link_list_clear()" class="cbi-button" value ="<%:Clear list%>" />'; + }) + } + + check_status(); + link_list_update(); +//]]></script> |