@@ -51,12 +51,32 @@ import (
5151 "github.com/pkg/errors"
5252)
5353
54+ // shareField and passwordField are the keys used to store a share's encoded
55+ // proto and its bcrypt-hashed password in a db entry.
56+ const (
57+ shareField = "share"
58+ passwordField = "password"
59+ )
60+
5461func init () {
5562 registry .Register ("json" , NewFile )
5663 registry .Register ("jsoncs3" , NewCS3 )
5764 registry .Register ("jsonmemory" , NewMemory )
5865}
5966
67+ // dbEntryString safely reads the string value stored under key in a db entry.
68+ // Entries are read back from persistence as interface{} (map[string]interface{}
69+ // with string values), so a corrupted or legacy record can hold an unexpected
70+ // type; this reports that via ok instead of panicking.
71+ func dbEntryString (v interface {}, key string ) (string , bool ) {
72+ m , ok := v .(map [string ]interface {})
73+ if ! ok {
74+ return "" , false
75+ }
76+ s , ok := m [key ].(string )
77+ return s , ok
78+ }
79+
6080// NewFile returns a new filesystem public shares manager.
6181func NewFile (c map [string ]interface {}) (publicshare.Manager , error ) {
6282 conf := & fileConfig {}
@@ -239,10 +259,16 @@ func (m *manager) Dump(ctx context.Context, shareChan chan<- *publicshare.WithPa
239259
240260 for _ , v := range db {
241261 var local publicshare.WithPassword
242- if err := utils .UnmarshalJSONToProtoV1 ([]byte (v .(map [string ]interface {})["share" ].(string )), & local .PublicShare ); err != nil {
243- log .Error ().Err (err ).Msg ("error unmarshalling share" )
262+ if share , ok := dbEntryString (v , shareField ); ok {
263+ if err := utils .UnmarshalJSONToProtoV1 ([]byte (share ), & local .PublicShare ); err != nil {
264+ log .Error ().Err (err ).Msg ("error unmarshalling share" )
265+ }
266+ } else {
267+ log .Error ().Msg ("error reading share entry: missing or invalid \" share\" field" )
244268 }
245- local .Password = v .(map [string ]interface {})["password" ].(string )
269+ // password is optional: shares without password protection have no
270+ // password field, so a missing/invalid entry just means "no password".
271+ local .Password , _ = dbEntryString (v , passwordField )
246272 shareChan <- & local
247273 }
248274
@@ -271,8 +297,8 @@ func (m *manager) Load(ctx context.Context, shareChan <-chan *publicshare.WithPa
271297 }
272298
273299 dbCopy [ps .PublicShare .Id .GetOpaqueId ()] = map [string ]interface {}{
274- "share" : string (encShare ),
275- "password" : ps .Password ,
300+ shareField : string (encShare ),
301+ passwordField : ps .Password ,
276302 }
277303 }
278304 return m .persistence .Write (ctx , dbCopy )
@@ -350,8 +376,8 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr
350376
351377 if _ , ok := dbCopy [s .Id .GetOpaqueId ()]; ! ok {
352378 dbCopy [s .Id .GetOpaqueId ()] = map [string ]interface {}{
353- "share" : string (encShare ),
354- "password" : ps .Password ,
379+ shareField : string (encShare ),
380+ passwordField : ps .Password ,
355381 }
356382 } else {
357383 return nil , errors .New ("key already exists" )
@@ -448,9 +474,9 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link
448474 }
449475
450476 if ok && passwordChanged {
451- data ["password" ] = newPasswordEncoded
477+ data [passwordField ] = newPasswordEncoded
452478 }
453- data ["share" ] = string (encShare )
479+ data [shareField ] = string (encShare )
454480
455481 dbCopy [share .Id .OpaqueId ] = data
456482
@@ -491,11 +517,14 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu
491517 }
492518
493519 for _ , v := range db {
494- d := v .(map [string ]interface {})["share" ]
495- passDB := v .(map [string ]interface {})["password" ].(string )
520+ share , ok := dbEntryString (v , shareField )
521+ if ! ok {
522+ continue
523+ }
524+ passDB , _ := dbEntryString (v , passwordField )
496525
497526 var ps link.PublicShare
498- if err := utils .UnmarshalJSONToProtoV1 ([]byte (d .( string ) ), & ps ); err != nil {
527+ if err := utils .UnmarshalJSONToProtoV1 ([]byte (share ), & ps ); err != nil {
499528 return nil , err
500529 }
501530
@@ -547,7 +576,12 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []
547576 shares := []* link.PublicShare {}
548577 for _ , v := range db {
549578 var local publicShare
550- if err := utils .UnmarshalJSONToProtoV1 ([]byte (v .(map [string ]interface {})["share" ].(string )), & local .PublicShare ); err != nil {
579+ share , ok := dbEntryString (v , shareField )
580+ if ! ok {
581+ log .Warn ().Interface ("entry" , v ).Msg ("ListPublicShares: skipping entry with missing or invalid \" share\" field" )
582+ continue
583+ }
584+ if err := utils .UnmarshalJSONToProtoV1 ([]byte (share ), & local .PublicShare ); err != nil {
551585 return nil , err
552586 }
553587
@@ -637,10 +671,13 @@ func (m *manager) cleanupExpiredShares() error {
637671
638672 var changed bool
639673 for id , v := range db {
640- d := v .(map [string ]interface {})["share" ]
674+ share , ok := dbEntryString (v , shareField )
675+ if ! ok {
676+ continue
677+ }
641678
642679 var ps link.PublicShare
643- if err := utils .UnmarshalJSONToProtoV1 ([]byte (d .( string ) ), & ps ); err != nil {
680+ if err := utils .UnmarshalJSONToProtoV1 ([]byte (share ), & ps ); err != nil {
644681 continue
645682 }
646683
@@ -705,13 +742,18 @@ func (m *manager) getByToken(ctx context.Context, token string) (*link.PublicSha
705742 }
706743
707744 for _ , v := range db {
745+ share , ok := dbEntryString (v , shareField )
746+ if ! ok {
747+ continue
748+ }
749+
708750 var local link.PublicShare
709- if err := utils .UnmarshalJSONToProtoV1 ([]byte (v .( map [ string ] interface {})[ " share" ].( string ) ), & local ); err != nil {
751+ if err := utils .UnmarshalJSONToProtoV1 ([]byte (share ), & local ); err != nil {
710752 return nil , "" , err
711753 }
712754
713755 if local .Token == token {
714- passDB := v .( map [ string ] interface {})[ "password" ].( string )
756+ passDB , _ := dbEntryString ( v , passwordField )
715757 return & local , passDB , nil
716758 }
717759 }
@@ -734,9 +776,14 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string, auth
734776 }
735777
736778 for _ , v := range db {
737- passDB := v .(map [string ]interface {})["password" ].(string )
779+ share , ok := dbEntryString (v , shareField )
780+ if ! ok {
781+ continue
782+ }
783+
784+ passDB , _ := dbEntryString (v , passwordField )
738785 var local link.PublicShare
739- if err := utils .UnmarshalJSONToProtoV1 ([]byte (v .( map [ string ] interface {})[ " share" ].( string ) ), & local ); err != nil {
786+ if err := utils .UnmarshalJSONToProtoV1 ([]byte (share ), & local ); err != nil {
740787 return nil , err
741788 }
742789
0 commit comments