<commit_before>package peergos.user.fs;

import peergos.crypto.*;
import peergos.util.Serialize;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.*;

public class FileAccess
{
    // read permissions
    private SortedMap<UserPublicKey, AsymmetricLink> sharingR2parent = new TreeMap();
    private final SymmetricLink parent2meta;
    // write permissions
    private SortedMap<UserPublicKey, AsymmetricLink> sharingW2parent = new TreeMap();

    private final byte[] metadata;
    public static final int MAX_ELEMENT_SIZE = Integer.MAX_VALUE;

    public FileAccess(Set<UserPublicKey> sharingR, SymmetricKey metaKey, SymmetricKey parentKey,
                      Set<UserPublicKey> sharingW, byte[] rawMetadata)
    {
        this.parent2meta = new SymmetricLink(parentKey, metaKey);
        if (sharingR != null) {
            for (UserPublicKey key: sharingR)
                sharingR2parent.put(key, new AsymmetricLink(key, parentKey));
        }
        this.metadata = metaKey.encrypt(rawMetadata, parent2meta.initializationVector());
        if (sharingW != null) {
            for (UserPublicKey key: sharingW)
                sharingW2parent.put(key, new AsymmetricLink(key, parentKey));
        }
    }

    public FileAccess(SymmetricKey parentKey, byte[] rawMetadata)
    {
        this(null, SymmetricKey.random(), parentKey, null, rawMetadata);
    }

    public FileAccess(byte[] m, byte[] p2m, Map<UserPublicKey, AsymmetricLink> sharingR)
    {
        metadata = m;
        parent2meta = new SymmetricLink(p2m);
        sharingR2parent.putAll(sharingR);
    }

    public void serialize(DataOutput dout) throws IOException
    {
        Serialize.serialize(metadata, dout);
        Serialize.serialize(parent2meta.serialize(), dout);
        dout.writeInt(sharingR2parent.size());
        for (UserPublicKey key: sharingR2parent.keySet()) {
            Serialize.serialize(key.getPublicKey(), dout);
            Serialize.serialize(sharingR2parent.get(key).serialize(), dout);
        }
    }

    public static FileAccess deserialize(DataInput din) throws IOException
    {
        byte[] meta = Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE);
        byte[] p2m = Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE);
        int count = din.readInt();
        Map<UserPublicKey, AsymmetricLink> sharingR = new HashMap();
        for (int i=0; i < count; i++) {
            sharingR.put(new UserPublicKey(Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE)),
                    new AsymmetricLink(Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE)));
        }
        FileAccess res = new FileAccess(meta, p2m, sharingR);
        return res;
    }

    public SymmetricKey getMetaKey(SymmetricKey parentKey)
    {
        return parent2meta.target(parentKey);
    }

    public SymmetricKey getParentKey(User sharingKey)
    {
        return sharingR2parent.get(sharingKey.getKey()).target(sharingKey);
    }

    public byte[] getMetadata(SymmetricKey metaKey)
    {
        return metaKey.decrypt(metadata, parent2meta.initializationVector());
    }
}
<commit_msg>granting write access to a file but not to the enclosing folder doesn't make sense, as adding knew blocks needs write access to the folder too. So file write access is inherited from the parent folder.<commit_after>package peergos.user.fs;

import peergos.crypto.*;
import peergos.util.Serialize;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.*;

public class FileAccess
{
    // read permissions
    private SortedMap<UserPublicKey, AsymmetricLink> sharingR2parent = new TreeMap();
    private final SymmetricLink parent2meta;

    private final byte[] metadata;
    public static final int MAX_ELEMENT_SIZE = Integer.MAX_VALUE;

    public FileAccess(Set<UserPublicKey> sharingR, SymmetricKey metaKey, SymmetricKey parentKey, byte[] rawMetadata)
    {
        this.parent2meta = new SymmetricLink(parentKey, metaKey);
        if (sharingR != null) {
            for (UserPublicKey key: sharingR)
                sharingR2parent.put(key, new AsymmetricLink(key, parentKey));
        }
        this.metadata = metaKey.encrypt(rawMetadata, parent2meta.initializationVector());
    }

    public FileAccess(SymmetricKey parentKey, byte[] rawMetadata)
    {
        this(null, SymmetricKey.random(), parentKey, rawMetadata);
    }

    public FileAccess(byte[] m, byte[] p2m, Map<UserPublicKey, AsymmetricLink> sharingR)
    {
        metadata = m;
        parent2meta = new SymmetricLink(p2m);
        sharingR2parent.putAll(sharingR);
    }

    public void serialize(DataOutput dout) throws IOException
    {
        Serialize.serialize(metadata, dout);
        Serialize.serialize(parent2meta.serialize(), dout);
        dout.writeInt(sharingR2parent.size());
        for (UserPublicKey key: sharingR2parent.keySet()) {
            Serialize.serialize(key.getPublicKey(), dout);
            Serialize.serialize(sharingR2parent.get(key).serialize(), dout);
        }
    }

    public static FileAccess deserialize(DataInput din) throws IOException
    {
        byte[] meta = Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE);
        byte[] p2m = Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE);
        int count = din.readInt();
        Map<UserPublicKey, AsymmetricLink> sharingR = new HashMap();
        for (int i=0; i < count; i++) {
            sharingR.put(new UserPublicKey(Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE)),
                    new AsymmetricLink(Serialize.deserializeByteArray(din, MAX_ELEMENT_SIZE)));
        }
        FileAccess res = new FileAccess(meta, p2m, sharingR);
        return res;
    }

    public SymmetricKey getMetaKey(SymmetricKey parentKey)
    {
        return parent2meta.target(parentKey);
    }

    public SymmetricKey getParentKey(User sharingKey)
    {
        return sharingR2parent.get(sharingKey.getKey()).target(sharingKey);
    }

    public byte[] getMetadata(SymmetricKey metaKey)
    {
        return metaKey.decrypt(metadata, parent2meta.initializationVector());
    }
}

{'fraction_non_alphanumeric': 0.09652258693532662, 'fraction_numerical': 0.006499837504062398, 'mean_word_length': 3.2157534246575343, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1662440', 'n_tokens_mistral': 1797, 'n_tokens_neox': 1752, 'n_words': 397}