mirror of
https://github.com/henrybear327/Proton-API-Bridge.git
synced 2025-12-25 16:47:42 -05:00
163 lines
4.3 KiB
Go
163 lines
4.3 KiB
Go
package proton_api_bridge
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/henrybear327/Proton-API-Bridge/common"
|
|
|
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
|
"github.com/henrybear327/go-proton-api"
|
|
)
|
|
|
|
type ProtonDrive struct {
|
|
MainShare *proton.Share
|
|
RootLink *proton.Link
|
|
|
|
MainShareKR *crypto.KeyRing
|
|
AddrKR *crypto.KeyRing
|
|
|
|
Config *common.Config
|
|
|
|
c *proton.Client
|
|
m *proton.Manager
|
|
userKR *crypto.KeyRing
|
|
addrKRs map[string]*crypto.KeyRing
|
|
addrData []proton.Address
|
|
signatureAddress string
|
|
}
|
|
|
|
func NewDefaultConfig() *common.Config {
|
|
return common.NewConfigWithDefaultValues()
|
|
}
|
|
|
|
func NewProtonDrive(ctx context.Context, config *common.Config) (*ProtonDrive, error) {
|
|
/* Log in and logout */
|
|
m, c, userKR, addrKRs, addrData, err := common.Login(ctx, config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
/*
|
|
Current understanding (at the time of the commit)
|
|
|
|
The volume is the mount point.
|
|
|
|
A link is like a folder in POSIX.
|
|
|
|
A share is associated with a link to represent the access control,
|
|
and serves as an entry point to a location in the file structure (Volume).
|
|
It points to a link, of file or folder type, anywhere in the tree and holds a key called the ShareKey.
|
|
To access a link, of file or folder type, a user must be a member of a share.
|
|
|
|
A volume has a default share for access control and is owned by the creator of the volume.
|
|
A volume has a default link as it's root folder.
|
|
|
|
MIMETYPE holds type, e.g. folder, image/png, etc.
|
|
*/
|
|
volumes, err := listAllVolumes(ctx, c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// log.Printf("all volumes %#v", volumes)
|
|
|
|
mainShareID := ""
|
|
for i := range volumes {
|
|
// iOS drive: first active volume
|
|
if volumes[i].State == proton.VolumeStateActive {
|
|
mainShareID = volumes[i].Share.ShareID
|
|
}
|
|
}
|
|
// log.Println("total volumes", len(volumes), "mainShareID", mainShareID)
|
|
|
|
/* Get root folder from the main share of the volume */
|
|
mainShare, err := getShareByID(ctx, c, mainShareID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// check for main share integrity
|
|
{
|
|
mainShareCheck := false
|
|
shares, err := getAllShares(ctx, c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i := range shares {
|
|
if shares[i].ShareID == mainShare.ShareID &&
|
|
shares[i].LinkID == mainShare.LinkID &&
|
|
shares[i].Flags == proton.PrimaryShare &&
|
|
shares[i].Type == proton.ShareTypeMain {
|
|
mainShareCheck = true
|
|
}
|
|
}
|
|
|
|
if !mainShareCheck {
|
|
log.Printf("mainShare %#v", mainShare)
|
|
log.Printf("shares %#v", shares)
|
|
return nil, ErrMainSharePreconditionsFailed
|
|
}
|
|
}
|
|
|
|
// Note: rootLink's parentLinkID == ""
|
|
/*
|
|
Link holds the tree structure, for the clients, they represent the files and folders of a given volume.
|
|
They have a ParentLinkID that points to parent folders.
|
|
Links also hold the file name (encrypted) and a hash of the name for name collisions.
|
|
Link data is encrypted with its owning Share keyring.
|
|
*/
|
|
rootLink, err := c.GetLink(ctx, mainShare.ShareID, mainShare.LinkID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// log.Printf("rootLink %#v", rootLink)
|
|
|
|
// log.Printf("addrKRs %#v", addrKRs)=
|
|
addrKR := addrKRs[mainShare.AddressID]
|
|
// log.Println("addrKR CountDecryptionEntities", addrKR.CountDecryptionEntities())
|
|
|
|
mainShareKR, err := mainShare.GetKeyRing(addrKR)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// log.Println("mainShareKR CountDecryptionEntities", mainShareKR.CountDecryptionEntities())
|
|
|
|
return &ProtonDrive{
|
|
MainShare: mainShare,
|
|
RootLink: &rootLink,
|
|
|
|
MainShareKR: mainShareKR,
|
|
AddrKR: addrKR,
|
|
|
|
Config: config,
|
|
|
|
c: c,
|
|
m: m,
|
|
userKR: userKR,
|
|
addrKRs: addrKRs,
|
|
addrData: addrData,
|
|
signatureAddress: mainShare.Creator,
|
|
}, nil
|
|
}
|
|
|
|
func (protonDrive *ProtonDrive) Logout(ctx context.Context) error {
|
|
return common.Logout(ctx, protonDrive.Config, protonDrive.m, protonDrive.c, protonDrive.userKR, protonDrive.addrKRs)
|
|
}
|
|
|
|
func (protonDrive *ProtonDrive) About(ctx context.Context) (*proton.User, error) {
|
|
user, err := protonDrive.c.GetUser(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
func (protonDrive *ProtonDrive) GetLink(ctx context.Context, linkID string) (*proton.Link, error) {
|
|
link, err := protonDrive.c.GetLink(ctx, protonDrive.MainShare.ShareID, linkID)
|
|
return &link, err
|
|
}
|