diff --git a/blockchain/Block Record File.go b/blockchain/Block Record File.go index 4985048..80633ff 100644 --- a/blockchain/Block Record File.go +++ b/blockchain/Block Record File.go @@ -48,7 +48,6 @@ type BlockRecordFile struct { Size uint64 // Size of the file data NodeID []byte // Node ID, owner of the file Tags []BlockRecordFileTag // Tags provide additional metadata - ProfileImage []byte // ProfileImage of the user who uploaded the file Username string // Username of the User who uploaded the file } diff --git a/webapi/File.go b/webapi/File.go index 9b8181a..fe8013d 100644 --- a/webapi/File.go +++ b/webapi/File.go @@ -32,27 +32,29 @@ type apiFileMetadata struct { // apiFile is the metadata of a file published on the blockchain type apiFile struct { - ID uuid.UUID `json:"id"` // Unique ID. - Hash []byte `json:"hash"` // Blake3 hash of the file data - Type uint8 `json:"type"` // File Type. For example audio or document. See TypeX. - Format uint16 `json:"format"` // File Format. This is more granular, for example PDF or Word file. See FormatX. - Size uint64 `json:"size"` // Size of the file - Folder string `json:"folder"` // Folder, optional - Name string `json:"name"` // Name of the file - Description string `json:"description"` // Description. This is expected to be multiline and contain hashtags! - Date time.Time `json:"date"` // Date shared - NodeID []byte `json:"nodeid"` // Node ID, owner of the file. Read only. - Metadata []apiFileMetadata `json:"metadata"` // Additional metadata. - ProfilePicture []byte `json:"profilepicture"` // The Profile Picture of the user who uploaded the file - Username string `json:"username"` // Username of the user who uploaded the file + ID uuid.UUID `json:"id"` // Unique ID. + Hash []byte `json:"hash"` // Blake3 hash of the file data + Type uint8 `json:"type"` // File Type. For example audio or document. See TypeX. + Format uint16 `json:"format"` // File Format. This is more granular, for example PDF or Word file. See FormatX. + Size uint64 `json:"size"` // Size of the file + Folder string `json:"folder"` // Folder, optional + Name string `json:"name"` // Name of the file + Description string `json:"description"` // Description. This is expected to be multiline and contain hashtags! + Date time.Time `json:"date"` // Date shared + NodeID []byte `json:"nodeid"` // Node ID, owner of the file. Read only. + Metadata []apiFileMetadata `json:"metadata"` // Additional metadata. + Username []byte `json:"username"` // Username of the user who uploaded the file } // --- conversion from core to API data --- func blockRecordFileToAPI(input blockchain.BlockRecordFile) (output apiFile) { - output = apiFile{ID: input.ID, Hash: input.Hash, NodeID: input.NodeID, Type: input.Type, Format: input.Format, Size: input.Size, ProfilePicture: input.ProfileImage, Username: input.Username, Metadata: []apiFileMetadata{}} + output = apiFile{ID: input.ID, Hash: input.Hash, NodeID: input.NodeID, Type: input.Type, Format: input.Format, Size: input.Size, Username: []byte(input.Username), Metadata: []apiFileMetadata{}} for _, tag := range input.Tags { + if tag.Type == blockchain.TagSharedByCount && tag.Number() == 0 { + return apiFile{} + } switch tag.Type { case blockchain.TagName: output.Name = tag.Text() @@ -208,11 +210,14 @@ func (api *WebapiInstance) apiBlockchainFileList(w http.ResponseWriter, r *http. var result apiBlockAddFiles for _, file := range files { - apiFile := blockRecordFileToAPI(file) - if apiFile.Format == uint16(fileType) { - result.Files = append(result.Files, apiFile) + ApiFile := blockRecordFileToAPI(file) + if ApiFile.NodeID == nil { + continue + } + if ApiFile.Format == uint16(fileType) { + result.Files = append(result.Files, ApiFile) } else if err != nil { - result.Files = append(result.Files, apiFile) + result.Files = append(result.Files, ApiFile) } } diff --git a/webapi/Merge directory.go b/webapi/Merge directory.go index e0b049b..86faec4 100644 --- a/webapi/Merge directory.go +++ b/webapi/Merge directory.go @@ -69,11 +69,13 @@ func (api *WebapiInstance) ExploreFileSharedByNodeThatSharedSimilarFile(fileType // loop over results for n := range resultFiles { - result.Files = append(result.Files, blockRecordFileToAPI(resultFiles[n])) + ApiFile := blockRecordFileToAPI(resultFiles[n]) + if ApiFile.NodeID == nil { + continue + } + result.Files = append(result.Files, ApiFile) } - // - } result.Status = 1 // No more results to expect diff --git a/webapi/Profile.go b/webapi/Profile.go index 4d630b2..c2bf9ef 100644 --- a/webapi/Profile.go +++ b/webapi/Profile.go @@ -7,6 +7,7 @@ Author: Peter Kleissner package webapi import ( + "bytes" "net/http" "strconv" @@ -41,15 +42,38 @@ func (api *WebapiInstance) apiProfileList(w http.ResponseWriter, r *http.Request var fields []blockchain.BlockRecordProfile var status int - if valid { - fields, status = api.Backend.NodelistLookup(NodeID).Backend.UserBlockchain.ProfileList() + result := apiProfileData{Status: status} + + if valid && !bytes.Equal(NodeID, api.Backend.SelfNodeID()) { + _, node, _ := api.Backend.FindNode(NodeID, 100) + + // First iteration of the entire blockchain to search for the profile + // image and Username of the user + for blockN1 := node.BlockchainHeight - 1; blockN1 > 0; blockN1-- { + blockDecoded, _, found, _ := node.Backend.ReadBlock(node.PublicKey, node.BlockchainVersion, blockN1) + if !found { + continue + } + // Adding profile image and Username to the output + for raw := range blockDecoded.Block.RecordsRaw { + if blockDecoded.Block.RecordsRaw[raw].Type == blockchain.ProfileName { + result.Status = 0 + result.Fields = append(result.Fields, blockRecordProfileToAPI(blockchain.BlockRecordProfile{Type: uint16(blockDecoded.Block.RecordsRaw[raw].Type), Data: blockDecoded.Block.RecordsRaw[raw].Data[:]})) + } + if blockDecoded.Block.RecordsRaw[raw].Type == blockchain.ProfilePicture { + result.Status = 0 + result.Fields = append(result.Fields, blockRecordProfileToAPI(blockchain.BlockRecordProfile{Type: uint16(blockDecoded.Block.RecordsRaw[raw].Type), Data: blockDecoded.Block.RecordsRaw[raw].Data[:]})) + } + } + } + + fields, status = node.Backend.UserBlockchain.ProfileList() } else { fields, status = api.Backend.UserBlockchain.ProfileList() - } - - result := apiProfileData{Status: status} - for n := range fields { - result.Fields = append(result.Fields, blockRecordProfileToAPI(fields[n])) + result.Status = status + for n := range fields { + result.Fields = append(result.Fields, blockRecordProfileToAPI(fields[n])) + } } EncodeJSON(api.Backend, w, r, result) @@ -75,7 +99,8 @@ func (api *WebapiInstance) apiProfileRead(w http.ResponseWriter, r *http.Request var data []byte if !valid { - if data, result.Status = api.Backend.UserBlockchain.ProfileReadField(uint16(fieldN)); result.Status == blockchain.StatusOK { + _, node, _ := api.Backend.FindNode(NodeID, 100) + if data, result.Status = node.Backend.UserBlockchain.ProfileReadField(uint16(fieldN)); result.Status == blockchain.StatusOK { result.Fields = append(result.Fields, blockRecordProfileToAPI(blockchain.BlockRecordProfile{Type: uint16(fieldN), Data: data})) } } else { diff --git a/webapi/Search.go b/webapi/Search.go index f2871dd..8d8c1aa 100644 --- a/webapi/Search.go +++ b/webapi/Search.go @@ -390,7 +390,11 @@ func (api *WebapiInstance) ExploreHelper(fileType int, limit, offset int, nodeID // loop over results for n := range resultFiles { - result.Files = append(result.Files, blockRecordFileToAPI(resultFiles[n])) + ApiFile := blockRecordFileToAPI(resultFiles[n]) + if ApiFile.NodeID == nil { + continue + } + result.Files = append(result.Files, ApiFile) } if len(result.Files) == 0 { diff --git a/webapi/Shared Recent.go b/webapi/Shared Recent.go index f7a29cc..05fb56d 100644 --- a/webapi/Shared Recent.go +++ b/webapi/Shared Recent.go @@ -6,124 +6,119 @@ Author: Peter Kleissner package webapi import ( - "fmt" - "time" + "fmt" + "time" - "github.com/PeernetOfficial/core" - "github.com/PeernetOfficial/core/blockchain" + "github.com/PeernetOfficial/core" + "github.com/PeernetOfficial/core/blockchain" ) // queryRecentShared returns recently shared files on the network from random peers until the limit is reached. func (api *WebapiInstance) queryRecentShared(backend *core.Backend, fileType int, limitPeer, offsetTotal, limitTotal uint64, nodeID []byte, nodeIDState bool) (files []blockchain.BlockRecordFile) { - if limitPeer == 0 { - limitPeer = 1 - } - // Assign peer list as an empty array - var peerList []*core.PeerInfo + if limitPeer == 0 { + limitPeer = 1 + } + // Assign peer list as an empty array + var peerList []*core.PeerInfo - // check if the NodeID is provided or not - if len(nodeID) == 0 && !nodeIDState { - // Use the peer list to know about active peers. Random order! - peerList = api.Backend.PeerlistGet() - } else { - // Get peer information based on the NodeID provided - _, peer, err := api.Backend.FindNode(nodeID, time.Second*5) - if err != nil { - return - } - peerList = append(peerList, peer) - } + // check if the NodeID is provided or not + if len(nodeID) == 0 && !nodeIDState { + // Use the peer list to know about active peers. Random order! + peerList = api.Backend.PeerlistGet() + } else { + // Get peer information based on the NodeID provided + _, peer, err := api.Backend.FindNode(nodeID, time.Second*5) + if err != nil { + return + } + peerList = append(peerList, peer) + } - // Files from peers exceeding the limit. It is used if from all peers the total limit is not reached. - var filesSeconday []blockchain.BlockRecordFile + // Files from peers exceeding the limit. It is used if from all peers the total limit is not reached. + var filesSeconday []blockchain.BlockRecordFile - for _, peer := range peerList { - if peer.BlockchainHeight == 0 { - continue - } + for _, peer := range peerList { + if peer.BlockchainHeight == 0 { + continue + } - var filesFromPeer uint64 + var filesFromPeer uint64 + var Name string - //var ProfileImage []byte - //var Name string + ProfileNameFound := false - //ProfileNameFound := false - //ProfilePictureFound := false - // - //// First iteration of the entire blockchain to search for the profile - //// image and Username of the user - //for blockN1 := peer.BlockchainHeight - 1; blockN1 > 0; blockN1-- { - // blockDecoded, _, found, _ := backend.ReadBlock(peer.PublicKey, peer.BlockchainVersion, blockN1) - // if !found { - // continue - // } - // // Adding profile image and Username to the output - // for raw := range blockDecoded.Block.RecordsRaw { - // if blockDecoded.Block.RecordsRaw[raw].Type == blockchain.ProfilePicture && !ProfilePictureFound { - // ProfileImage = blockDecoded.Block.RecordsRaw[raw].Data - // ProfilePictureFound = true - // } - // if blockDecoded.Block.RecordsRaw[raw].Type == blockchain.ProfileName && !ProfileNameFound { - // Name = string(blockDecoded.Block.RecordsRaw[raw].Data[:]) - // ProfileNameFound = true - // } - // } - //} + // First iteration of the entire blockchain to search for the profile + // image and Username of the user + for blockN1 := peer.BlockchainHeight - 1; blockN1 > 0; blockN1-- { + blockDecoded, _, found, _ := backend.ReadBlock(peer.PublicKey, peer.BlockchainVersion, blockN1) + if !found { + continue + } + // Adding profile image and Username to the output + for raw := range blockDecoded.Block.RecordsRaw { + if blockDecoded.Block.RecordsRaw[raw].Type == blockchain.ProfileName && !ProfileNameFound { + Name = string(blockDecoded.Block.RecordsRaw[raw].Data[:]) + ProfileNameFound = true + } + } + } - // decode blocks from top down - blockLoop: - for blockN := peer.BlockchainHeight - 1; blockN > 0; blockN-- { - blockDecoded, _, found, _ := backend.ReadBlock(peer.PublicKey, peer.BlockchainVersion, blockN) + // decode blocks from top down + blockLoop: + for blockN := peer.BlockchainHeight - 1; blockN > 0; blockN-- { + blockDecoded, _, found, _ := backend.ReadBlock(peer.PublicKey, peer.BlockchainVersion, blockN) - if !found { - continue - } + if !found { + continue + } - for _, record := range blockDecoded.RecordsDecoded { - if file, ok := record.(blockchain.BlockRecordFile); ok && isFileTypeMatchBlock(&file, fileType) { - // add the tags 'Shared By Count' and 'Shared By GeoIP' - file.Tags = append(file.Tags, blockchain.TagFromNumber(blockchain.TagSharedByCount, 1)) - if latitude, longitude, valid := api.Peer2GeoIP(peer); valid { - sharedByGeoIP := fmt.Sprintf("%.4f", latitude) + "," + fmt.Sprintf("%.4f", longitude) - file.Tags = append(file.Tags, blockchain.TagFromText(blockchain.TagSharedByGeoIP, sharedByGeoIP)) - } + for _, record := range blockDecoded.RecordsDecoded { + if file, ok := record.(blockchain.BlockRecordFile); ok && isFileTypeMatchBlock(&file, fileType) { + // add the tags 'Shared By Count' and 'Shared By GeoIP' + file.Tags = append(file.Tags, blockchain.TagFromNumber(blockchain.TagSharedByCount, 1)) + if latitude, longitude, valid := api.Peer2GeoIP(peer); valid { + sharedByGeoIP := fmt.Sprintf("%.4f", latitude) + "," + fmt.Sprintf("%.4f", longitude) + file.Tags = append(file.Tags, blockchain.TagFromText(blockchain.TagSharedByGeoIP, sharedByGeoIP)) + } - // found a new file! append. - if filesFromPeer < limitPeer { - filesFromPeer++ + file.Username = Name - if offsetTotal > 0 { - offsetTotal-- - continue - } + // found a new file! append. + if filesFromPeer < limitPeer { + filesFromPeer++ - files = append(files, file) + if offsetTotal > 0 { + offsetTotal-- + continue + } - if uint64(len(files)) >= limitTotal { - return - } - } else if uint64(len(filesSeconday)) < limitTotal-uint64(len(files)) { - filesSeconday = append(filesSeconday, file) - } else { - break blockLoop - } - } - } - } - } + files = append(files, file) - files = append(files, filesSeconday...) + if uint64(len(files)) >= limitTotal { + return + } + } else if uint64(len(filesSeconday)) < limitTotal-uint64(len(files)) { + filesSeconday = append(filesSeconday, file) + } else { + break blockLoop + } + } + } + } + } - return + files = append(files, filesSeconday...) + + return } // isFileTypeMatchBlock checks if the file type matches. -1 = accept any. -2 = core.TypeBinary, core.TypeCompressed, core.TypeContainer, core.TypeExecutable. func isFileTypeMatchBlock(file *blockchain.BlockRecordFile, fileType int) bool { - if fileType == -1 { - return true - } else if fileType == -2 { - return file.Type == core.TypeBinary || file.Type == core.TypeCompressed || file.Type == core.TypeContainer || file.Type == core.TypeExecutable - } + if fileType == -1 { + return true + } else if fileType == -2 { + return file.Type == core.TypeBinary || file.Type == core.TypeCompressed || file.Type == core.TypeContainer || file.Type == core.TypeExecutable + } - return file.Type == uint8(fileType) + return file.Type == uint8(fileType) }