'Search for all matching objects under base using the query.
Args:
base -- dn to search under
scope -- search scope (base, subtree, onelevel)
filterstr -- filter objects by
attrlist -- attrs to return. Returns all attrs if not specified'

def search_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0):

    if server_fail:
        raise ldap.SERVER_DOWN
    if ((not filterstr) and (scope != ldap.SCOPE_BASE)):
        raise AssertionError('Search    without    filter    on    onelevel    or    subtree    scope')
    if (scope == ldap.SCOPE_BASE):
        try:
            item_dict = self.db[self.key(base)]
        except KeyError:
            LOG.debug('search    fail:    dn    not    found    for    SCOPE_BASE')
            raise ldap.NO_SUCH_OBJECT
        results = [(base, item_dict)]
    elif (scope == ldap.SCOPE_SUBTREE):
        try:
            item_dict = self.db[self.key(base)]
        except KeyError:
            LOG.debug('search    fail:    dn    not    found    for    SCOPE_SUBTREE')
            raise ldap.NO_SUCH_OBJECT
        results = [(base, item_dict)]
        extraresults = [(k[len(self.__prefix):], v) for (k, v) in self.db.items() if re.match(('%s.*,%s' % (re.escape(self.__prefix), re.escape(self.dn(base)))), k)]
        results.extend(extraresults)
    elif (scope == ldap.SCOPE_ONELEVEL):
        def get_entries():
            base_dn = ldap.dn.str2dn(common.utf8_encode(base))
            base_len = len(base_dn)
            for (k, v) in self.db.items():
                if (not k.startswith(self.__prefix)):
                    continue
                k_dn_str = k[len(self.__prefix):]
                k_dn = ldap.dn.str2dn(common.utf8_encode(k_dn_str))
                if (len(k_dn) != (base_len + 1)):
                    continue
                if (k_dn[(- base_len):] != base_dn):
                    continue
                (yield (k_dn_str, v))
        results = list(get_entries())
    else:
        raise ldap.PROTOCOL_ERROR
    objects = []
    for (dn, attrs) in results:
        (id_attr, id_val, _) = ldap.dn.str2dn(common.utf8_encode(dn))[0][0]
        id_attr = common.utf8_decode(id_attr)
        id_val = common.utf8_decode(id_val)
        match_attrs = attrs.copy()
        match_attrs[id_attr] = [id_val]
        attrs_checked = set()
        if ((not filterstr) or _match_query(common.utf8_decode(filterstr), match_attrs, attrs_checked)):
            if (filterstr and (scope != ldap.SCOPE_BASE) and ('objectclass' not in attrs_checked)):
                raise AssertionError('No    objectClass    in    search    filter')
            attrs = {k: v for (k, v) in attrs.items() if ((not attrlist) or (k in common.utf8_decode(attrlist)))}
            objects.append((dn, attrs))
    return objects
