You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.4 KiB

# Version 4.0
#
from splunk.clilib import cli_common, control_api
from splunk.appserver import Util, Template, html, SearchFormatter, SearchAgent
import logging as logger
import os, traceback
from defusedxml.cElementTree import fromstring as safe_fromstring
def get(requestObject) :
requestArgs = _flattenRequestArgs(requestObject)
requestObject.setHeader('content-type', 'text/html')
t = _getTemplate("surrounding_events.html", requestArgs)
searchCommand = _getSearchCommand(requestArgs)
#tack the extra output clause back onto q
searchCommand += "| outputxml format::raw maxlines::10000"
requestArgs["q"] = searchCommand
# get the proper search agent
searchAgent = SearchAgent.Factory(requestArgs, requestObject.getSession())
# return the output from search agent
agentResponse = searchAgent.run()
if( searchAgent.messages ):
messagesBlock = html.HTMLList()
for message in searchAgent.messages:
messagesBlock.append( html.Raw( message["text"] ) )
messagesBlock.append( html.br() )
messagesBlock.append( html.br() )
t.messages = messagesBlock
else:
t.messages = html.Raw("")
parsedResponse = safe_fromstring(agentResponse)
eventsBlock = html.HTMLList()
cdIndex = ""
decIndex = ""
for rNode in parsedResponse.findall(".//cols"):
for cNode in rNode.findall(".//col"):
if cNode.text == "_decoration":
decIndex = cNode.attrib["cd"]
elif cNode.text == "_cd":
cdIndex = cNode.attrib["cd"]
for rNode in parsedResponse.findall(".//r") :
thisEventId = "0:0000000"
thisDecoration = ""
try :
for mNode in rNode.findall(".//m") :
if mNode.attrib["col"] == cdIndex :
thisEventId = mNode.text
elif mNode.attrib["col"] == decIndex :
thisDecoration = mNode.text
except Exception as e:
logger.debug("could not get thisEventId")
traceback.print_exc()
for vNode in rNode.findall(".//v") :
logger.debug("****" * 20)
logger.debug(vNode.text)
preElement = html.pre()[vNode.text]
# the class is needed for the CSS highlighting, but an ID is also used by the JS, for the scroll-to behaviour.
thisClass = "resultRow " + thisDecoration
thisId = ""
if (thisEventId == requestArgs["eventId"]) :
thisClass += " selectedRow"
thisId = "selectedItem"
innerDiv = html.div(class_=thisClass, id="events" + thisEventId)[preElement]
resultRowDiv = html.div(id=thisId)[innerDiv]
eventsBlock.append(resultRowDiv)
t.events = eventsBlock
if "server" not in requestArgs:
t.server = ""
t.run(requestObject)
return ""
def export(requestObject) :
requestArgs = _flattenRequestArgs(requestObject)
searchCommand = _getSearchCommand(requestArgs)
requestObject.setHeader("Content-type", "text/plain")
requestObject.setHeader("Content-disposition", "attachment; filename=source.txt;")
#tack the extra output clause back onto q
searchCommand += "| outputtext"
requestArgs["q"] = searchCommand
# get the proper search agent
searchAgent = SearchAgent.Factory(requestArgs, requestObject.getSession())
# return the output from search agent
agentResponse = searchAgent.run()
parsedResponse = safe_fromstring(agentResponse)
try :
resultsNode = parsedResponse.findall(".//results")[0]
return resultsNode.text
except Exception as e:
logger.error("Show source did not return expected results. ")
return agentResponse
##################
# Internal functions that arent intended to be accessed via the endpoints.
##################
def _getTemplate(fileNameStr,requestArgs) :
path = [os.environ["SPLUNK_HOME"]]
path.append("share/splunk")
try :
frontEndName = cli_common.confSettings["web"]["settings"]
if not frontend_name: frontend_name = 'oxiclean'
except Exception as e:
frontend_name = 'oxiclean'
frontend_dirname = 'search_' + frontend_name
path.append(frontend_dirname);
path.append('static/html')
path.append(fileNameStr)
t = Template.Template("/".join(path))
for key in requestArgs :
t.__setattr__(key, requestArgs[key])
return t
def _getSearchCommand(requestArgs) :
searchCommand = ["|"]
remote = False
if "server" in requestArgs:
remote = True
searchCommand.append( "remote " + requestArgs["server"] + " [ ");
searchCommand.append("surrounding")
searchCommand.append("id::" + requestArgs["eventId"])
searchCommand.append("index::" + requestArgs["eventIndex"])
searchCommand.append("searchkeys=\"" + requestArgs["q"] + "\"")
searchCommand.append("readlevel::2")
searchCommand.append("maxresults::" + requestArgs["num"])
searchCommand.append("timeBefore::60")
searchCommand.append("timeAfter::60")
if( remote ):
searchCommand.append( " ]" )
return " ".join(searchCommand)
def _flattenRequestArgs(requestObject) :
# generate flattened request args dict
requestArgs = {}
for key in requestObject.args:
requestArgs[key] = requestObject.args[key][0]
return requestArgs