github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/service/incoming-share.go (about)

     1  // Copyright 2020 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package service
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"errors"
    10  	"os"
    11  	"path/filepath"
    12  
    13  	"github.com/keybase/client/go/libkb"
    14  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    15  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    16  )
    17  
    18  type IncomingShareHandler struct {
    19  	*BaseHandler
    20  	libkb.Contextified
    21  }
    22  
    23  func NewIncomingShareHandler(xp rpc.Transporter, g *libkb.GlobalContext) *IncomingShareHandler {
    24  	return &IncomingShareHandler{
    25  		BaseHandler:  NewBaseHandler(g, xp),
    26  		Contextified: libkb.NewContextified(g),
    27  	}
    28  }
    29  
    30  // shareItemJSON is for json parsing only.
    31  type shareItemJSON struct {
    32  	Type          string `json:"type"`
    33  	OriginalPath  string `json:"originalPath"`
    34  	ScaledPath    string `json:"scaledPath"`
    35  	ThumbnailPath string `json:"thumbnailPath"`
    36  	Content       string `json:"content"`
    37  	Error         string `json:"error"`
    38  }
    39  
    40  func strPtr(str string) *string {
    41  	if len(str) > 0 {
    42  		return &str
    43  	}
    44  	return nil
    45  }
    46  
    47  func numPtr(num int) *int {
    48  	if num != 0 {
    49  		return &num
    50  	}
    51  	return nil
    52  }
    53  
    54  func (h *IncomingShareHandler) GetIncomingShareItems(ctx context.Context) (items []keybase1.IncomingShareItem, err error) {
    55  	mctx := libkb.NewMetaContext(ctx, h.G())
    56  	manifestPath := filepath.Join(h.G().Env.GetMobileSharedHome(), "Library", "Caches", "incoming-shares", "manifest.json")
    57  	f, err := os.Open(manifestPath)
    58  	if err != nil {
    59  		mctx.Debug("incoming-share: open manifest.json error: %v", err)
    60  		return nil, err
    61  	}
    62  	defer f.Close()
    63  	var jsonItems []shareItemJSON
    64  	if err = json.NewDecoder(f).Decode(&jsonItems); err != nil {
    65  		mctx.Debug("incoming-share: decode manifest.json error: %v", err)
    66  		return nil, err
    67  	}
    68  	mctx.Debug("incoming-share: %d items", len(jsonItems))
    69  loop:
    70  	for _, jsonItem := range jsonItems {
    71  		if len(jsonItem.Error) > 0 {
    72  			mctx.Debug("incoming-share: error: %s", jsonItem.Error)
    73  			continue loop
    74  		}
    75  		var t keybase1.IncomingShareType
    76  		switch jsonItem.Type {
    77  		case "file":
    78  			t = keybase1.IncomingShareType_FILE
    79  		case "text":
    80  			t = keybase1.IncomingShareType_TEXT
    81  		case "image":
    82  			t = keybase1.IncomingShareType_IMAGE
    83  		case "video":
    84  			t = keybase1.IncomingShareType_VIDEO
    85  		default:
    86  			mctx.Debug("incoming-share: skippping unknown type: %v", jsonItem.Type)
    87  			continue loop
    88  		}
    89  
    90  		var originalSize int
    91  		if len(jsonItem.OriginalPath) > 0 {
    92  			fiOriginal, err := os.Stat(jsonItem.OriginalPath)
    93  			if err != nil {
    94  				mctx.Debug("incoming-share: stat error on original: %v", err)
    95  				return nil, err
    96  			}
    97  			originalSize = int(fiOriginal.Size())
    98  		}
    99  
   100  		var scaledSize int
   101  		if len(jsonItem.ScaledPath) > 0 {
   102  			fiScaled, err := os.Stat(jsonItem.ScaledPath)
   103  			if err != nil {
   104  				mctx.Debug("incoming-share: stat error on scaled: %v", err)
   105  				return nil, err
   106  			}
   107  			scaledSize = int(fiScaled.Size())
   108  		}
   109  
   110  		items = append(items, keybase1.IncomingShareItem{
   111  			Type:          t,
   112  			OriginalPath:  strPtr(jsonItem.OriginalPath),
   113  			OriginalSize:  numPtr(originalSize),
   114  			ScaledPath:    strPtr(jsonItem.ScaledPath),
   115  			ScaledSize:    numPtr(scaledSize),
   116  			ThumbnailPath: strPtr(jsonItem.ThumbnailPath),
   117  			Content:       strPtr(jsonItem.Content),
   118  		})
   119  	}
   120  
   121  	if len(items) == 0 {
   122  		return nil, errors.New("empty incoming share")
   123  	}
   124  
   125  	return items, nil
   126  }
   127  
   128  func (h *IncomingShareHandler) dbKey() libkb.DbKey {
   129  	return libkb.DbKey{
   130  		Typ: libkb.DBIncomingSharePreference,
   131  		Key: "v0-compress-preference",
   132  	}
   133  }
   134  
   135  func (h *IncomingShareHandler) GetPreference(ctx context.Context) (
   136  	pref keybase1.IncomingSharePreference, err error) {
   137  	found, err := h.G().GetKVStore().GetInto(&pref, h.dbKey())
   138  	if err != nil {
   139  		return keybase1.IncomingSharePreference{}, err
   140  	}
   141  	if found {
   142  		return pref, nil
   143  	}
   144  	return keybase1.IncomingSharePreference{
   145  		CompressPreference: keybase1.IncomingShareCompressPreference_ORIGINAL,
   146  	}, nil
   147  }
   148  
   149  func (h *IncomingShareHandler) SetPreference(ctx context.Context,
   150  	preference keybase1.IncomingSharePreference) error {
   151  	return h.G().GetKVStore().PutObj(h.dbKey(), nil, preference)
   152  }