cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# -*- coding: utf-8 -*-
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncTest Manager Core - Web Server Abstraction Base Class.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCopyright (C) 2012-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThis file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncavailable from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncyou can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncGeneral Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncFoundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynchope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThe contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncof the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync(CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncYou may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncterms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Standard python imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Validation Kit imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync For exceptions raised by glue code.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Web server interface abstraction and some HTML utils.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## Enables more debug output.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## The maximum number of characters to cache.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## Special getUserName return value.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def __init__(self, sValidationKitDir, fHtmlDebugOutput = True):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._fHtmlDebugOutput = fHtmlDebugOutput; # For trace
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if config.g_ksSrcGlueDebugLogDst is not None and config.g_kfSrvGlueDebug is True:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._oDbgFile = open(config.g_ksSrcGlueDebugLogDst, 'a');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # HTTP header.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.oOutputText = codecs.getwriter('utf-8')(sys.stdout);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Get stuff.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns a dictionary with the query parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync The parameter name is the key, the values are given as lists. If a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync parameter is given more than once, the value is appended to the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync existing dictionary entry.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns the client address, as a string.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('getClientAddr is not implemented');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the HTTP request method.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 'POST';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets login name provided by Apache.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns kUnknownUser if not logged on.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets scheme name (aka. access protocol) from request URL, i.e. 'http' or 'https'.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync See also urlparse.scheme.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 'http';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the network location (server host name / ip) from the request URL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync See also urlparse.netloc.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('getUrlNetLoc is not implemented');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the hirarchical path (relative to server) from the request URL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync See also urlparse.path.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Note! This includes the leading slash.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('getUrlPath is not implemented');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the hirarchical base path (relative to server) from the request URL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Note! This includes both a leading an trailing slash.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the URL being accessed, sans parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync For instance this will return, "http://localhost/testmanager/admin.cgi"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync when "http://localhost/testmanager/admin.cgi?blah=blah" is being access.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return '%s://%s%s' % (self.getUrlScheme(), self.getUrlNetLoc(), self.getUrlPath());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the base URL (with trailing slash).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync For instance this will return, "http://localhost/testmanager/" when
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "http://localhost/testmanager/admin.cgi?blah=blah" is being access.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return '%s://%s%s' % (self.getUrlScheme(), self.getUrlNetLoc(), self.getUrlBasePath());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the User-Agent field of the HTTP header, returning empty string
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if not present.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the Content-Type field of the HTTP header, parsed into a type
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync string and a dictionary.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return ('text/html', {});
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the content length.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns int.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns file object for reading the HTML body.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('getUrlPath is not implemented');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Output stuff.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Worker function which child classes can override.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Flushes the HTTP header.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._writeHeader('%s: %s\n' % (sKey, self._dHeaderFields[sKey]));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._writeHeader('\n'); # End of header indicator.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Sets a header field.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Sets up redirection of the page.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Raises an exception if called too late.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('setRedirect called after the header was written');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('Redirection code %d is not supported' % (iCode,));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Worker function which child classes can override.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Writes chunk of HTML, making sure the HTTP header is flushed first.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('Cannot use writeParameter when body type is "%s"' % (self._sBodyType, ));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Writes a raw chunk the document. Can be binary or any encoding.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync No caching.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('Cannot use writeParameter when body type is "%s"' % (self._sBodyType, ));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Writes one or more reply parameters in a form style response. The names
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync and values in dParams are unencoded, this method takes care of that.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Note! This automatically changes the content type to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'application/x-www-form-urlencoded', if the header hasn't been flushed
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.setHeaderField('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif self._dHeaderFields['Content-Type'] != 'application/x-www-form-urlencoded; charset=utf-8':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('Cannot use writeParams when content-type is "%s"' % \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WebServerGlueException('Cannot use writeParams when body type is "%s"' % (self._sBodyType, ));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Flush the output.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return None;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Gets the path to the TM 'webui' directory.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return os.path.join(self._sValidationKitDir, 'testmanager', 'webui');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Error stuff & Debugging.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Writes the error to a log file.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Easy solution for log file size: Only one report.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except: pass;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Try write the log file.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def errorPage(self, sError, aXcptInfo, sLogFile = None):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Displays a page with an error message.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sLogFile is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Reset buffering, hoping that nothing was flushed yet.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.setHeaderField('Content-Type', 'text/html; charset=utf-8');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.setHeaderField('Content-Type', 'text/plain; charset=utf-8');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Write the error page.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.write('<html><head><title>Test Manage Error</title></head>\n' +
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<body><h1>Test Manager Error:</h1>\n' +
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '===================\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '---------\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '----------\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.write('\nDebug info callback %s raised exception: %s\n' % (fn, oXcpt));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Dumps useful debug info.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite('<html><head><title>Test Manage Debug Info</title></head>\n<body>\n');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def debugDumpDict(self, sName, dDict, fSorted = True, fnWrite = None):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Dumps dictionary.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<table border="1"><tr><th>name</th><th>value</th></tr>\n' % (sName,));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite(' <tr><td>' + webutils.escapeElem(sKey) + '</td><td>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync + '</td></tr>\n');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite('------------------------------------------------------------------------\n');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def debugDumpList(self, sName, aoStuff, fnWrite = None):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Dumps array.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<table border="1"><tr><th>index</th><th>value</th></tr>\n' % (sName,));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite(' <tr><td>' + str(i) + '</td><td>' + webutils.escapeElem(str(aoStuff[i])) + '</td></tr>\n');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite('------------------------------------------------------------------------\n');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Dumps request parameters. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite('<p>Exception %s while retriving parameters.</p>\n' % (oXcpt,))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnWrite('Exception %s while retriving parameters.\n' % (oXcpt,))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Dumps os.environ. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self.debugDumpDict('Environment (os.environ)', os.environ, fnWrite = fnWrite);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Dumps sys.argv. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self.debugDumpList('Arguments (sys.argv)', sys.argv, fnWrite = fnWrite);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Dump python info.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dInfo['sys.builtin_module_names'] = sys.builtin_module_names;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self.debugDumpDict('Python Info', dInfo, fnWrite = fnWrite);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Dumps stuff to the error page and debug info page.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Should be extended by child classes when possible.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Prints to debug log (usually apache error log).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._oDbgFile.write('%s/%03u: %s\n' % (tsNow, tsReq, sLine,));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Registers a debug info method for calling when the error page is shown.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync The fnDebugInfo function takes two parameters. The first is this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync object, the second is a boolean indicating html (True) or text (False)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync output. The return value is ignored.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def unregisterDebugInfoCallback(self, fnDebugInfo):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Unregisters a debug info method previously registered by
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync registerDebugInfoCallback.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except: pass;