当前位置: 首页>>代码示例>>Python>>正文


Python rhnConfig.CFG类代码示例

本文整理汇总了Python中spacewalk.common.rhnConfig.CFG的典型用法代码示例。如果您正苦于以下问题:Python CFG类的具体用法?Python CFG怎么用?Python CFG使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。


在下文中一共展示了CFG类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。

示例1: __init__

    def __init__(self, req):
        """ init with http request object """

        # FIXME: should rename some things:
        #        self.bodyFd --> self.body or self.data or ?
        #        self.caChain --> self.caCert

        self.req = req
        # turn wsgi.input object into a SmartIO instance so it can be read
        # more than once
        if 'wsgi.input' in self.req.headers_in:
            smartFd = SmartIO(max_mem_size=CFG.MAX_MEM_FILE_SIZE)
            smartFd.write(self.req.headers_in['wsgi.input'].read())
            self.req.headers_in['wsgi.input'] = smartFd

        self.responseContext = ResponseContext()
        self.uri = None   # ''

        # Common settings for both the proxy and the redirect
        # broker and redirect immediately alter these for their own purposes
        self.caChain = CFG.CA_CHAIN
        self.httpProxy = CFG.HTTP_PROXY
        self.httpProxyUsername = CFG.HTTP_PROXY_USERNAME
        self.httpProxyPassword = CFG.HTTP_PROXY_PASSWORD
        if not self.httpProxyUsername:
            self.httpProxyPassword = ''
        self.rhnParent = CFG.RHN_PARENT or ''
        self.rhnParent = rhnLib.parseUrl(self.rhnParent)[1].split(':')[0]
        CFG.set('RHN_PARENT', self.rhnParent)
开发者ID:TJM,项目名称:spacewalk,代码行数:29,代码来源:rhnShared.py

示例2: accessible

def accessible(url):
    """Try if url is accessible

    :arg url: the url which is tried to access

    Returns True if url is accessible, otherwise False.

    """
    timeout = 120
    if CFG.is_initialized() and CFG.has_key('TIMEOUT'):
        timeout = CFG.TIMEOUT
    curl = pycurl.Curl()

    curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
    curl.setopt(pycurl.URL, url)
    curl.setopt(pycurl.DEBUGFUNCTION, _curl_debug)
    curl.setopt(pycurl.VERBOSE, True)
    proxy_url, proxy_user, proxy_pass = get_proxy(url)
    if proxy_url:
        curl.setopt(pycurl.PROXY, proxy_url)
    log_debug(2, "Connect to %s" % url)

    # We implement our own redirection-following, because pycurl
    # 7.19 doesn't POST after it gets redirected. Ideally we'd be
    # using pycurl.POSTREDIR here, but that's in 7.21.
    curl.setopt(pycurl.FOLLOWLOCATION, False)
    curl.setopt(pycurl.NOBODY, True)

    try_counter = 5
    while try_counter:
        try_counter -= 1
        try:
            curl.perform()
        except pycurl.error, e:
            if e[0] == 56:  # Proxy requires authentication
                log_debug(2, e[1])
                if not (proxy_user and proxy_pass):
                    raise TransferException("Proxy requires authentication, "
                                            "but reading credentials from "
                                            "%s failed." % YAST_PROXY)
                curl.setopt(pycurl.PROXYUSERPWD,
                            "%s:%s" % (proxy_user, proxy_pass))
            else:
                break

        status = curl.getinfo(pycurl.HTTP_CODE)
        # OK or file
        if status == 200 or (URL(url).scheme == "file" and status == 0):
            return True
        elif status in (301, 302):  # redirects
            url = curl.getinfo(pycurl.REDIRECT_URL)
            log_debug(2, "Got redirect to %s" % url)
            curl.setopt(pycurl.URL, url)
        elif status >= 400:
            break
开发者ID:m47ik,项目名称:uyuni,代码行数:55,代码来源:suseLib.py

示例3: _useProxyFor

def _useProxyFor(url):
    """Return True if a proxy should be used for given url, otherwise False.

    This function uses server.satellite.no_proxy variable to check for
    hosts or domains which should not be connected via a proxy.

    server.satellite.no_proxy is a comma seperated list.
    Either an exact match, or the previous character
    is a '.', so host is within the same domain.
    A leading '.' in the pattern is ignored.
    See also 'man curl'

    """
    u = urlparse.urlsplit(url)
    # pylint can't see inside the SplitResult class
    # pylint: disable=E1103
    if u.scheme == 'file':
        return False
    hostname = u.hostname.lower()
    if hostname in ["localhost", "127.0.0.1", "::1"]:
        return False
    comp = CFG.getComponent()
    if not CFG.has_key("no_proxy"):
        initCFG("server.satellite")
    if not CFG.has_key('no_proxy'):
        initCFG(comp)
        return True
    noproxy = CFG.no_proxy
    initCFG(comp)
    if not noproxy:
        return True
    if not isinstance(noproxy, list):
        if noproxy == '*':
            # just an asterisk disables all.
            return False
        noproxy = [noproxy]

    # No proxy: Either an exact match, or the previous character
    # is a '.', so host is within the same domain.
    # A leading '.' in the pattern is ignored. Some implementations
    # need '.foo.ba' to prevent 'foo.ba' from matching 'xfoo.ba'.
    for domain in noproxy:
        domain = domain.lower()
        if domain[0] == '.':
            domain = domain[1:]
        if hostname.endswith(domain) and \
            (len(hostname) == len(domain) or
             hostname[len(hostname) - len(domain) - 1] == '.'):
            return False
    return True
开发者ID:m47ik,项目名称:uyuni,代码行数:50,代码来源:suseLib.py

示例4: _create_connection

    def _create_connection(self):
        """ Returns a Connection object """
        scheme, host, port, _uri = self._parse_url(self.rhnParent)
        # Build the list of params
        params = {
            'host':   host,
            'port':   port,
        }
        if CFG.has_key('timeout'):
            params['timeout'] = CFG.TIMEOUT
        if self.httpProxy:
            params['proxy'] = self.httpProxy
            params['username'] = self.httpProxyUsername
            params['password'] = self.httpProxyPassword
        if scheme == 'https' and self.caChain:
            params['trusted_certs'] = [self.caChain, ]

        # Now select the right class
        if self.httpProxy:
            if scheme == 'https':
                conn_class = connections.HTTPSProxyConnection
            else:
                conn_class = connections.HTTPProxyConnection
        else:
            if scheme == 'https':
                conn_class = connections.HTTPSConnection
            else:
                conn_class = connections.HTTPConnection

        log_debug(5, "Using connection class", conn_class, 'Params:', params)
        return conn_class(**params)
开发者ID:TJM,项目名称:spacewalk,代码行数:31,代码来源:rhnShared.py

示例5: _create_connection

    def _create_connection(self):
        """ Returns a Connection object """
        scheme, host, port, _uri = self._parse_url(self.rhnParent)
        # Build the list of params
        params = {"host": host, "port": port}
        if CFG.has_key("timeout"):
            params["timeout"] = CFG.TIMEOUT
        if self.httpProxy:
            params["proxy"] = self.httpProxy
            params["username"] = self.httpProxyUsername
            params["password"] = self.httpProxyPassword
        if scheme == "https" and self.caChain:
            params["trusted_certs"] = [self.caChain]

        # Now select the right class
        if self.httpProxy:
            if scheme == "https":
                conn_class = connections.HTTPSProxyConnection
            else:
                conn_class = connections.HTTPProxyConnection
        else:
            if scheme == "https":
                conn_class = connections.HTTPSConnection
            else:
                conn_class = connections.HTTPConnection

        log_debug(5, "Using connection class", conn_class, "Params:", params)
        return conn_class(**params)
开发者ID:NehaRawat,项目名称:spacewalk,代码行数:28,代码来源:rhnShared.py

示例6: initDB

def initDB(backend=None, host=None, port=None, username=None,
           password=None, database=None, sslmode=None, sslrootcert=None, initsecond=False):
    """
    Initialize the database.

    Either we get backend and all parameter which means the caller
    knows what they are doing, or we populate everything from the
    config files.

    initsecond: If set to True it initialize a second DB connection.
                By default only one DB connection is needed.
    """

    if backend is None:
        if CFG is None or not CFG.is_initialized():
            initCFG('server')
        backend = CFG.DB_BACKEND
        host = CFG.DB_HOST
        port = CFG.DB_PORT
        database = CFG.DB_NAME
        username = CFG.DB_USER
        password = CFG.DB_PASSWORD
        sslmode = None
        sslrootcert = None
        if CFG.DB_SSL_ENABLED:
            sslmode = 'verify-full'
            sslrootcert = CFG.DB_SSLROOTCERT

    if backend not in SUPPORTED_BACKENDS:
        raise rhnException("Unsupported database backend", backend)

    if port:
        port = int(port)

    # Hide the password
    add_to_seclist(password)
    try:
        if initsecond == False:
            __init__DB(backend, host, port, username, password, database, sslmode, sslrootcert)
        else:
            __init__DB2(backend, host, port, username, password, database, sslmode, sslrootcert)
#    except (rhnException, SQLError):
#        raise  # pass on, we know those ones
#    except (KeyboardInterrupt, SystemExit):
#        raise
    except SQLConnectError:
        e = sys.exc_info()[1]
        try:
            closeDB()
        except NameError:
            pass
        raise e
    except:
        raise
        #e_type, e_value = sys.exc_info()[:2]
        # raise rhnException("Could not initialize Oracle database connection",
        #                   str(e_type), str(e_value))
    return 0
开发者ID:dewayneHat,项目名称:spacewalk,代码行数:58,代码来源:__init__.py

示例7: _get_proxy_from_rhn_conf

def _get_proxy_from_rhn_conf():
    """Return a tuple of (url, user, pass) proxy information from rhn config

    Returns None instead of a tuple if there was no proxy url. user,
    pass can be None.

    """
    comp = CFG.getComponent()
    if not CFG.has_key("http_proxy"):
        initCFG("server.satellite")
    result = None
    if CFG.http_proxy:
        # CFG.http_proxy format is <hostname>[:<port>] in 1.7
        url = 'http://%s' % CFG.http_proxy
        result = (url, CFG.http_proxy_username, CFG.http_proxy_password)
    initCFG(comp)
    log_debug(2, "Could not read proxy URL from rhn config.")
    return result
开发者ID:m47ik,项目名称:uyuni,代码行数:18,代码来源:suseLib.py

示例8: _createConnection

    def _createConnection(host, port, scheme):
        params = {"host": host, "port": port}

        if CFG.has_key("timeout"):
            params["timeout"] = CFG.TIMEOUT

        if scheme == SCHEME_HTTPS:
            conn_class = connections.HTTPSConnection
        else:
            conn_class = connections.HTTPConnection

        return conn_class(**params)
开发者ID:pgervase,项目名称:spacewalk,代码行数:12,代码来源:apacheHandler.py

示例9: __init__

    def __init__(self, req):
        """ init with http request object """

        # FIXME: should rename some things:
        #        self.bodyFd --> self.body or self.data or ?
        #        self.caChain --> self.caCert

        self.req = req
        self.responseContext = ResponseContext()
        self.uri = None  # ''

        # Common settings for both the proxy and the redirect
        # broker and redirect immediately alter these for their own purposes
        self.caChain = CFG.CA_CHAIN
        self.httpProxy = CFG.HTTP_PROXY
        self.httpProxyUsername = CFG.HTTP_PROXY_USERNAME
        self.httpProxyPassword = CFG.HTTP_PROXY_PASSWORD
        if not self.httpProxyUsername:
            self.httpProxyPassword = ""
        self.rhnParent = CFG.RHN_PARENT or ""
        self.rhnParent = rhnLib.parseUrl(self.rhnParent)[1].split(":")[0]
        CFG.set("RHN_PARENT", self.rhnParent)
开发者ID:NehaRawat,项目名称:spacewalk,代码行数:22,代码来源:rhnShared.py

示例10: _createConnection

    def _createConnection(host, port, scheme):
        params = {'host': host,
                  'port': port}

        if CFG.has_key('timeout'):
            params['timeout'] = CFG.TIMEOUT

        if scheme == SCHEME_HTTPS:
            conn_class = connections.HTTPSConnection
        else:
            conn_class = connections.HTTPConnection

        return conn_class(**params)
开发者ID:jdobes,项目名称:spacewalk,代码行数:13,代码来源:apacheHandler.py

示例11: initDB

def initDB(backend=None, host=None, port=None, username=None,
           password=None, database=None, sslmode=None, sslrootcert=None):
    """
    Initialize the database.

    Either we get backend and all parameter which means the caller
    knows what they are doing, or we populate everything from the
    config files.
    """

    if backend is None:
        if CFG is None or not CFG.is_initialized():
            initCFG('server')
        backend = CFG.DB_BACKEND
        host = CFG.DB_HOST
        port = CFG.DB_PORT
        database = CFG.DB_NAME
        username = CFG.DB_USER
        password = CFG.DB_PASSWORD
        sslmode = None
        sslrootcert = None
        if CFG.DB_SSL_ENABLED:
            sslmode = 'verify-full'
            sslrootcert = CFG.DB_SSLROOTCERT

    if backend not in SUPPORTED_BACKENDS:
        raise rhnException("Unsupported database backend", backend)

    if port:
        port = int(port)

    # Hide the password
    add_to_seclist(password)
    try:
        __init__DB(backend, host, port, username, password, database, sslmode, sslrootcert)
        __init__DB2(backend, host, port, username, password, database, sslmode, sslrootcert)
#    except (rhnException, SQLError):
#        raise  # pass on, we know those ones
#    except (KeyboardInterrupt, SystemExit):
#        raise
    except SQLConnectError, e:
        try:
            global __DB
            global __DB2
            del __DB
            del __DB2
        except NameError:
            pass
        raise e
开发者ID:Kilian-Petsch,项目名称:spacewalk,代码行数:49,代码来源:__init__.py

示例12: get_mirror_credentials

def get_mirror_credentials():
    """Return a list of mirror credential tuples (user, pass)

    N.B. The config values will be read from the global configuration:
     server.susemanager.mirrcred_user
     server.susemanager.mirrcred_pass
     server.susemanager.mirrcred_user_1
     server.susemanager.mirrcred_pass_1
     etc.

    The credentials are read sequentially, when the first value is found
    to be missing, the process is aborted and the list of credentials
    that have been read so far are returned. For example if
    server.susemanager.mirrcred_pass_1 can not be read, only the first
    pair of default mirrcreds will be returned, even though
    mirrcred_user_2, mirrcred_pass_2 etc. might still exist.

    """
    comp = CFG.getComponent()
    initCFG("server.susemanager")

    creds = []

    # the default values should at least always be there
    if not CFG["mirrcred_user"] or not CFG["mirrcred_pass"]:
        initCFG(comp)
        raise ConfigParserError("Could not read default mirror credentials: "
                                "server.susemanager.mirrcred_user, "
                                "server.susemanager.mirrcred_pass.")

    creds.append((CFG["mirrcred_user"], CFG["mirrcred_pass"]))

    # increment the credentials number, until we can't read one
    n = 1
    while True:
        try:
            creds.append((CFG["mirrcred_user_%s" % n],
                          CFG["mirrcred_pass_%s" % n]))
        except (KeyError, AttributeError):
            break
        n += 1
    initCFG(comp)
    return creds
开发者ID:m47ik,项目名称:uyuni,代码行数:43,代码来源:suseLib.py

示例13: __init__

    def __init__(self, no_packages=False, no_errata=False, no_rpms=False, no_kickstarts=False,
                 log_level=None, mount_point=None, consider_full=False):

        self.cdn_repository_manager = CdnRepositoryManager(mount_point)
        self.no_packages = no_packages
        self.no_errata = no_errata
        self.no_rpms = no_rpms
        self.no_kickstarts = no_kickstarts
        if log_level is None:
            log_level = 0
        self.log_level = log_level

        if mount_point:
            self.mount_point = "file://" + mount_point
            self.consider_full = consider_full
        else:
            self.mount_point = CFG.CDN_ROOT
            self.consider_full = True

        CFG.set('DEBUG', log_level)
        rhnLog.initLOG(self.log_path, self.log_level)
        log2disk(0, "Command: %s" % str(sys.argv))

        rhnSQL.initDB()
        initCFG('server.satellite')

        verify_mappings()

        f = None
        # try block in try block - this is hack for python 2.4 compatibility
        # to support finally
        try:
            try:
                # Channel families mapping to channels
                f = open(constants.CHANNEL_FAMILY_MAPPING_PATH, 'r')
                self.families = json.load(f)
                f.close()

                # Channel metadata
                f = open(constants.CHANNEL_DEFINITIONS_PATH, 'r')
                self.channel_metadata = json.load(f)
                f.close()

                # Dist/Release channel mapping
                f = open(constants.CHANNEL_DIST_MAPPING_PATH, 'r')
                self.channel_dist_mapping = json.load(f)
                f.close()

                # Kickstart metadata
                f = open(constants.KICKSTART_DEFINITIONS_PATH, 'r')
                self.kickstart_metadata = json.load(f)
                f.close()
            except IOError:
                e = sys.exc_info()[1]
                raise CdnMappingsLoadError("Problem with loading file: %s" % e)
        finally:
            if f is not None:
                f.close()

        # Map channels to their channel family
        self.channel_to_family = {}
        for family in self.families:
            for channel in self.families[family]['channels']:
                self.channel_to_family[channel] = family

        # Set already synced channels
        h = rhnSQL.prepare("""
            select label from rhnChannel where org_id is null
        """)
        h.execute()
        channels = h.fetchall_dict() or []
        self.synced_channels = [ch['label'] for ch in channels]
开发者ID:shastah,项目名称:spacewalk,代码行数:72,代码来源:cdnsync.py

示例14: send

def send(url, sendData=None):
    """Connect to url and return the result as stringIO

    :arg url: the url where the request will be sent
    :kwarg sendData: do a post-request when "sendData" is given.

    Returns the result as stringIO object.

    """
    connect_retries = 10
    try_counter = connect_retries
    timeout = 120
    if CFG.is_initialized() and CFG.has_key('TIMEOUT'):
        timeout = CFG.TIMEOUT
    curl = pycurl.Curl()

    curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
    curl.setopt(pycurl.URL, url)
    curl.setopt(pycurl.DEBUGFUNCTION, _curl_debug)
    curl.setopt(pycurl.VERBOSE, True)
    proxy_url, proxy_user, proxy_pass = get_proxy(url)
    if proxy_url:
        curl.setopt(pycurl.PROXY, proxy_url)
    log_debug(2, "Connect to %s" % url)
    if sendData is not None:
        curl.setopt(pycurl.POSTFIELDS, sendData)
        if (CFG.is_initialized() and
                CFG.has_key('DISABLE_EXPECT') and
                CFG.DISABLE_EXPECT):
            # disable Expect header
            curl.setopt(pycurl.HTTPHEADER, ['Expect:'])

    # We implement our own redirection-following, because pycurl
    # 7.19 doesn't POST after it gets redirected. Ideally we'd be
    # using pycurl.POSTREDIR here, but that's in 7.21.
    curl.setopt(pycurl.FOLLOWLOCATION, False)

    response = StringIO()
    curl.setopt(pycurl.WRITEFUNCTION, response.write)

    try_counter = connect_retries
    while try_counter:
        try_counter -= 1
        try:
            curl.perform()
        except pycurl.error, e:
            if e[0] == 56:  # Proxy requires authentication
                log_debug(2, e[1])
                if not (proxy_user and proxy_pass):
                    raise TransferException("Proxy requires authentication, "
                                            "but reading credentials from "
                                            "%s failed." % YAST_PROXY)
                curl.setopt(pycurl.PROXYUSERPWD,
                            "%s:%s" % (proxy_user, proxy_pass))
            elif e[0] == 60:
                log_error("Peer certificate could not be authenticated "
                          "with known CA certificates.")
                raise TransferException("Peer certificate could not be "
                                        "authenticated with known CA "
                                        "certificates.")
            else:
                log_error(e[1])
                raise

        status = curl.getinfo(pycurl.HTTP_CODE)
        if status == 200 or (URL(url).scheme == "file" and status == 0):
            # OK or file
            break
        elif status in (301, 302):  # redirects
            url = curl.getinfo(pycurl.REDIRECT_URL)
            log_debug(2, "Got redirect to %s" % url)
            curl.setopt(pycurl.URL, url)
开发者ID:m47ik,项目名称:uyuni,代码行数:72,代码来源:suseLib.py

示例15: main

def main():
    # Initialize a command-line processing object with a table of options
    optionsTable = [
        Option('-v', '--verbose',   action='count',      help='Increase verbosity'),
        Option('-d', '--dir',       action='store',      help='Process packages from this directory'),
        Option('-L', '--cache-locally', action='store_true',
               help='Locally cache packages so that Proxy will not ever need to '
               + 'download them. Changes nothing on the upstream server.'),
        Option('-e', '--from-export', action='store', dest='export_location',
               help='Process packages from this channel export. Can only be used '
               + 'with --cache-locally or --copyonly.'),
        Option('-c', '--channel',   action='append',
               help='Channel to operate on. When used with --from-export '
               + 'specifies channels to cache rpms for, else specifies channels '
               + 'that we will be pushing into.'),
        Option('-n', '--count',     action='store',      help='Process this number of headers per call', type='int'),
        Option('-l', '--list',      action='store_true', help='Only list the specified channels'),
        Option('-s', '--sync',      action='store_true', help='Check if in sync with the server'),
        Option('-p', '--printconf', action='store_true', help='Print the configuration and exit'),
        Option('-X', '--exclude',   action="append",     help="Exclude packages that match this glob expression"),
        Option('--newest',    action='store_true', help='Only push the files that are newer than the server ones'),
        Option('--stdin',     action='store_true', help='Read the package names from stdin'),
        Option('--nosig',     action='store_true', help="Push unsigned packages"),
        Option('--username',  action='store',      help='Use this username to connect to RHN'),
        Option('--password',  action='store',      help='Use this password to connect to RHN'),
        Option('--source',    action='store_true', help='Upload source package headers'),
        Option('--dontcopy',  action='store_true', help='Do not copy packages to the local directory'),
        Option('--copyonly',  action='store_true',
               help="Only copy packages; don't reimport. Same as --cache-locally"),
        Option('--test',      action='store_true', help='Only print the packages to be pushed'),
        Option('-N', '--new-cache',  action='store_true', help='Create a new username/password cache'),
        Option('--no-ssl',    action='store_true', help='Turn off SSL (not recommended).'),
        Option('--no-session-caching',  action='store_true',
               help='Disables session-token authentication.'),
        Option('-?', '--usage',     action='store_true', help="Briefly describe the options"),
    ]
    # Process the command line arguments
    optionParser = OptionParser(option_list=optionsTable, usage="USAGE: %prog [OPTION] [<package>]")
    options, files = optionParser.parse_args()
    upload = UploadClass(options, files=files)

    if options.usage:
        optionParser.print_usage()
        sys.exit(0)

    if options.printconf:
        CFG.show()
        return

    if options.list:
        upload.list()
        return

    if options.sync:
        upload.checkSync()
        return

    # It's just an alias to copyonly
    if options.cache_locally:
        options.copyonly = True

    # remeber to process dir option before export, export can overwrite dir
    if options.dir:
        upload.directory()
    if options.export_location:
        if not options.copyonly:
            upload.die(0, "--from-export can only be used with --cache-locally"
                       + " or --copyonly")
        if options.source:
            upload.die(0, "--from-export cannot be used with --source")
        upload.from_export()
    if options.stdin:
        upload.readStdin()

    # if we're going to allow the user to specify packages by dir *and* export
    # *and* stdin *and* package list (why not?) then we have to uniquify
    # the list afterwards. Sort just for user-friendly display.
    upload.files = sorted(list(set(upload.files)))

    if options.copyonly:
        if not upload.files:
            upload.die(0, "Nothing to do; exiting. Try --help")
        if options.test:
            upload.test()
            return
        upload.copyonly()
        return

    if options.exclude:
        upload.filter_excludes()

    if options.newest:
        upload.newest()

    if not upload.files:
        upload.die(0, "Nothing to do; exiting. Try --help")

    if options.test:
        upload.test()
        return
#.........这里部分代码省略.........
开发者ID:phurrelmann,项目名称:spacewalk,代码行数:101,代码来源:rhn_package_manager.py


注:本文中的spacewalk.common.rhnConfig.CFG类示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。