def RenderBranch(self, path, request): """Renders tree leafs for filesystem path.""" aff4_root = rdfvalue.RDFURN(request.REQ.get("aff4_root", aff4.ROOT_URN)) container = request.REQ.get("container") if not container: raise RuntimeError("Container not provided.") # Path is relative to the aff4 root specified. urn = aff4_root.Add(path) # Open the container container = aff4.FACTORY.Open(container, token=request.token) # Find only direct children of this tree branch. # NOTE: Although all AFF4Volumes are also containers, this gui element is # really only suitable for showing AFF4Collection objects which are not very # large, since we essentially list all members. query_expression = ("subject matches '%s.+'" % utils.EscapeRegex(urn)) branches = set() for child in container.Query(query_expression): try: branch, _ = child.urn.RelativeName(urn).split("/", 1) branches.add(branch) except ValueError: pass # This actually sorts by the URN (which is UTF8) - I am not sure about the # correct sorting order for unicode string? directory_like = list(branches) directory_like.sort(cmp=locale.strcoll) for d in directory_like: self.AddElement(d)
def Resolve(self, subject, predicate, token=None): """Retrieve a value set for a subject's predicate. This method is easy to use but always gets the latest version of the attribute. It is more flexible and efficient to use the other Resolve methods. Args: subject: The subject URN. predicate: The predicate URN. token: An ACL token. Returns: A (value, timestamp in microseconds) stored in the datastore cell, or (None, 0) or a (decoded protobuf, timestamp) if protobuf was specified. Value will be the same type as originally stored with Set(). Raises: AccessError: if anything goes wrong. """ for _, value, timestamp in self.ResolveMulti( subject, [utils.EscapeRegex(predicate)], token=token, timestamp=self.NEWEST_TIMESTAMP): # Just return the first one. return value, timestamp return (None, 0)
def Startswith(attribute, filter_implemention, string): return filter_implemention.PredicateContainsFilter( attribute, "^" + utils.EscapeRegex(string))
def Startswith(unused_attribute, filter_implemention, string): return filter_implemention.SubjectContainsFilter( "^" + utils.EscapeRegex(string))
def BuildTable(self, start_row, end_row, request): """Populate the table.""" # Default sort direction sort = request.REQ.get("sort", "Name:asc") try: reverse_sort = sort.split(":")[1] == "desc" except IndexError: reverse_sort = False filter_term = request.REQ.get("filter") aff4_path = request.REQ.get("aff4_path", self.root_path) urn = rdfvalue.RDFURN(aff4_path) filter_string = None if filter_term: column, regex = filter_term.split(":", 1) escaped_regex = utils.EscapeRegex(aff4_path + "/") # The start anchor refers only to this directory. if regex.startswith("^"): escaped_regex += utils.EscapeRegex(regex[1:]) else: escaped_regex += ".*" + utils.EscapeRegex(regex) filter_string = "subject matches '%s'" % escaped_regex # For now we just list the directory try: key = utils.SmartUnicode(urn) if filter_string: key += ":" + filter_string # Open the directory as a directory. directory_node = aff4.FACTORY.Open(urn, token=request.token).Upgrade( "VFSDirectory") if not directory_node: raise IOError() key += str(directory_node.Get(directory_node.Schema.LAST)) key += ":" + str(request.token) try: children = self.content_cache.Get(key) except KeyError: # Only show the direct children. children = sorted(directory_node.Query(filter_string=filter_string, limit=100000)) # Filter the children according to types. if self.visible_types: children = [x for x in children if x.__class__.__name__ in self.visible_types] self.content_cache.Put(key, children) try: self.message = "Directory Listing '%s' was taken on %s" % ( aff4_path, directory_node.Get(directory_node.Schema.TYPE.age)) except AttributeError: pass except IOError: children = [] children.sort(reverse=reverse_sort) row_index = start_row # Make sure the table knows how large it is for paging. self.size = len(children) self.columns[1].base_path = urn for fd in children[start_row:end_row]: # We use the timestamp on the TYPE as a proxy for the last update time # of this object - its only an estimate. fd_type = fd.Get(fd.Schema.TYPE) if fd_type: self.AddCell(row_index, "Age", rdfvalue.RDFDatetime(fd_type.age)) self.AddCell(row_index, "Name", fd.urn) # Add the fd to all the columns for column in self.columns: # This sets AttributeColumns directly from their fd. if isinstance(column, semantic.AttributeColumn): column.AddRowFromFd(row_index, fd) if "Container" in fd.behaviours: self.AddCell(row_index, "Icon", dict(icon="directory", description="Directory")) else: self.AddCell(row_index, "Icon", dict(icon="file", description="File Like Object")) row_index += 1 if row_index > end_row: return
def Query(self, attributes=None, filter_obj=None, subject_prefix="", token=None, subjects=None, limit=100, timestamp=None): """Selects a set of subjects based on filters.""" if filter_obj: spec = filter_obj.FilterExpression() else: spec = {} try: skip, limit = limit except TypeError: skip = 0 if attributes is None: attributes = [] if u"aff4:type" not in attributes: attributes.append(u"aff4:type") # Make this lookup fast if subjects: subjects = set(subjects) attributes = [EscapeKey(x) for x in attributes] result_subjects = [] if subject_prefix: regex = utils.EscapeRegex(EscapeKey(subject_prefix)) spec = {"$and": [spec, {"_id": {"$regex": "^" + regex}}]} if subjects: expressions = [] for subject in subjects: regex = utils.EscapeRegex(EscapeKey(subject)) expressions.append({"_id": {"$regex": "^" + regex + "$"}}) spec = {"$and": [spec, {"$or": expressions}]} for document in self.collection.find(spec=spec, fields=attributes, skip=skip, limit=limit, slave_okay=True): try: subject = DecodeKey(document["_id"]) # Only yield those subjects which we are allowed to view. self.security_manager.CheckDataStoreAccess( token, [subject], "r") result = dict(subject=[(subject, 0)]) for key, values in document.items(): if isinstance(values, list): if timestamp: if timestamp == self.ALL_TIMESTAMPS: pass elif timestamp == self.NEWEST_TIMESTAMP: values.sort(key=lambda t: t["t"]) values = values[-1:] else: try: ts_start, ts_end = timestamp values = [ v for v in values if ts_start <= v["t"] <= ts_end ] except (ValueError, TypeError): raise RuntimeError( "Invalid timestamp value: %s" % utils.SmartStr(timestamp)) for v in values: result.setdefault(key, []).append( (Decode(v["v"]), v["t"])) result_subjects.append(result) except access_control.UnauthorizedAccess: pass result_subjects.sort() total_count = len(result_subjects) result_set = data_store.ResultSet(result_subjects) result_set.total_count = total_count return result_set