cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# -*- coding: utf-8 -*-
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# $Id$
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCommon Web Utility Functions.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync__copyright__ = \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCopyright (C) 2012-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
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.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
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.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
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"""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync__version__ = "$Revision$"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Standard Python imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncimport os;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncimport shutil;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncimport sys;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncimport unittest;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Validation Kit imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom common import utils;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Python 3 hacks:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncif sys.version_info[0] < 3:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from urllib import urlopen as urllib_urlopen;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from urllib2 import quote as urllib_quote;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from urllib import urlencode as urllib_urlencode;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncelse:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from urllib.parse import quote as urllib_quote; # pylint: disable=F0401,E0611
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from urllib.parse import urlencode as urllib_urlencode; # pylint: disable=F0401,E0611
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from urllib.request import urlopen as urllib_urlopen; # pylint: disable=F0401,E0611
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef escapeElem(sText):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Escapes special character to HTML-safe sequences.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sText = sText.replace('&', '&amp;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sText = sText.replace('<', '&lt;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return sText.replace('>', '&gt;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef escapeAttr(sText):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Escapes special character to HTML-safe sequences.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sText = sText.replace('&', '&amp;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sText = sText.replace('<', '&lt;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sText = sText.replace('>', '&gt;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return sText.replace('"', '&quot;')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef escapeElemToStr(oObject):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stringifies the object and hands it to escapeElem.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if utils.isString(oObject):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return escapeElem(oObject);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return escapeElem(str(oObject));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef escapeAttrToStr(oObject):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Stringifies the object and hands it to escapeAttr. May return unicode string.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return escapeAttr(oObject);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef escapeAttrJavaScriptStringDQ(sText):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Escapes a javascript string that is to be emitted between double quotes. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if '"' not in sText:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync chMin = min(sText);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ord(chMin) >= 0x20:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return sText;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet = '';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for ch in sText:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ch == '"':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet += '\\"';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif ord(ch) >= 0x20:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet += ch;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif ch == '\n':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet += '\\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif ch == '\r':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet += '\\r';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif ch == '\t':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet += '\\t';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRet += '\\x%02x' % (ch,);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return sRet;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef quoteUrl(sText):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync See urllib.quote().
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return urllib_quote(sText);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef encodeUrlParams(dParams):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync See urllib.urlencode().
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return urllib_urlencode(dParams, doseq=True)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef hasSchema(sUrl):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Checks if the URL has a schema (e.g. http://) or is file/server relative.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns True if schema is present, False if not.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iColon = sUrl.find(':');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if iColon > 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sSchema = sUrl[0:iColon];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if len(sSchema) >= 2 and len(sSchema) < 16 and sSchema.islower() and sSchema.isalpha():
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return False;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef getFilename(sUrl):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Extracts the filename from the URL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @TODO This isn't entirely correct. Use the urlparser instead!
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sFilename = os.path.basename(sUrl.replace('/', os.path.sep));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return sFilename;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdef downloadFile(sUrlFile, sDstFile, sLocalPrefix, fnLog, fnError = None, fNoProxies=True):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Downloads the given file if an URL is given, otherwise assume it's
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync something on the build share and copy it from there.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Raises no exceptions, returns log + success indicator instead.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Note! This method may use proxies configured on the system and the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync http_proxy, ftp_proxy, no_proxy environment variables.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync @todo Fixed build burn here. Please set default value for fNoProxies
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to appropriate one.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if fnError is None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnError = fnLog;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sUrlFile.startswith('http://') \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync or sUrlFile.startswith('https://') \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync or sUrlFile.startswith('ftp://'):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Download the file.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnLog('Downloading "%s" to "%s"...' % (sUrlFile, sDstFile));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @todo We get 404.html content instead of exceptions here, which is confusing and should be addressed.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if fNoProxies:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSrc = urllib_urlopen(sUrlFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSrc = urllib_urlopen(sUrlFile, proxies = dict());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oDst = utils.openNoInherit(sDstFile, 'wb');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oDst.write(oSrc.read());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oDst.close();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSrc.close();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except Exception, oXcpt:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnError('Error downloading "%s" to "%s": %s' % (sUrlFile, sDstFile, oXcpt));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return False;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Assumes file from the build share.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sSrcPath = os.path.join(sLocalPrefix, sUrlFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnLog('Copying "%s" to "%s"...' % (sSrcPath, sDstFile));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync shutil.copyfile(sSrcPath, sDstFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except Exception, oXcpt:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fnError('Error copying "%s" to "%s": %s' % (sSrcPath, sDstFile, oXcpt));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return False;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return True;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Unit testing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# pylint: disable=C0111
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncclass CommonUtilsTestCase(unittest.TestCase):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def testHasSchema(self):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertTrue(hasSchema('http://www.oracle.com/'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertTrue(hasSchema('https://virtualbox.com/'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertFalse(hasSchema('://virtualbox.com/'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertFalse(hasSchema('/usr/bin'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertFalse(hasSchema('usr/bin'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertFalse(hasSchema('bin'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self.assertFalse(hasSchema('C:\\WINNT'));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncif __name__ == '__main__':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync unittest.main();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # not reached.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync