// Creates a collection with a specific uniq element, used for friend collections func (this *MetaMgr) CreateSpecialCollection(owner *crypto.SecretIdentity, uniq *crypto.Digest) (cid string) { pubkey := owner.Public() cb := &collectionBasis{ Uniq: uniq, Owner: pubkey, } cid = crypto.HashOf(cb.Owner.Fingerprint(), cb.Uniq).String() existing := this.SyncMgr.Get(sync.RTBasis, cid, "$") if existing != nil { return cid } basis := &sync.Record{ RecordType: sync.RTBasis, Topic: cid, Key: "$", Author: pubkey.Fingerprint().String(), Value: transfer.AsBytes(cb), } signRecord(basis, owner) this.SyncMgr.Put(basis) owr := &sync.Record{ RecordType: sync.RTWriter, Topic: cid, Key: pubkey.Fingerprint().String(), Value: transfer.AsBytes(pubkey), } signRecord(owr, owner) this.SyncMgr.Put(owr) return }
// Writes meta-data, may fail if cid does not exist, or writer is not allowed func (this *MetaMgr) Put(cid string, writer *crypto.SecretIdentity, key string, data []byte) error { basisRec := this.SyncMgr.Get(sync.RTBasis, cid, "$") if basisRec == nil { return fmt.Errorf("Unable to write to cid '%s', doesn't exist!", cid) } myFingerprint := writer.Public().Fingerprint().String() myPerm := this.SyncMgr.Get(sync.RTWriter, cid, myFingerprint) if myPerm == nil { return fmt.Errorf("Unable to write to cid '%s', '%s' doesn't have permission", cid, myFingerprint) } old := this.SyncMgr.Get(sync.RTData, cid, key) priority := 0 if old != nil { priority = old.Priority + 1 } rec := &sync.Record{ RecordType: sync.RTData, Topic: cid, Key: key, Value: data, Priority: priority, Author: myFingerprint, } signRecord(rec, writer) if old != nil { this.doCallbacks(cid, key, old.Value, myFingerprint, false) } this.SyncMgr.Put(rec) this.doCallbacks(cid, key, data, myFingerprint, true) return nil }
func main() { user, err := user.Current() if err != nil { fatal("Current user is invalid", err) } defaultDir := path.Join(user.HomeDir, DefaultDir) dir := flag.String("d", defaultDir, "The directory your h0tb0x stuff lives in") flag.Parse() if *dir == "" { fatal("Directory option is required", nil) } cfgFilename := path.Join(*dir, ConfigFilename) dbFilename := path.Join(*dir, DbFilename) idFilename := path.Join(*dir, IdFilename) dataDir := path.Join(*dir, "data") var config *Config var thedb *db.Database var ident *crypto.SecretIdentity if fi, err := os.Stat(*dir); err == nil && fi.IsDir() { pass1, err := gopass.GetPass("Please enter your h0tb0x password: "******"", err) } configFile, err := os.Open(cfgFilename) if err != nil { fatal("", err) } dec := json.NewDecoder(configFile) err = dec.Decode(&config) if err != nil { fatal("", err) } configFile.Close() identFile, err := os.Open(idFilename) if err != nil { fatal("", err) } var lockedId *crypto.LockedIdentity err = transfer.Decode(identFile, &lockedId) if err != nil { fatal("", err) } ident, err = crypto.UnlockSecretIdentity(lockedId, pass1) if err != nil { fatal("", err) } thedb = db.NewDatabase(dbFilename) } else { fmt.Println("Making a *NEW* h0tb0x config") err = os.MkdirAll(*dir, 0700) if err != nil { fatal("", err) } pass1, err := gopass.GetPass("Please enter the new password for your h0tb0x: ") if err != nil { fatal("", err) } pass2, err := gopass.GetPass("Re-enter your password: "******"", err) } if pass1 != pass2 { fmt.Println("Passwords don't match, go away") return } config = &Config{ ApiPort: DefaultApiPort, LinkPort: DefaultLinkPort, } configFile, err := os.Create(cfgFilename) if err != nil { fatal("", err) } enc := json.NewEncoder(configFile) err = enc.Encode(&config) if err != nil { fatal("", err) } configFile.Close() thedb = db.NewDatabase(dbFilename) thedb.Install() ident = crypto.NewSecretIdentity(pass1) identFile, err := os.Create(idFilename) if err != nil { fatal("", err) } _, err = identFile.Write(transfer.AsBytes(ident.Lock())) if err != nil { fatal("", err) } } extHost, extPort := GetExternalAddr(config.LinkPort) base := &base.Base{ Log: log.New(os.Stderr, "h0tb0x", log.LstdFlags), Db: thedb, Ident: ident, Port: config.LinkPort, } link := link.NewLinkMgr(base) sync := sync.NewSyncMgr(link) meta := meta.NewMetaMgr(sync) data := data.NewDataMgr(dataDir, meta) api := api.NewApiMgr(extHost.String(), extPort, config.ApiPort, data) ch := make(chan os.Signal, 1) signal.Notify(ch, os.Interrupt, os.Kill) api.Run() <-ch fmt.Fprintf(os.Stderr, "\n") api.Stop() }
func signRecord(rec *sync.Record, writer *crypto.SecretIdentity) { hash := crypto.HashOf(rec.RecordType, rec.Topic, rec.Key, rec.Value, rec.Priority) sig := writer.Sign(hash) rec.Author = writer.Fingerprint().String() rec.Signature = transfer.AsBytes(sig) }