Beispiel #1
0
def Grph2HtmlJinja(theCgi, topUrl, error_msg, isSubServer, gblCgiEnvList):
    this_dir = os.path.dirname(os.path.abspath(__file__))
    template_file_name = "www/export_html.template.htm"

    # The current URL is used to calculate the base href.
    current_uri = lib_util.RequestUri()

    parsed_url = lib_util.survol_urlparse(current_uri)
    path_url = parsed_url.path

    # Something like "/survol" or "survol/sources_types"
    url_dir = os.path.dirname(path_url)

    num_slashes = len(url_dir.split("/")) - 2
    base_href = ("../" * num_slashes) + "www/"

    # Create the jinja2 environment.
    # Notice the use of trim_blocks, which greatly helps control whitespace.
    jinja2 = lib_util.GetJinja2()
    jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(this_dir),
                                   trim_blocks=True)
    jinja_template = jinja_env.get_template(template_file_name)

    script_information_html = "".join(
        _script_information_html_iterator(theCgi, gblCgiEnvList))
    object_information_html = "".join(
        _object_information_html_iterator(theCgi))

    errors_table_html = "".join(_write_errors_no_jinja(error_msg, isSubServer))

    dictClassSubjPropObj = _create_objects_list(theCgi.m_graph)

    all_objects_list = []
    for (urlClass_with_mode, entity_graphic_class, colorClass,
         dictSubjPropObj) in _objects_triplets(dictClassSubjPropObj):
        one_class_html = "".join(
            _display_class_objects_no_jinja(dictSubjPropObj))
        all_objects_list.append((urlClass_with_mode, entity_graphic_class,
                                 colorClass, one_class_html))

    parameters_edition_html = "".join(
        _parameters_edition_html_iterator(theCgi))

    scripts_tree_html = "".join(_scripts_tree_html_iterator(theCgi))

    list_other_urls = _other_urls(topUrl)
    html_cim_urls = "".join(_cim_urls_html_iterator())

    jinja_render = jinja_template.render(
        base_href=base_href,
        page_title=theCgi.m_page_title,
        script_information=script_information_html,
        object_information=object_information_html,
        errors_table_html=errors_table_html,
        all_objects_list=all_objects_list,
        parameters_edition_html=parameters_edition_html,
        scripts_tree_html=scripts_tree_html,
        list_other_urls=list(list_other_urls),
        html_cim_urls=html_cim_urls)
    WrtAsUtf(jinja_render)
Beispiel #2
0
def _script_information_html_iterator(theCgi, gblCgiEnvList):
    """
        This displays general information about this script and the object if there is one.
    """
    logging.debug("_script_information_html_iterator entity_type=%s",
                  theCgi.m_entity_type)

    # This is already called in lib_common, when creating ScriptEnvironment.
    # It does not matter because this is very fast.
    calling_url = lib_util.RequestUri()
    entity_label, entity_graphic_class, entity_id = lib_naming.ParseEntityUri(
        calling_url, long_display=True)
    logging.debug("entity_label=%s entity_graphic_class=%s entity_id=%s",
                  entity_label, entity_graphic_class, entity_id)

    yield '<table border="0">'
    if len(gblCgiEnvList):
        logging.debug("gblCgiEnvList=%s", str(gblCgiEnvList))
        # This step is dedicated to the merging of several scripts.

        yield (
            "<tr align=left><td colspan=2 align=left><h2>Fusion of data from %d scripts</h2></td></tr>"
            % len(gblCgiEnvList))
        for aCgiEnv in gblCgiEnvList:
            page_title_first, page_title_rest = aCgiEnv.m_page_title, aCgiEnv.m_page_subtitle
            yield ("<tr><td><a href='%s'>%s</td><td><i>%s</i></td></tr>" %
                   (aCgiEnv.m_calling_url, page_title_first, page_title_rest))
    else:
        (page_title_first,
         page_title_rest) = theCgi.m_page_title, theCgi.m_page_subtitle
        yield "<tr><td colspan=2><h2>%s</h2></td></tr>" % page_title_first
        if page_title_rest:
            yield "<tr><td colspan=2>%s</td></tr>" % page_title_rest

    yield '</table>'
Beispiel #3
0
def _cim_urls_html_iterator():
    def w_map_to_html(the_map):
        """This callback receives a RDF property (WBEM or WMI) and a map
        which represents the CIM links associated to the current object. """
        logging.debug("w_map_to_html len=%d", len(the_map))
        for url_subj in the_map:
            unquoted_subj = lib_util.urllib_unquote(url_subj)
            subj_text, subj_entity_graph_class, subj_entity_id = lib_naming.ParseEntityUri(
                unquoted_subj)
            yield "<tr>"
            yield "<td valign='top'><a href='%s'>%s</a></td>" % (str(url_subj),
                                                                 subj_text)
            yield "<td>"
            yield "<table border=0>"
            for the_prop, url_obj in the_map[url_subj]:
                yield "<tr>"
                prop_nam = lib_exports.PropToShortPropNam(the_prop)
                yield "<td><i>%s</i></td>" % prop_nam
                if lib_kbase.IsLiteral(url_obj):
                    yield "<td>%s</td>" % str(url_obj)
                else:
                    unquoted_obj = lib_util.urllib_unquote(url_obj)
                    obj_text, obj_entity_graph_class, obj_entity_id = lib_naming.ParseEntityUri(
                        unquoted_obj)
                    yield "<td><a href='%s'>%s</a></td>" % (str(url_obj),
                                                            obj_text)
                yield "</tr>"
            yield "</table>"
            yield "</td>"
        yield "</tr>"

    calling_url = lib_util.RequestUri()
    entity_label, entity_type, entity_id = lib_naming.ParseEntityUri(
        calling_url, long_display=True)
    host_wbem_wmi = lib_util.currentHostname
    name_space = ""

    map_wbem = CIM_ComputerSystem.AddWbemServers(host_wbem_wmi, name_space,
                                                 entity_type, entity_id)
    for lin_html in w_map_to_html(map_wbem):
        yield lin_html
    map_wmi = CIM_ComputerSystem.AddWmiServers(host_wbem_wmi, name_space,
                                               entity_type, entity_id)
    for lin_html in w_map_to_html(map_wmi):
        yield lin_html
    map_survol = CIM_ComputerSystem.AddSurvolServers(host_wbem_wmi, name_space,
                                                     entity_type, entity_id)
    for lin_html in w_map_to_html(map_survol):
        yield lin_html
Beispiel #4
0
def _cim_urls_html_iterator():
    # This callback receives a RDF property (WBEM or WMI) and a map
    # which represents the CIM links associated to the current object.
    def WMapToHtml(theMap):
        DEBUG("WMapToHtml len=%d", len(theMap))
        for urlSubj in theMap:
            (subjText, subjEntityGraphClass,
             subjEntityId) = lib_naming.ParseEntityUri(
                 lib_util.urllib_unquote(urlSubj))
            yield ("<tr>")
            yield ("<td valign='top'><a href='%s'>%s</a></td>" %
                   (str(urlSubj), subjText))
            yield ("<td>")
            yield ("<table border=0>")
            for theProp, urlObj in theMap[urlSubj]:
                yield ("<tr>")
                propNam = lib_exports.PropToShortPropNam(theProp)
                yield ("<td><i>%s</i></td>" % propNam)
                if lib_kbase.IsLiteral(urlObj):
                    yield ("<td>%s</td>" % (str(urlObj)))
                else:
                    (objText, objEntityGraphClass,
                     objEntityId) = lib_naming.ParseEntityUri(
                         lib_util.urllib_unquote(urlObj))
                    yield ("<td><a href='%s'>%s</a></td>" %
                           (str(urlObj), objText))
                yield ("</tr>")
            yield ("</table>")
            yield ("</td>")
        yield ("</tr>")

    callingUrl = lib_util.RequestUri()
    (entity_label, entity_type,
     entity_id) = lib_naming.ParseEntityUri(callingUrl, longDisplay=True)
    host_wbem_wmi = lib_util.currentHostname
    nameSpace = ""

    mapWbem = CIM_ComputerSystem.AddWbemServers(host_wbem_wmi, nameSpace,
                                                entity_type, entity_id)
    for linHtml in WMapToHtml(mapWbem):
        yield linHtml
    mapWmi = CIM_ComputerSystem.AddWmiServers(host_wbem_wmi, nameSpace,
                                              entity_type, entity_id)
    for linHtml in WMapToHtml(mapWmi):
        yield linHtml
    mapSurvol = CIM_ComputerSystem.AddSurvolServers(host_wbem_wmi, nameSpace,
                                                    entity_type, entity_id)
    for linHtml in WMapToHtml(mapSurvol):
        yield linHtml
Beispiel #5
0
def ErrorMessageHtml(message):
    """
    This is called by CGI scripts to leave with an error message.
    At this stage, the CGI scripts did not write anything to stdout.
    Therefore, it is possible to return any MIME document.
    The challenge is to return an error message in the expected output format: html, json, rdf etc...
    """
    exc_stack = traceback.format_exc()
    for one_line in exc_stack.split("\n"):
        logging.error("Exception line: %s", one_line)

    if globalErrorMessageEnabled:
        logging.error("ErrorMessageHtml %s. Exiting.", message)
        try:
            # Use RequestUri() instead of "REQUEST_URI", because this CGI environment variable
            # is not set in minimal HTTP servers such as CGIHTTPServer.
            request_uri = lib_util.RequestUri()
            url_mode = lib_util.get_url_mode(request_uri)
            logging.error("request_uri=%s url_mode=%s" % (request_uri, url_mode))
            if url_mode == "json":
                # If we are in Json mode, this returns a special json document with the error message.
                lib_export_json.write_json_error(message)
                sys.exit(0)
            if url_mode == "rdf":
                # If we are in Json mode, this returns a special RDF document with the error message.
                lib_export_ontology.WriteRdfError(message, request_uri)
                sys.exit(0)
        except KeyError:
            pass

        lib_util.InfoMessageHtml(message)

        if _is_wsgi():
            # WSGI server is persistent and should not exit.
            raise RuntimeError("WSGI server should not exit")
        else:
            sys.exit(0)
    else:
        # Instead of exiting, it throws an exception which can be used by merge_scripts.py
        logging.debug("ErrorMessageHtml DISABLED")
        # It might be displayed in a HTML document.
        message_clean = lib_util.html_escape(message)
        raise Exception("ErrorMessageHtml raised:%s" % message_clean)
Beispiel #6
0
def _script_information_html_iterator(theCgi, gblCgiEnvList):
    """
        This displays general information about this script and the object if there is one.
    """
    DEBUG("_script_information_html_iterator entity_type=%s",
          theCgi.m_entity_type)

    # This is already called in lib_common, when creating CgiEnv.
    # It does not matter because this is very fast.
    callingUrl = lib_util.RequestUri()
    (entity_label, entity_graphic_class,
     entity_id) = lib_naming.ParseEntityUri(callingUrl, longDisplay=True)
    DEBUG("entity_label=%s entity_graphic_class=%s entity_id=%s", entity_label,
          entity_graphic_class, entity_id)

    # WrtAsUtf('<table class="list_of_merged_scripts">')
    yield ('<table border="0">')
    if len(gblCgiEnvList):
        DEBUG("gblCgiEnvList=%s", str(gblCgiEnvList))
        # This step is dedicated to the merging of several scripts.

        yield (
            "<tr align=left><td colspan=2 align=left><h2>Fusion of data from %d scripts</h2></td></tr>"
            % len(gblCgiEnvList))
        for aCgiEnv in gblCgiEnvList:
            DEBUG("aCgiEnv=%s", str(aCgiEnv))
            DEBUG("aCgiEnv.m_page_title=%s", str(aCgiEnv.m_page_title))
            DEBUG("aCgiEnv.m_calling_url=%s", str(aCgiEnv.m_calling_url))
            #(page_title_first,page_title_rest) = lib_util.SplitTextTitleRest(aCgiEnv.m_page_title)
            page_title_first, page_title_rest = aCgiEnv.m_page_title, aCgiEnv.m_page_subtitle
            yield ("<tr><td><a href='%s'>%s</td><td><i>%s</i></td></tr>" %
                   (aCgiEnv.m_calling_url, page_title_first, page_title_rest))
    else:
        # (page_title_first,page_title_rest) = lib_util.SplitTextTitleRest(theCgi.m_page_title)
        (page_title_first,
         page_title_rest) = theCgi.m_page_title, theCgi.m_page_subtitle
        yield ("<tr><td colspan=2><h2>%s</h2></td></tr>" % (page_title_first))
        if page_title_rest:
            yield ("<tr><td colspan=2>%s</td></tr>" % (page_title_rest))

    yield ('</table>')
Beispiel #7
0
def WriteScriptInformation(theCgi, gblCgiEnvList):
    """
		This displays general information about this script and the object if there is one.
	"""
    sys.stderr.write("WriteScriptInformation entity_type=%s\n" %
                     (theCgi.m_entity_type))

    # This is already called in lib_common, when creating CgiEnv.
    # It does not matter because this is very fast.
    callingUrl = lib_util.RequestUri()
    (entity_label, entity_graphic_class,
     entity_id) = lib_naming.ParseEntityUri(callingUrl, longDisplay=True)
    sys.stderr.write("entity_label=%s entity_graphic_class=%s entity_id=%s\n" %
                     (entity_label, entity_graphic_class, entity_id))

    # WrtAsUtf('<table class="list_of_merged_scripts">')
    WrtAsUtf('<table border="0">')
    if len(gblCgiEnvList):
        sys.stderr.write("gblCgiEnvList=%s\n" % str(gblCgiEnvList))
        # This step is dedicated to the merging of several scripts.

        WrtAsUtf(
            "<tr align=left><td colspan=2 align=left><h2>Fusion of data from %d scripts</h2></td></tr>"
            % len(gblCgiEnvList))
        for aCgiEnv in gblCgiEnvList:
            sys.stderr.write("aCgiEnv=%s\n" % str(aCgiEnv))
            sys.stderr.write("aCgiEnv.m_page_title=%s\n" %
                             str(aCgiEnv.m_page_title))
            sys.stderr.write("aCgiEnv.m_calling_url=%s\n" %
                             str(aCgiEnv.m_calling_url))
            (page_title_first, page_title_rest) = lib_util.SplitTextTitleRest(
                aCgiEnv.m_page_title)
            WrtAsUtf(
                "<tr><td><a href='%s'>%s</td><td><i>%s</i></td></tr>" %
                (aCgiEnv.m_calling_url, page_title_first, page_title_rest))

    else:
        (page_title_first,
         page_title_rest) = lib_util.SplitTextTitleRest(theCgi.m_page_title)
        WrtAsUtf("<tr><td colspan=2><h2>%s</h2></td></tr>" %
                 (page_title_first))
        if page_title_rest:
            WrtAsUtf("<tr><td colspan=2>%s</td></tr>" % (page_title_rest))

    WrtAsUtf('</table>')

    if theCgi.m_entity_type:
        # WrtAsUtf('m_entity_id: %s<br>'%(theCgi.m_entity_id))

        WrtAsUtf('<table class="table_script_information">')

        entity_module = lib_util.GetEntityModule(theCgi.m_entity_type)
        entDoc = entity_module.__doc__
        if not entDoc:
            entDoc = ""

        urlClass = lib_util.EntityClassUrl(theCgi.m_entity_type)
        urlClass_with_mode = UrlInHtmlMode(urlClass)
        WrtAsUtf("""
		<tr>
			<td><a href='%s'>%s</a></td>
			<td>%s</td>
		</tr>
		""" % (urlClass_with_mode, theCgi.m_entity_type, entDoc))

        for keyProp in theCgi.m_entity_id_dict:
            keyVal = theCgi.m_entity_id_dict[keyProp]

            WrtAsUtf("""
			<tr>
				<td>%s</td>
				<td>%s</td>
			</tr>
			""" % (keyProp, keyVal))

        WrtAsUtf('</table>')
Beispiel #8
0
def WriteOtherUrls(topUrl):
    """
		This displays the URL to view the same document, in other ouput formats.
	"""

    WrtAsUtf('<table class="other_urls">')

    if topUrl:
        topUrl_with_mode = UrlInHtmlMode(topUrl)
        WrtAsUtf("""
		<tr><td align="left" colspan="2"><a href="%s"><b>Home</b></a></td></tr>
		""" % topUrl_with_mode)

    # Because Graphviz is not available on OVH platform.
    if not lib_util.modeOVH:
        WrtAsUtf("""
		<tr>
			<td class="other_urls"><a href="%s">SVG format</a></td>
			<td>Graphviz&trade; generated</td>
		</tr>
		""" % lib_exports.ModedUrl("svg"))

    WrtAsUtf("""
	<tr>
		<td class="other_urls"><a href="%s">RDF format</a></td>
		<td>Semantic Web, OWL standard / Prot&eacute;g&eacute;&trade;...</td>
	</tr>
	""" % lib_exports.ModedUrl("rdf"))

    urlD3 = lib_exports.UrlToMergeD3()

    WrtAsUtf("""
	<tr>
		<td class="other_urls"><a href="%s">D3</a></td>
		<td>Javascript D3 library</td>
	</tr>
	""" % urlD3)

    host_wbem_wmi = lib_util.currentHostname

    # This callback receives a RDF property (WBEM or WMI) and a map
    # which represents the CIM links associated to the current object.
    def WMapToHtml(theMap, propData):
        sys.stderr.write("WMapToHtml len=%d\n" % len(theMap))
        for urlSubj in theMap:
            (subjText, subjEntityGraphClass,
             subjEntityId) = lib_naming.ParseEntityUri(
                 lib_util.urllib_unquote(urlSubj))
            WrtAsUtf("<tr>")
            WrtAsUtf("<td valign='top'><a href='%s'>%s</a></td>" %
                     (str(urlSubj), subjText))
            WrtAsUtf("<td>")
            WrtAsUtf("<table>")
            for theProp, urlObj in theMap[urlSubj]:
                WrtAsUtf("<tr>")
                propNam = lib_exports.PropToShortPropNam(theProp)
                WrtAsUtf("<td><i>%s</i></td>" % propNam)
                if lib_kbase.IsLiteral(urlObj):
                    WrtAsUtf("<td>%s</td>" % (str(urlObj)))
                else:
                    (objText, objEntityGraphClass,
                     objEntityId) = lib_naming.ParseEntityUri(
                         lib_util.urllib_unquote(urlObj))
                    WrtAsUtf("<td><a href='%s'>%s</a></td>" %
                             (str(urlObj), objText))
                WrtAsUtf("</tr>")
            WrtAsUtf("</table>")
            WrtAsUtf("</td>")
        WrtAsUtf("</tr>")

    callingUrl = lib_util.RequestUri()
    (entity_label, entity_type,
     entity_id) = lib_naming.ParseEntityUri(callingUrl, longDisplay=True)
    nameSpace = ""

    mapWbem = CIM_ComputerSystem.AddWbemServers(host_wbem_wmi, nameSpace,
                                                entity_type, entity_id)
    WMapToHtml(mapWbem, pc.property_wbem_data)
    mapWmi = CIM_ComputerSystem.AddWmiServers(host_wbem_wmi, nameSpace,
                                              entity_type, entity_id)
    WMapToHtml(mapWmi, pc.property_wmi_data)
    mapSurvol = CIM_ComputerSystem.AddSurvolServers(host_wbem_wmi, nameSpace,
                                                    entity_type, entity_id)
    WMapToHtml(mapSurvol, pc.property_survol_agent)

    WrtAsUtf('</table>')
Beispiel #9
0
	def __init__(self, parameters = {}, can_process_remote = False ):
		# TODO: This value is read again in OutCgiRdf, we could save time by making this object global.
		sys.stderr.write( "CgiEnv parameters=%s\n" % ( str(parameters) ) )

		# TODO: When running from cgiserver.py, and if QUERY_STRING is finished by a dot ".", this dot
		# TODO: is removed. Workaround: Any CGI variable added after.
		# TODO: Also: Several slashes "/" are merged into one.
		# TODO: Example: "xid=http://192.168.1.83:5988/." becomes "xid=http:/192.168.1.83:5988/"
		# TODO: ... or "xx.py?xid=smbshr.Id=////WDMyCloudMirror///rchateau" become "xx.py?xid=smbshr.Id=/WDMyCloudMirror/rchateau"
		# TODO: Replace by "xid=http:%2F%2F192.168.1.83:5988/."
		# Maybe a bad collapsing of URL ?
		# sys.stderr.write("QUERY_STRING=%s\n" % os.environ['QUERY_STRING'] )
		mode = lib_util.GuessDisplayMode()

		# Contains the optional arguments, needed by calling scripts.
		self.m_parameters = parameters

		self.m_parameterized_links = dict()


		# When in merge mode, the display parameters must be stored in a place accessible by the graph.

		docModuAll = GetCallingModuleDoc()

		# Take only the first non-empty line. See lib_util.FromModuleToDoc()
		docModuSplit = docModuAll.split("\n")
		self.m_page_title = docModuSplit[0]

		# Title page contains __doc__ plus object label.
		callingUrl = lib_util.RequestUri()
		self.m_calling_url = callingUrl
		sys.stderr.write("CgiEnv m_page_title=%s m_calling_url=%s\n"%(self.m_page_title,self.m_calling_url))
		parsedEntityUri = lib_naming.ParseEntityUri(callingUrl,longDisplay=False,force_entity_ip_addr=None)
		if parsedEntityUri[2]:
			# If there is an object to display.
			# Practically, we are in the script "entity.py" and the single doc string is "Overview"
			fullTitle = parsedEntityUri[0]
			self.m_page_title += " " + fullTitle

			# We assume there is an object, and therefore a class and its description.
			entity_class = parsedEntityUri[1]

			# Similar code in objtypes.py
			entity_module = lib_util.GetEntityModule(entity_class)
			entDoc = entity_module.__doc__
			# The convention is the first line treated as a title.
			if entDoc:
				self.m_page_title += "\n" + entDoc

		# If we can talk to a remote host to get the desired values.

		# Global CanProcessRemote has precedence over parameter can_process_remote
		# whcih should probably be deprecated, although they do not have exactly the same role:
		# * Global CanProcessRemote is used by entity.py to display scripts which have this capability.
		# * Parameter can_process_remote is used to inform, at execution time, of this capability.
		# Many scripts are not enumerated by entity.py so a global CanProcessRemote is not necessary.
		# For clarity, it might be fine to replace the parameter can_process_remote by the global value.
		# There cannot be nasty consequences except that some scripts might not be displayed
		# when they should be, and vice-versa.
		try:
			globalCanProcessRemote = globals()["CanProcessRemote"]
		except KeyError:
			globalCanProcessRemote = False

		if can_process_remote != globalCanProcessRemote:
			# sys.stderr.write("INCONSISTENCY CanProcessRemote\n") # ... which is not an issue.
			can_process_remote = True

		self.m_can_process_remote = can_process_remote

		self.m_arguments = cgi.FieldStorage()

		(self.m_entity_type,self.m_entity_id,self.m_entity_host) = self.GetXid()
		sys.stderr.write("CgiEnv m_entity_type=%s m_entity_id=%s m_entity_host=%s\n"%(self.m_entity_type,self.m_entity_id,self.m_entity_host))
		self.m_entity_id_dict = lib_util.SplitMoniker(self.m_entity_id)

		# Depending on the caller module, maybe the arguments should be 64decoded. See "sql/query".
		# As the entity type is available, it is possible to import it and check if it encodes it arguments.
		# See presence of source_types.sql.query.DecodeCgiArg(keyWord,cgiArg) for example.

		# This is probably too generous to indicate a local host.
		self.TestRemoteIfPossible(can_process_remote)

		# TODO: HOW WILL WE RESTORE THE ORIGINAL DISPLAY MODE ?
		if mode == "edit":
			self.EditionMode()
Beispiel #10
0
# This is a technical script used only for testing.
# It depends only on low-level libraries and returns their internal results
# which cannot not normally be printed clearly.
# BEWARE: This does not work with WSGI.

import json
import sys

import lib_util

internal_data = {
    "uriRoot": lib_util.uriRoot,
    "HttpPrefix": lib_util.HttpPrefix(),
    "RootUri": lib_util.RootUri(),
    "RequestUri": lib_util.RequestUri()
}
json_data = json.dumps(internal_data)

sys.stdout.write(
    """Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST,GET,OPTIONS
Access-Control-Allow-Origin:*
Content-Type: application/json; charset=utf-8
Content-Length: %d

""" % len(json_data))

ret_dict = {
    "uriRoot": lib_util.uriRoot,
    "HttpPrefix": lib_util.HttpPrefix(),
Beispiel #11
0
def Main():
    orig_req_uri = lib_util.RequestUri()

    # It initialises an implicit global object similar.
    # When in the mode of global merging, the method "cgiEnv.OutCgiRdf()" does not generate anything,
    # but simply stores the new cgiEnv in a global list..
    # The script loops on the URLs passed as CGI parameters.
    # The URLs are loaded and their content merged into the container lib_common.globalGraph
    lib_common.CgiEnvMergeMode()

    arguments = cgi.FieldStorage()

    # The display mode is read now, otherwise the CGI arguments are later destroyed, in this script.
    the_mode = lib_util.GuessDisplayMode()
    logging.debug("the_mode=%s", the_mode)

    # Concatenation of error messages of each script.
    cumulated_error = ""

    # This logic might be needed in lib_client.py
    for urlfil in arguments.getlist("url"):
        # The parameters are coded in base64, although we leave the possibility not to encode them,
        # for compatibility with test scripts.

        complete_url = lib_util.Base64Decode(urlfil)

        logging.debug("complete_url=%s", complete_url)

        # Only the URL without the arguments.
        url_split = complete_url.split("?")
        url_no_args = url_split[0]
        if len(url_split) > 1:
            cgi_query_string = url_split[1]
        else:
            cgi_query_string = ""

        # The URL might be absolute or relative. Example:
        # "survol/sources_types/enumerate_CIM_Process.py?xid=."
        idx_htbin = url_no_args.find("sources_types/")
        if idx_htbin == -1:
            # This may be the main presentation page of a Survol, WMI or WBEM object. Example:
            # "http://127.0.0.1:80/Survol/survol/entity.py?xid=CIM_Process.Handle=640"
            survol_prefix = "survol/"
            idx_survol = url_no_args.find(survol_prefix)
            if idx_survol == -1:
                # TODO: This happens if the URL is a main presentation page of an object,
                # instead of a script: Something like "survol/entity.py/entity.py?xid=..."
                # This should be fixed but is not an issue.
                logging.warning("merge: SHOULD NOT HAPPEN url=%s",
                                complete_url)
                url_path_short = "INVALID_MERGED_URL"
            else:
                # Just starts at the beginning of the script name: "entity.py", "entity_wmi.py", "entity_wbem.py".
                url_path_short = url_no_args[idx_survol + len(survol_prefix):]
        else:
            url_path_short = url_no_args[idx_htbin:]

        # url_path_short is the actual script to load.
        url_dir_nam = os.path.dirname(url_path_short)

        # The directory of the script is used to build a Python module name.
        modu_nam = url_dir_nam.replace("/", ".")

        url_fil_nam = os.path.basename(url_path_short)

        logging.debug(
            "url_path_short=%s url_dir_nam=%s modu_nam=%s url_fil_nam=%s",
            url_path_short, url_dir_nam, modu_nam, url_fil_nam)
        try:
            # argDir="sources_types.win32" urlFileNam="enumerate_top_level_windows.py"
            imported_mod = lib_util.GetScriptModule(modu_nam, url_fil_nam)
        except Exception as exc:
            logging.warning(
                "Caught %s when loading modu_nam=%s url_fil_nam=%s", exc,
                modu_nam, url_fil_nam)
            continue

        if not imported_mod:
            cumulated_error = "merge_scripts.py Cannot import complete_url=%s" % complete_url
            continue

        try:
            # The entire URL must be "injected" so the parameters will be properly parsed,
            # when Main() call lib_util.RequestUri().
            # The script passed as CGI parameter, believes that it is loaded as a plain URL.
            url_unquote = lib_util.urllib_unquote(complete_url)
            os.environ["REQUEST_URI"] = url_unquote

            os.environ['SCRIPT_NAME'] = url_fil_nam
            # "xid=EURO%5CLONL00111310@process:16580"
            os.environ['QUERY_STRING'] = cgi_query_string

            lib_common.enable_error_message(False)

            # This executes the script: The new nodes and links are merged in a global RDF container.
            imported_mod.Main()
        except Exception as exc:
            logging.warning(
                "Caught %s when executing Main in modu_nam=%s url_fil_nam=%s",
                exc, modu_nam, url_fil_nam)
            if cumulated_error != "":
                cumulated_error += " ; "
            cumulated_error += " url=" + url_no_args + " / " + url_fil_nam + ":" + str(
                exc)

            continue
        lib_common.enable_error_message(True)

    os.environ["REQUEST_URI"] = orig_req_uri

    # OutCgiRdf has been called by each script without writing anything,
    # but the specific parameters per script are stored inside.

    # Here, all the RDF nodes and links, loaded from each URL, and then merged in lib_common.globalGraph,
    # are then transformed into the chosen output format.
    lib_common.MergeOutCgiRdf(the_mode, cumulated_error)
Beispiel #12
0
def Main():
    origReqUri = lib_util.RequestUri()

    # There is only one cgiEnv and "cgiEnv.OutCgiRdf()" does not generate anything.
    lib_common.CgiEnvMergeMode()

    arguments = cgi.FieldStorage()

    # The display mode is read now, otherwise the CGI arguments are later destroyed, in this script.
    theMode = lib_util.GuessDisplayMode()
    sys.stderr.write("merge_scripts.py theMode=%s\n" % (theMode))

    # Concatenation of error messages of each script.
    cumulatedError = ""

    for urlfil in arguments.getlist("url"):
        # The parameters are coded in base64, although we leave the possibility not to encode them,
        # for compatibility with test scripts.

        complete_url = lib_util.Base64Decode(urlfil)

        sys.stderr.write("complete_url=%s\n" % complete_url)

        # Only the URL without the arguments.
        urlSplit = complete_url.split("?")
        urlNoArgs = urlSplit[0]
        if len(urlSplit) > 1:
            cgiQueryString = urlSplit[1]
        else:
            cgiQueryString = ""

        # The URL might be absolute or relative. Example:
        # "survol/sources_types/enumerate_CIM_Process.py?xid=."
        idxHtbin = urlNoArgs.find("sources_types/")
        if idxHtbin == -1:
            # This may be the main presentation page of a Survol, WMI or WBEM object. Example:
            # "http://127.0.0.1:80/Survol/survol/entity.py?xid=CIM_Process.Handle=640"
            survolPrefix = "survol/"
            idxSurvol = urlNoArgs.find(survolPrefix)
            if idxSurvol == -1:
                # TODO: This happens if the URL is a main presentation page of an object,
                # instead of a script: Something like "survol/entity.py/entity.py?xid=..."
                # This should be fixed but is not an issue.
                sys.stderr.write("merge: SHOULD NOT HAPPEN url=%s\n" %
                                 complete_url)
                urlPathShort = "INVALID_MERGED_URL"
            else:
                # Just starts at the beginning of the script name: "entity.py", "entity_wmi.py", "entity_wbem.py".
                urlPathShort = urlNoArgs[idxSurvol + len(survolPrefix):]
        else:
            urlPathShort = urlNoArgs[idxHtbin:]

        # urlPathShort is the actual script to load.
        urlDirNam = os.path.dirname(urlPathShort)
        moduNam = urlDirNam.replace("/", ".")

        urlFilNam = os.path.basename(urlPathShort)

        sys.stderr.write(
            "urlPathShort=%s urlDirNam=%s moduNam=%s urlFilNam=%s\n" %
            (urlPathShort, urlDirNam, moduNam, urlFilNam))
        try:
            # argDir="sources_types.win32" urlFileNam="enumerate_top_level_windows.py"
            importedMod = lib_util.GetScriptModule(moduNam, urlFilNam)
        except Exception:
            errorMsg = sys.exc_info()[1]
            sys.stderr.write(
                "Caught %s when loading moduNam=%s urlFilNam=%s\n" %
                (errorMsg, moduNam, urlFilNam))
            continue

        if not importedMod:
            cumulatedError = "merge_scripts.py Cannot import complete_url=%s" % (
                complete_url)
            continue

        try:
            # The entire URL must be "injected" so the parameters will be properly parsed,
            # when Main() call lib_util.RequestUri().
            urlUnquote = lib_util.urllib_unquote(complete_url)
            os.environ["REQUEST_URI"] = urlUnquote

            os.environ['SCRIPT_NAME'] = urlFilNam
            # "xid=EURO%5CLONL00111310@process:16580"
            os.environ['QUERY_STRING'] = cgiQueryString

            lib_common.ErrorMessageEnable(False)
            importedMod.Main()
        except Exception:
            errorMsg = sys.exc_info()[1]
            sys.stderr.write(
                "Caught %s when executing Main in moduNam=%s urlFilNam=%s\n" %
                (errorMsg, moduNam, urlFilNam))
            if cumulatedError != "":
                cumulatedError += " ; "
            cumulatedError += " url=" + urlNoArgs + " / " + urlFilNam + ":" + str(
                errorMsg)

            continue
        lib_common.ErrorMessageEnable(True)

    os.environ["REQUEST_URI"] = origReqUri

    # OutCgiRdf has been called by each script without writing anything,
    # but the specific parameters per script are stored inside.

    # TESTER AVEC CA:
    # http://127.0.0.1:8000/survol/merge_scripts.py?url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9ob3N0LnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBc3No&url=aHRiaW4vc291cmNlc190eXBlcy9DSU1fQ29tcHV0ZXJTeXN0ZW0vaG9zdG5hbWVfbm1hcC5weT94aWQ9Q0lNX0NvbXB1dGVyU3lzdGVtLk5hbWUlM0RVbmtub3duLTMwLWI1LWMyLTAyLTBjLWI1LTI&url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9ob3N0LnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBc3ZybG9j&url=aHRiaW4vZW50aXR5LnB5P3hpZD1zbWJzaHIuSWQ9Ly8vL1dETXlDbG91ZE1pcnJvci9yY2hhdGVhdQ&url=aHRiaW4vc291cmNlc190eXBlcy9DSU1fQ29tcHV0ZXJTeXN0ZW0vY29ubmVjdGVkX3NvY2tldHMucHk_eGlkPUNJTV9Db21wdXRlclN5c3RlbS5OYW1lJTNEVW5rbm93bi0zMC1iNS1jMi0wMi0wYy1iNS0y&url=aHRiaW4vc291cmNlc190eXBlcy9DSU1fQ29tcHV0ZXJTeXN0ZW0vaG9zdG5hbWVfbm1hcC5weT94aWQ9Q0lNX0NvbXB1dGVyU3lzdGVtLk5hbWUlM0RVbmtub3duLTMwLWI1LWMyLTAyLTBjLWI1LTI&url=aHRiaW4vc291cmNlc190eXBlcy9ncm91cC9saW51eF91c2VyX2dyb3VwLnB5P3hpZD1ncm91cC5OYW1lJTNEYXBhY2hl&url=aHRiaW4vc291cmNlc190eXBlcy91c2VyL3VzZXJfbGludXhfaWQucHk_eGlkPXVzZXIuRG9tYWluJTNETG9jYWxIb3N0JTJDTmFtZSUzRGFwYWNoZQ&url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9jb25uZWN0ZWRfcHJvY2Vzc2VzLnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBdGVsbmV0&url=aHRiaW4vc291cmNlc190eXBlcy91c2VyL3VzZXJfcHJvY2Vzc2VzLnB5P3hpZD11c2VyLkRvbWFpbiUzRExvY2FsSG9zdCUyQ05hbWUlM0RhcGFjaGU&url=aHRiaW4vc291cmNlc190eXBlcy9DSU1fUHJvY2Vzcy9wcm9jZXNzX2N3ZC5weT94aWQ9Q0lNX1Byb2Nlc3MuSGFuZGxlJTNEMTQ3MDU&url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9jb25uZWN0ZWRfcHJvY2Vzc2VzLnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBc3No&url=aHRiaW4vc291cmNlc190eXBlcy9DSU1fUHJvY2Vzcy9wcm9jZXNzX2N3ZC5weT94aWQ9Q0lNX1Byb2Nlc3MuSGFuZGxlJTNEMTQ3MDU&url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9jb25uZWN0ZWRfcHJvY2Vzc2VzLnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBdGVsbmV0&url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9jb25uZWN0ZWRfcHJvY2Vzc2VzLnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBdGVsbmV0&url=aHRiaW4vc291cmNlc190eXBlcy9hZGRyL3NvY2tldF9jb25uZWN0ZWRfcHJvY2Vzc2VzLnB5P3hpZD1hZGRyLklkJTNEMTkyLjE2OC4xLjg4JTNBc3No&url=aHR0cDovLzE5Mi4xNjguMS44ODo4MC9TdXJ2b2wvaHRiaW4vZW50aXR5LnB5P3hpZD1DSU1fUHJvY2Vzcy5IYW5kbGU9MjA1MTI
    lib_common.MergeOutCgiRdf(theMode, cumulatedError)
Beispiel #13
0
    def __init__(self,
                 parameters=None,
                 can_process_remote=False,
                 layout_style="",
                 collapsed_properties=None):
        # It is possible to run these scripts as CGI scripts, so this transforms
        # command line arguments into CGI arguments. This is very helpful for debugging.

        # The HTTP server can set the logging level with the environment variable SURVOL_LOGGING_LEVEL.
        try:
            logging_level = os.environ["SURVOL_LOGGING_LEVEL"]
            logging.getLogger().setLevel(logging_level)
            logging.info("logging_level set with SURVOL_LOGGING_LEVEL=%s" % logging_level)
        except KeyError:
            logging.info("logging_level is not forced with SURVOL_LOGGING_LEVEL.")

        lib_command_line.command_line_to_cgi_args()
        assert "QUERY_STRING" in os.environ

        # Some limitations of cgiserver.py and Python2:
        # TODO: When running from cgiserver.py, and if QUERY_STRING is finished by a dot ".", this dot
        # TODO: is removed. Workaround: Any CGI variable added after.
        # TODO: Also: Several slashes "/" are merged into one.
        # TODO: Example: "xid=http://192.168.1.83:5988/." becomes "xid=http:/192.168.1.83:5988/"
        # TODO: ... or "xx.py?xid=smbshr.Id=////WDMyCloudMirror///jsmith" ...
        # TODO: ... becomes "xx.py?xid=smbshr.Id=/WDMyCloudMirror/jsmith"
        # TODO: Replace by "xid=http:%2F%2F192.168.1.83:5988/."

        mode = lib_util.GuessDisplayMode()
        logging.debug("mode=%s" % mode)

        # Contains the optional arguments of the script, entered as CGI arguments..
        self.m_parameters = parameters if parameters else {}

        self.m_parameterized_links = dict()

        self.m_layout_style = layout_style
        self.m_collapsed_properties = collapsed_properties if collapsed_properties else []

        # When in merge mode, the display parameters must be stored in a place accessible by the graph.

        doc_modu_all = _get_calling_module_doc()

        # Take only the first non-empty line. See lib_util.FromModuleToDoc()
        self.m_page_title, self.m_page_subtitle = lib_util.SplitTextTitleRest(doc_modu_all)

        # Title page contains __doc__ plus object label.

        # Example: REQUEST_URI=/Survol/survol/print_environment_variables.py
        # This does NOT contain the host and the port, which implies a confusion if severl Survol agents
        # use the same database. It makes sense, because the result should not depend in the agent.
        self.m_calling_url = lib_util.RequestUri()
        self.m_url_without_mode = lib_util.url_mode_replace(self.m_calling_url, "")

        full_title, entity_class, entity_id, entity_host = lib_naming.parse_entity_uri_with_host(
            self.m_calling_url,
            long_display=False,
            force_entity_ip_addr=None)
        # Here, the commas separating the CGI arguments are intact, but the commas in the arguments are encoded.
        entity_id_dict = lib_util.SplitMoniker(entity_id)

        self._concatenate_entity_documentation(full_title, entity_class, entity_id)

        # Global CanProcessRemote has precedence over parameter can_process_remote
        # which should probably be deprecated, although they do not have exactly the same role:
        # * Global CanProcessRemote is used by entity.py to display scripts which have this capability.
        # * Parameter can_process_remote is used to inform, at execution time, of this capability.
        # Many scripts are not enumerated by entity.py so a global CanProcessRemote is not necessary.
        # For clarity, it might be fine to replace the parameter can_process_remote by the global value.
        # There cannot be nasty consequences except that some scripts might not be displayed
        # when they should be, and vice-versa.
        try:
            globalCanProcessRemote = globals()["CanProcessRemote"]
        except KeyError:
            globalCanProcessRemote = False

        if can_process_remote != globalCanProcessRemote:
            # "INCONSISTENCY CanProcessRemote ... which is not an issue.
            can_process_remote = True

        self.m_can_process_remote = can_process_remote

        self.m_arguments = cgi.FieldStorage()

        self.m_entity_type = entity_class
        self.m_entity_id = entity_id
        self.m_entity_host = entity_host
        self.m_entity_id_dict = entity_id_dict

        self._create_or_get_graph()

        # Depending on the caller module, maybe the arguments should be 64decoded. See "sql/query".
        # As the entity type is available, it is possible to import it and check if it encodes it arguments.
        # See presence of source_types.sql.query.DecodeCgiArg(keyWord,cgiArg) for example.

        # This is probably too generous to indicate a local host.
        self.test_remote_if_possible(can_process_remote)

        if mode == "edit":
            self.enter_edition_mode()
            logging.critical("Should not be here because the HTML form is displayed.")
            assert False

        # Scripts which can run as events feeders must have their name starting with "events_feeder_".
        # This allows to use CGI programs as events genetors not written in Python.
        # TODO: Using the script name is enough, the module is not necessary.
        full_script_path, _, _ = self.m_calling_url.partition("?")
        script_basename = os.path.basename(full_script_path)
        daemonizable_script = os.path.basename(script_basename).startswith("events_feeder_")

        if not daemonizable_script:
            # This would be absurd to have a normal CGI script started in this mode.
            assert mode != "daemon", "Script is not an events generator:" + self.m_calling_url
            # Runs as usual as a CGI script. The script will fill the graph.
            return

        # The events graph must be specified because, from here, everything will access the events graph.
        set_events_credentials()

        # Maybe this is in the daemon.
        if mode == "daemon":
            # Just runs as usual. At the end of the script, OutCgiRdf will write the RDF graph in the events.
            # Here, this process is started by the supervisor process; It is not started by the HTTP server,
            # in CGI or WSGI.
            return

        try:
            # This may throw "[Errno 111] Connection refused"
            is_daemon_running = lib_daemon.is_events_feeder_daemon_running(self.m_url_without_mode)
        except Exception as exc:
            # Then display the content in snapshot mode, which is better than nothing.
            self.report_error_message("Cannot start daemon, caught:%s\n" % exc)
            logging.error("Cannot start daemon: When getting daemon status, caught:%s" % exc)
            return

        if not is_daemon_running:
            # This is the case of a daemonizable script, normally run.
            # TODO: Slight ambiguity here: The daemon could be intentionally stopped, and the user
            # TODO: would like to see the existing events stored in the persistent triplestore,
            # TODO: without restarting the daemon. We do not know how to do this yet.
            lib_daemon.start_events_feeder_daemon(self.m_url_without_mode)
            # After that, whether the daemon dedicated to the script and its parameters is started or not,
            # the script is then executed in normal, snapshot mode, as a CGI script.
        else:
            # Events are probably stored in the big events graph. The host and port are not used in the URL.
            lib_kbase.read_events_to_graph(self.m_url_without_mode, self.m_graph)

            # TODO: The layout parameters and any other display parameters of the calling script
            # TODO: must be in the constructor.
            # TODO: This, because the rest of the script is not executed.
            self.OutCgiRdf()

            # The rest of the script must not be executed because daemon scripts are organised so that
            # when the daemon is started, it writes all events in the database, to be read by the same script
            # run in CGI or WSGI.
            # The snapshot part of a daemon script is executed only when the deamon is not started.
            logging.info("Events are read from the events database because the deamon is running.")
            if _is_wsgi():
                logging.info("Leaving the execution of the script run in a WSGI server.")
                # This is not an error.
            else:
                logging.info("Exiting the process of the script run in snapshot mode and CGI server.")
            # This raises SystemExit which can be handled.
            exit(0)