ZDCNode

@interface ZDCNode <NSCoding, NSCopying>

ZDCNode encapsulates the metadata for a node. This includes the basic information needed by the framework to sync the node with the cloud.

Note

Do NOT subclass ZDCNode. It’s just for storing metadata. You’re free to store your objects however you prefer.

Every node in the treesystem can be thought of as 2 separate parts:

Node Metadata:

The metadata is everything needed by the treesystem to store a node, but excluding the actual content of the node. This includes information such as:

  • what is the name of the node
  • who is the parent of this node
  • who was permission to read / write this node
  • when was the node last modified in the cloud
  • various sync related information, such as eTag(s)
  • various crypto information needed for encrypting & decrypting the content

Node Data:

The data is the actual content of the node. In other words, the content that your app generates.

ZDCNode is responsible for the metadata. And you’re responsible for the data (using whatever objects, files, or formats you prefer).

During a pull, whenever ZeroDark discovers new nodes in the cloud, it will automatically create ZDCNode instances and then inform the ZeroDarkCloudDelegate about them.

When you want upload a new node to the cloud, a ZDCNode instance will be created and added to the treesystem. You can do this the easy way, via -[ZDCCloudTransaction createNodeWithPath:error:]. Or you can do it the manual way, via -[ZDCCloudTransaction createNode:error:]. Either way, once the node is created, the framework will queue and perform the upload operation(s) for it.

  • Creates a new ZDCNode instance.

    Before the node can be used by the framework, you’ll need to assign the parentID & name properties.

    Declaration

    Objective-C

    - (nonnull instancetype)initWithLocalUserID:(nonnull NSString *)localUserID;

    Swift

    init(localUserID: String)
  • Every ZDCNode has a uuid. This is commonly referred to as the nodeID:

    nodeID == ZDCNode.uuid

    The nodeID is only for referencing a ZDCNode instance in the LOCAL DATABASE. NodeID’s are NOT uploaded to the cloud, nor are they synced in any way.

    Declaration

    Objective-C

    @property (readonly, nonatomic) NSString *_Nonnull uuid;

    Swift

    var uuid: String { get }
  • A reference to the corresponding localUser. (localUserID == ZDCLocalUser.uuid)

    Declaration

    Objective-C

    @property (readonly, nonatomic) NSString *_Nonnull localUserID;

    Swift

    var localUserID: String { get }
  • A reference to the parent ZDCNode.uuid.

    Declaration

    Objective-C

    @property (readwrite, copy, nonatomic, nullable) NSString *parentID;

    Swift

    var parentID: String? { get set }
  • The cleartext name of the node. For example: Grandma’s famous pumpkin bread.recipe.

    Declaration

    Objective-C

    @property (readwrite, copy, nonatomic, nullable) NSString *name;

    Swift

    var name: String? { get set }
  • The shareList encompasses the permissions for the node.

    Declaration

    Objective-C

    @property (readonly, nonatomic) ZDCShareList *_Nonnull shareList;

    Swift

    var shareList: ZDCShareList { get }
  • Node’s can be assigned a burn date. which tells the server to automatically delete the node at the specified time.

    This is especially useful when:

  • you have temporary content that you want to cleanup from the cloud after a set time period
  • you’re sharing content with other users on a temporary basis

  • Note

    The time at which the server deletes the content isn’t exact. Currently the server performs this task as a batch operation every hour on the hour.

    Declaration

    Objective-C

    @property (readwrite, copy, nonatomic, nullable) NSDate *burnDate;

    Swift

    var burnDate: Date? { get set }
  • For incoming messages (in the inbox), this value will be set to the userID that sent the message.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSString *senderID;

    Swift

    var senderID: String? { get }
  • For outgoing messages & signals, this set contains the list of userID’s for which the system is still working on sending the node.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSSet<NSString *> *pendingRecipients;

    Swift

    var pendingRecipients: Set<String>? { get }
  • The symmetric key that’s used to encrypt & decrypt the node’s data. Every node uses a different (randomly generated) symmetric key.

    This property is created for you automatically. For locally created nodes, the property is randomly generated. For nodes that are pulled down from the server, the encryption key is extracted & decrypted from the cloud data.

    Declaration

    Objective-C

    @property (readonly, nonatomic) NSData *_Nonnull encryptionKey;

    Swift

    var encryptionKey: Data { get }
  • Random bits used for creating cloudName’s. Every node has a different salt.

    A node’s cloudName is generated by hashing the (cleartext) name, along with the parent directory’s dirSalt. Thus nodes with the exact same name, but in different directories, will actually have different names in the cloud.

    Declaration

    Objective-C

    @property (readonly, nonatomic) NSData *_Nonnull dirSalt;

    Swift

    var dirSalt: Data { get }
  • This value represents the dirPrefix to be used by all the children.

    A file’s cloudPath is: {treeID}/{dirPrefix_of_parent_node}/{cloudName}

    Declaration

    Objective-C

    @property (readonly, nonatomic) NSString *_Nonnull dirPrefix;

    Swift

    var dirPrefix: String { get }
  • Every node has a server-assigned uuid, called the cloudID. This value is immutable - once set by the server, it cannot be changed.

    The sync system uses the cloudID to detect when a node has been renamed or moved within the treesystem. Since the server assigns this value, it is unknown until either:

    • we’ve successfully uploaded the node’s RCRD to the server at least once
    • we’ve downloaded the node’s RCRD from the server at least once

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSString *cloudID;

    Swift

    var cloudID: String? { get }
  • The eTag value of the RCRD file in the cloud.

    If this value is nil, then the node was created on this device, and hasn’t been updated yet.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSString *eTag_rcrd;

    Swift

    var eTag_rcrd: String? { get }
  • The eTag value of the data fork in the cloud.

    If this value is nil, any of the following could be true:

    • the node was created on this device, and hasn’t been uploaded yet
    • there isn’t a data fork for this node (it’s an empty node)
    • the PullManager is in the process of updating, and hasn’t discovered it yet

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSString *eTag_data;

    Swift

    var eTag_data: String? { get }
  • Returns the later of the 2 dates: lastModified_rcrd & lastModified_data

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSDate *lastModified;

    Swift

    var lastModified: Date? { get }
  • The date in which the RCRD file was last modified on the server. This relates to the last time the node’s treesystem information was changed, such as permissions.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSDate *lastModified_rcrd;

    Swift

    var lastModified_rcrd: Date? { get }
  • The date in which the DATA file was last modified on the server. This relates to the last time the node’s content was changed.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSDate *lastModified_data;

    Swift

    var lastModified_data: Date? { get }
  • Stores the most recently downloaded information about the data file in the cloud.

    If you request any kind of download of the node via the DownloadManager, this information gets automatically updated for you.

    Warning

    This information is not necessarily up-to-date. It’s kept cached to allow you to inspect the previous data info before requesting a download.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) ZDCCloudDataInfo *cloudDataInfo;

    Swift

    var cloudDataInfo: ZDCCloudDataInfo? { get }
  • Typically the cloudName is calculated by hashing node.name along with parentNode.dirSalt. And thus there’s no need to store the cloudName as it can be calcualted on-the-fly.

    However, it’s possible for a node to arrive in our tree with a hash mismatch. That is, somebody didn’t follow the hashing rules, and the cloudName doesn’t match what we’d expect via hashing. If this occurs, we store the mismatched value here.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSString *explicitCloudName;

    Swift

    var explicitCloudName: String? { get }
  • Pointers may point to nodes in a different treesystem. These foreign nodes may be in a different user’s treesystem (e.g. user’s are collaborating). Or they may be in the treesystem of a different treeID (e.g. an app upgrade transition).

    In any case, the root node for the grafting operation has an anchor that points to the foreign location.

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) ZDCNodeAnchor *anchor;

    Swift

    var anchor: ZDCNodeAnchor? { get }
  • If the node is a pointer, specifies the ZDCNode.uuid that it points to.

    See

    -[ZDCNode isPointer]

    Declaration

    Objective-C

    @property (readonly, nonatomic, nullable) NSString *pointeeID;

    Swift

    var pointeeID: String? { get }
  • Convenience method: equivalent to (pointeeID != nil).

    Declaration

    Objective-C

    @property (readonly, nonatomic) BOOL isPointer;

    Swift

    var isPointer: Bool { get }
  • Returns True if the node is an outgoing signal (lightweight message).

    Declaration

    Objective-C

    @property (readonly, nonatomic) BOOL isSignal;

    Swift

    var isSignal: Bool { get }
  • Generates a random 512 bit value (64 bytes).

    Declaration

    Objective-C

    + (nonnull NSData *)randomEncryptionKey;

    Swift

    class func randomEncryptionKey() -> Data
  • Generates a random 160 bit value (20 bytes).

    Declaration

    Objective-C

    + (nonnull NSData *)randomDirSalt;

    Swift

    class func randomDirSalt() -> Data
  • Generates a random string suitable for use as a dirPrefix. These are 128 bits, encoded in hexadecimal as 32 characters.

    Declaration

    Objective-C

    + (nonnull NSString *)randomDirPrefix;

    Swift

    class func randomDirPrefix() -> String
  • Generates a random string suitable for use as a cloudName. These are 160 bits, encoded in zBase32 as 32 characters.

    Declaration

    Objective-C

    + (nonnull NSString *)randomCloudName;

    Swift

    class func randomCloudName() -> String