def __init__(self, config): self.config = config util.initLogging(config["verbose"], config.get("log_path", ""), config.get("enable_loggers", [])) util.log("Default encoding: %s (file system: %s)" % (sys.getdefaultencoding(), sys.getfilesystemencoding())) # Evaluate configuration and set defaults _checkConfig(config) provider_mapping = self.config["provider_mapping"] # response_trailer = config.get("response_trailer", "") self._verbose = config.get("verbose", 2) lockStorage = config.get("locksmanager") if lockStorage is True: lockStorage = LockStorageDict() if not lockStorage: locksManager = None else: locksManager = LockManager(lockStorage) propsManager = config.get("propsmanager") if not propsManager: # Normalize False, 0 to None propsManager = None elif propsManager is True: propsManager = PropertyManager() mount_path = config.get("mount_path") # Instantiate DAV resource provider objects for every share self.providerMap = {} for (share, provider) in provider_mapping.items(): # Make sure share starts with, or is, '/' share = "/" + share.strip("/") # We allow a simple string as 'provider'. In this case we interpret # it as a file system root folder that is published. if isinstance(provider, basestring): provider = FilesystemProvider(provider) assert isinstance(provider, DAVProvider) provider.setSharePath(share) if mount_path: provider.setMountPath(mount_path) # TODO: someday we may want to configure different lock/prop managers per provider provider.setLockManager(locksManager) provider.setPropManager(propsManager) self.providerMap[share] = { "provider": provider, "allow_anonymous": False } # Define WSGI application stack application = RequestResolver() domain_controller = None dir_browser = config.get("dir_browser", {}) middleware_stack = config.get("middleware_stack", []) # Replace WsgiDavDirBrowser to custom class for backward compatibility only # In normal way you should insert it into middleware_stack if dir_browser.get("enable", True) and "app_class" in dir_browser.keys(): config["middleware_stack"] = [ m if m != WsgiDavDirBrowser else dir_browser['app_class'] for m in middleware_stack ] for mw in middleware_stack: if mw.isSuitable(config): if self._verbose >= 2: print "Middleware %s is suitable" % mw application = mw(application, config) if issubclass(mw, HTTPAuthenticator): domain_controller = application.getDomainController() # check anonymous access for share, data in self.providerMap.items(): if application.allowAnonymousAccess(share): data['allow_anonymous'] = True else: if self._verbose >= 2: print "Middleware %s is not suitable" % mw # Print info if self._verbose >= 2: print "Using lock manager: %r" % locksManager print "Using property manager: %r" % propsManager print "Using domain controller: %s" % domain_controller print "Registered DAV providers:" for share, data in self.providerMap.items(): hint = " (anonymous)" if data['allow_anonymous'] else "" print " Share '%s': %s%s" % (share, provider, hint) if self._verbose >= 1: for share, data in self.providerMap.items(): if data['allow_anonymous']: # TODO: we should only warn here, if --no-auth is not given print "WARNING: share '%s' will allow anonymous access." % share self._application = application
def __init__(self, config): self.config = copy.deepcopy(DEFAULT_CONFIG) util.deep_update(self.config, config) # self.config.update(config) config = self.config # Evaluate configuration and set defaults _check_config(config) # response_trailer = config.get("response_trailer", "") self.verbose = config.get("verbose", 3) lockStorage = config.get("lock_manager") if lockStorage is True: lockStorage = LockStorageDict() if not lockStorage: self.locksManager = None else: self.locksManager = LockManager(lockStorage) self.propsManager = config.get("property_manager") if not self.propsManager: # Normalize False, 0 to None self.propsManager = None elif self.propsManager is True: self.propsManager = PropertyManager() self.mount_path = config.get("mount_path") # Instantiate DAV resource provider objects for every share # provider_mapping may contain the args that are passed to a `FilesystemProvider` # instance: # <mount_path>: <folder_path> # or # <mount_path>: [folder_path, is_readonly] # or contain a complete new instance: # <mount_path>: <DAVProvider Instance> provider_mapping = self.config["provider_mapping"] self.providerMap = {} self.sortedShareList = None for share, provider in provider_mapping.items(): self.add_provider(share, provider) domain_controller = None # Define WSGI application stack middleware_stack = config.get("middleware_stack", []) mw_list = [] # This is the 'outer' application, i.e. the WSGI application object that # is eventually called by the server. self.application = self # When building up the middleware stack, this app will be wrapped and replaced by the # next middleware in the list. # The `middleware_stack` is configured such that the first app in the list should be # called first. But since every app wraps its predecessor, we iterate in reverse # order: for mw in reversed(middleware_stack): # The middleware stack configuration may contain plain strings, dicts, # classes, or objects app = None if compat.is_basestring(mw): # If a plain string is passed, try to import it, assuming BaseMiddleware # signature app_class = dynamic_import_class(mw) app = app_class(self, self.application, config) elif type(mw) is dict: # If a dict with one entry is passed, use the key as module/class name # and the value as constructor arguments (positional or kwargs). assert len(mw) == 1 name, args = list(mw.items())[0] expand = {"${application}": self.application} app = dynamic_instantiate_middleware(name, args, expand) elif inspect.isclass(mw): # If a class is passed, assume BaseMiddleware (or compatible) assert issubclass( mw, BaseMiddleware ) # TODO: remove this assert with 3.0 app = mw(self, self.application, config) else: # Otherwise assume an initialized middleware instance app = mw # TODO: We should try to generalize this specific code: if isinstance(app, HTTPAuthenticator): domain_controller = app.get_domain_controller() # Check anonymous access for share, data in self.providerMap.items(): if app.allow_anonymous_access(share): data["allow_anonymous"] = True # Add middleware to the stack if app: mw_list.append(app) self.application = app else: _logger.error("Could not add middleware {}.".format(mw)) # Print info _logger.info( "WsgiDAV/{} Python/{} {}".format( __version__, util.PYTHON_VERSION, platform.platform(aliased=True) ) ) if self.verbose >= 4: _logger.info( "Default encoding: {!r} (file system: {!r})".format( sys.getdefaultencoding(), sys.getfilesystemencoding() ) ) _logger.info("Lock manager: {}".format(self.locksManager)) _logger.info("Property manager: {}".format(self.propsManager)) _logger.info("Domain controller: {}".format(domain_controller)) # We traversed the stack in reverse order. Now revert again, so # we see the order that was configured: _logger.info("Middleware stack:") for mw in reversed(mw_list): _logger.info(" - {}".format(mw)) _logger.info("Registered DAV providers by route:") for share in self.sortedShareList: data = self.providerMap[share] hint = " (anonymous)" if data["allow_anonymous"] else "" _logger.info(" - '{}': {}{}".format(share, data["provider"], hint)) for share, data in self.providerMap.items(): if data["allow_anonymous"]: # TODO: we should only warn here, if --no-auth is not given _logger.warn("Share '{}' will allow anonymous access.".format(share)) return
def __init__(self, config): self.config = config # Do not initialize logging here, because we want to keep silence in library-mode # util.initLogging(config["verbose"], config.get("enable_loggers", [])) _logger.info("Default encoding: {} (file system: {})".format( sys.getdefaultencoding(), sys.getfilesystemencoding())) # Evaluate configuration and set defaults _checkConfig(config) provider_mapping = self.config["provider_mapping"] # response_trailer = config.get("response_trailer", "") self._verbose = config.get("verbose", 3) lockStorage = config.get("locksmanager") if lockStorage is True: lockStorage = LockStorageDict() if not lockStorage: locksManager = None else: locksManager = LockManager(lockStorage) propsManager = config.get("propsmanager") if not propsManager: # Normalize False, 0 to None propsManager = None elif propsManager is True: propsManager = PropertyManager() mount_path = config.get("mount_path") # Instantiate DAV resource provider objects for every share self.providerMap = {} for (share, provider) in provider_mapping.items(): # Make sure share starts with, or is, '/' share = "/" + share.strip("/") # We allow a simple string as 'provider'. In this case we interpret # it as a file system root folder that is published. if compat.is_basestring(provider): provider = FilesystemProvider(provider) assert isinstance(provider, DAVProvider) provider.setSharePath(share) if mount_path: provider.setMountPath(mount_path) # TODO: someday we may want to configure different lock/prop # managers per provider provider.setLockManager(locksManager) provider.setPropManager(propsManager) self.providerMap[share] = { "provider": provider, "allow_anonymous": False, } # Define WSGI application stack application = RequestResolver() domain_controller = None dir_browser = config.get("dir_browser", {}) middleware_stack = config.get("middleware_stack", []) if dir_browser.get("app_class"): _logger.error("") # # Replace WsgiDavDirBrowser to custom class for backward compatibility only # # In normal way you should insert it into middleware_stack # if dir_browser.get("enable", True) and "app_class" in dir_browser.keys(): # config["middleware_stack"] = [m if m != WsgiDavDirBrowser else dir_browser[ # "app_class"] for m in middleware_stack] _logger.info("Middleware stack:") for mw in middleware_stack: if mw.isSuitable(config): # if self._verbose >= 2: _logger.info(" - {}".format(mw)) application = mw(application, config) if issubclass(mw, HTTPAuthenticator): domain_controller = application.getDomainController() # check anonymous access for share, data in self.providerMap.items(): if application.allowAnonymousAccess(share): data["allow_anonymous"] = True else: # if self._verbose >= 2: _logger.warn( "- SKIPPING middleware {} (not suitable)".format(mw)) # Print info if self._verbose >= 3: _logger.info("Using lock manager: {!r}".format(locksManager)) _logger.info("Using property manager: {!r}".format(propsManager)) _logger.info( "Using domain controller: {!r}".format(domain_controller)) _logger.info("Registered DAV providers:") for share, data in self.providerMap.items(): hint = " (anonymous)" if data["allow_anonymous"] else "" _logger.info(" Share '{}': {}{}".format( share, provider, hint)) if self._verbose >= 2: for share, data in self.providerMap.items(): if data["allow_anonymous"]: # TODO: we should only warn here, if --no-auth is not given _logger.warn( "WARNING: share '{}' will allow anonymous access.". format(share)) self._application = application
def __init__(self, config): self.config = copy.deepcopy(DEFAULT_CONFIG) util.deep_update(self.config, config) config = self.config # Evaluate configuration and set defaults _check_config(config) self.verbose = config.get("verbose", 3) hotfixes = config.get("hotfixes", {}) self.re_encode_path_info = hotfixes.get("re_encode_path_info", None) if self.re_encode_path_info is None: self.re_encode_path_info = compat.PY3 self.unquote_path_info = hotfixes.get("unquote_path_info", False) lock_storage = config.get("lock_manager") if lock_storage is True: lock_storage = LockStorageDict() if not lock_storage: self.lock_manager = None else: self.lock_manager = LockManager(lock_storage) self.prop_manager = config.get("property_manager") if not self.prop_manager: # Normalize False, 0 to None self.prop_manager = None elif self.prop_manager is True: self.prop_manager = PropertyManager() self.mount_path = config.get("mount_path") auth_conf = config.get("http_authenticator", {}) # Instantiate DAV resource provider objects for every share. # provider_mapping may contain the args that are passed to a # `FilesystemProvider` instance: # <mount_path>: <folder_path> # or # <mount_path>: { "root": <folder_path>, "readonly": True } # or contain a complete new instance: # <mount_path>: <DAVProvider Instance> provider_mapping = self.config["provider_mapping"] self.provider_map = {} self.sorted_share_list = None for share, provider in provider_mapping.items(): self.add_provider(share, provider) self.http_authenticator = None domain_controller = None # Define WSGI application stack middleware_stack = config.get("middleware_stack", []) mw_list = [] # This is the 'outer' application, i.e. the WSGI application object that # is eventually called by the server. self.application = self # The `middleware_stack` is configured such that the first app in the # list should be called first. Since every app wraps its predecessor, we # iterate in reverse order: for mw in reversed(middleware_stack): # The middleware stack configuration may contain plain strings, dicts, # classes, or objects app = None if compat.is_basestring(mw): # If a plain string is passed, try to import it, assuming # `BaseMiddleware` signature app_class = dynamic_import_class(mw) app = app_class(self, self.application, config) elif type(mw) is dict: # If a dict with one entry is passed, use the key as module/class name # and the value as constructor arguments (positional or kwargs). assert len(mw) == 1 name, args = list(mw.items())[0] expand = {"${application}": self.application} app = dynamic_instantiate_middleware(name, args, expand) elif inspect.isclass(mw): # If a class is passed, assume BaseMiddleware (or compatible) assert issubclass( mw, BaseMiddleware) # TODO: remove this assert with 3.0 app = mw(self, self.application, config) else: # Otherwise assume an initialized middleware instance app = mw # Remember if isinstance(app, HTTPAuthenticator): self.http_authenticator = app domain_controller = app.get_domain_controller() # Add middleware to the stack if app: if callable(getattr(app, "is_disabled", None)) and app.is_disabled(): _logger.warning( "App {}.is_disabled() returned True: skipping.".format( app)) else: mw_list.append(app) self.application = app else: _logger.error("Could not add middleware {}.".format(mw)) domain_controller # Print info _logger.info("WsgiDAV/{} Python/{} {}".format( __version__, util.PYTHON_VERSION, platform.platform(aliased=True))) if self.verbose >= 4: _logger.info("Default encoding: {!r} (file system: {!r})".format( sys.getdefaultencoding(), sys.getfilesystemencoding())) if self.verbose >= 3: _logger.info("Lock manager: {}".format(self.lock_manager)) _logger.info("Property manager: {}".format(self.prop_manager)) _logger.info("Domain controller: {}".format(domain_controller)) if self.verbose >= 4: # We traversed the stack in reverse order. Now revert again, so # we see the order that was configured: _logger.info("Middleware stack:") for mw in reversed(mw_list): _logger.info(" - {}".format(mw)) if self.verbose >= 3: _logger.info("Registered DAV providers by route:") for share in self.sorted_share_list: provider = self.provider_map[share] hint = (" (anonymous)" if domain_controller.is_share_anonymous(share) else "") _logger.info(" - '{}': {}{}".format(share, provider, hint)) if auth_conf.get("accept_basic") and not config.get("ssl_certificate"): _logger.warning( "Basic authentication is enabled: It is highly recommended to enable SSL." ) if domain_controller: for share, provider in self.provider_map.items(): if domain_controller.is_share_anonymous(share): _logger.warning( "Share '{}' will allow anonymous {} access.".format( share, "read" if provider.is_readonly() else "write")) return
def __init__(self, config): self.config = config util.initLogging(config["verbose"], config.get("enable_loggers", [])) util.log("Default encoding: %s (file system: %s)" % (sys.getdefaultencoding(), sys.getfilesystemencoding())) # Evaluate configuration and set defaults _checkConfig(config) provider_mapping = self.config["provider_mapping"] # response_trailer = config.get("response_trailer", "") self._verbose = config.get("verbose", 2) lockStorage = config.get("locksmanager") if lockStorage is True: lockStorage = LockStorageDict() if not lockStorage: locksManager = None else: locksManager = LockManager(lockStorage) propsManager = config.get("propsmanager") if not propsManager: # Normalize False, 0 to None propsManager = None elif propsManager is True: propsManager = PropertyManager() mount_path = config.get("mount_path") user_mapping = self.config.get("user_mapping", {}) domainController = config.get( "domaincontroller") or WsgiDAVDomainController(user_mapping) isDefaultDC = isinstance(domainController, WsgiDAVDomainController) # authentication fields authacceptbasic = config.get("acceptbasic", True) authacceptdigest = config.get("acceptdigest", True) authdefaultdigest = config.get("defaultdigest", True) # Check configuration for NTDomainController # We don't use 'isinstance', because include would fail on non-windows boxes. wdcName = "NTDomainController" if domainController.__class__.__name__ == wdcName: if authacceptdigest or authdefaultdigest or not authacceptbasic: util.warn( "WARNING: %s requires basic authentication.\n\tSet acceptbasic=True, acceptdigest=False, defaultdigest=False" % wdcName) # Instantiate DAV resource provider objects for every share self.providerMap = {} for (share, provider) in provider_mapping.items(): # Make sure share starts with, or is, '/' share = "/" + share.strip("/") # We allow a simple string as 'provider'. In this case we interpret # it as a file system root folder that is published. if isinstance(provider, basestring): provider = FilesystemProvider(provider) assert isinstance(provider, DAVProvider) provider.setSharePath(share) if mount_path: provider.setMountPath(mount_path) # TODO: someday we may want to configure different lock/prop managers per provider provider.setLockManager(locksManager) provider.setPropManager(propsManager) self.providerMap[share] = provider if self._verbose >= 2: print "Using lock manager: %r" % locksManager print "Using property manager: %r" % propsManager print "Using domain controller: %s" % domainController print "Registered DAV providers:" for share, provider in self.providerMap.items(): hint = "" if isDefaultDC and not user_mapping.get(share): hint = " (anonymous)" print " Share '%s': %s%s" % (share, provider, hint) # If the default DC is used, emit a warning for anonymous realms if isDefaultDC and self._verbose >= 1: for share in self.providerMap: if not user_mapping.get(share): # TODO: we should only warn here, if --no-auth is not given print "WARNING: share '%s' will allow anonymous access." % share # Define WSGI application stack application = RequestResolver() if config.get("dir_browser") and config["dir_browser"].get( "enable", True): application = WsgiDavDirBrowser(application) application = HTTPAuthenticator(application, domainController, authacceptbasic, authacceptdigest, authdefaultdigest) application = ErrorPrinter(application, catchall=False) application = WsgiDavDebugFilter(application, config) self._application = application