Browse Source

fix: stupid check for empty string was incorrect!

Gwyneth Llewelyn 5 months ago
parent
commit
26e67034dd
3 changed files with 36 additions and 179 deletions
  1. 4 10
      functions.go
  2. 10 2
      gosl.go
  3. 22 167
      search.go

+ 4 - 10
functions.go

@@ -81,18 +81,12 @@ func funcName() string {
 	return ""
 }
 
-/*
-// isValidUUID checks if the UUID is valid.
-// Deprecated: Since regexps may be overkill here, Google's own package is far more efficient and we'll use it directly (gwyneth 20211031)
-func isValidUUID(uuid string) bool {
-	r := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
-	return r.MatchString(uuid)
-}
-*/
-
-// isValidUUID checks if the UUID is valid.
+// isValidUUID returns whether the UUID is valid.
 // Thanks to Patrick D'Appollonio https://stackoverflow.com/questions/25051675/how-to-validate-uuid-v4-in-go
 //  as well as https://stackoverflow.com/a/46315070/1035977 (gwyneth 29211031)
+// This exists mostly to be able to return just _one_ value (the boolean) and not require anything else.
+// Also note that _some_ UUIDs are not fully v4 compliant; LL invented a few ones for the first "special"
+// residents.
 func isValidUUID(u string) bool {
 	_, err := uuid.Parse(u)
 	return err == nil

+ 10 - 2
gosl.go

@@ -410,7 +410,7 @@ func main() {
 				avatarKey, gridName = searchKVname(checkInput)
 				avatarName = checkInput
 			}
-			if avatarName != NullUUID && avatarKey != NullUUID {
+			if avatarName != "" && avatarKey != NullUUID {
 				fmt.Println(avatarName, "which has UUID:", avatarKey, "comes from grid:", gridName)
 			} else {
 				fmt.Println("sorry, unknown input", checkInput)
@@ -475,6 +475,11 @@ func handler(w http.ResponseWriter, r *http.Request) {
 	messageToSL := "" // this is what we send back to SL - defined here due to scope issues.
 	if name != "" {
 		if key != "" {
+			// be stricter!
+			if len(key) != 36 || !isValidUUID(key) {
+				logErrHTTP(w, http.StatusBadRequest, fmt.Sprintf("invalid key %q", key))
+				return
+			}
 			// we received both: add a new entry.
 			uuidToInsert.UUID = key
 			uuidToInsert.Grid = r.Header.Get("X-Secondlife-Shard")
@@ -511,6 +516,9 @@ func handler(w http.ResponseWriter, r *http.Request) {
 		} else {
 			// we received a name: look up its UUID key and grid.
 			key, grid := searchKVname(name)
+			if len(key) != 36 || !isValidUUID(key) {		// this is to prevent stupid mistakes!
+				key = NullUUID
+			}
 			if compat == "false" {
 				messageToSL += "UUID for '" + name + "' is: " + key + " from grid: '" + grid + "'"
 			} else { // empty also means true!
@@ -521,7 +529,7 @@ func handler(w http.ResponseWriter, r *http.Request) {
 		// in this scenario, we have the UUID key but no avatar name: do the equivalent of a llKey2Name
 		name, grid := searchKVUUID(key)
 		if compat == "false" {
-			messageToSL += "avatar name for " + key + "' is '" + name + "' on grid: '" + grid + "'"
+			messageToSL += "avatar name for '" + key + "' is '" + name + "' on grid: '" + grid + "'"
 		} else { // empty also means true!
 			messageToSL += name
 		}

+ 22 - 167
search.go

@@ -6,6 +6,7 @@ package main
 
 import (
 	"encoding/json"
+	"strings"
 	"time"
 
 	"github.com/dgraph-io/badger/v3"
@@ -14,178 +15,28 @@ import (
 )
 
 // searchKVname searches the KV database for an avatar name.
+// Returns NullUUID if the key wasn't found.
 func searchKVname(avatarName string) (uuid string, grid string) {
-	_, tempUUID, tempGrid := searchKV(avatarName)
+	_, tempUUID, tempGrid := searchKV(strings.TrimSpace(avatarName))
 	return tempUUID, tempGrid
 }
 
-// searchKVname searches the KV database for an avatar name.
+// searchKVUUID searches the KV database for an avatar UUID.
+// Returns empty string if the avatar name wasn't found.
 func searchKVUUID(avatarKey string) (name string, grid string) {
-	tempAvatarName, _, tempGrid := searchKV(avatarKey)
+	tempAvatarName, _, tempGrid := searchKV(strings.TrimSpace(avatarKey))
 	return tempAvatarName, tempGrid
 }
 
-/* deprecated (gwyneth 20211031)
-
-// searchKVname searches the KV database for an avatar name.
-func searchKVname(avatarName string) (UUID string, grid string) {
-	var val = avatarUUID{ avatarName, uuid.Nil, "" }
-	time_start := time.Now()
-	var err error // to deal with scope issues
-	switch *goslConfig.database {
-		case "badger":
-			kv, err := badger.Open(Opt)
-			checkErrPanic(err)
-			defer kv.Close()
-			err = kv.View(func(txn *badger.Txn) error {
-				item, err := txn.Get([]byte(avatarName))
-				if err != nil {
-					return err
-				}
-				data, err := item.ValueCopy(nil)
-				if err != nil {
-					log.Errorf("error %q while getting data from %v\n", err, item)
-					return err
-				}
-				if err = json.Unmarshal(data, &val); err != nil {
-					log.Errorf("error while unparsing UUID for name: %q (%v)\n", avatarName, err)
-					return err
-				}
-				return nil
-			})
-			checkErr(err)
-		case "buntdb":
-			db, err := buntdb.Open(goslConfig.dbNamePath)
-			checkErrPanic(err)
-			defer db.Close()
-			var data string
-			err = db.View(func(tx *buntdb.Tx) error {
-				data, err = tx.Get(avatarName)
-				return err
-			})
-			err = json.Unmarshal([]byte(data), &val)
-			if err != nil {
-				log.Errorf("error while unparsing UUID for name: %q (%v)\n", avatarName, err)
-			}
-		case "leveldb":
-			db, err := leveldb.OpenFile(goslConfig.dbNamePath, nil)
-			checkErrPanic(err)
-			defer db.Close()
-			data, err := db.Get([]byte(avatarName), nil)
-			if err != nil {
-				log.Errorf("error while getting UUID for name: %q (%v)\n", avatarName, err)
-			} else {
-				if err = json.Unmarshal(data, &val); err != nil {
-					log.Errorf("error while unparsing UUID for name: %q (%v)\n", avatarName, err)
-				}
-			}
-	}
-	log.Debugf("time to lookup %q: %v\n", avatarName, time.Since(time_start))
-	if err != nil {
-		return uuid.Nil, ""
-	} // else:
-	return val.UUID, val.Grid
-}
-// searchKVUUID searches the KV database for an avatar key.
-func searchKVUUID(avatarKey string) (name string, grid string) {
-	time_start := time.Now()
-	checks := 0
-	var val = avatarUUID{ "", avatarKey, "" }
-	var found string
-
-	switch *goslConfig.database {
-		case "badger":
-			kv, err := badger.Open(Opt)
-			checkErr(err) // should probably panic
-			itOpt := badger.DefaultIteratorOptions
-	//
-	//		if !*goslConfig.noMemory {
-	//			itOpt.PrefetchValues = true
-	//			itOpt.PrefetchSize = 1000	// attempt to get this a little bit more efficient; we have many small entries, so this is not too much
-	//		} else {
-	//
-				itOpt.PrefetchValues = false // allegedly this is supposed to be WAY faster...
-	// 		}
-			txn := kv.NewTransaction(true)
-			defer txn.Discard()
-
-			err = kv.View(func(txn *badger.Txn) error {
-				itr := txn.NewIterator(itOpt)
-				defer itr.Close()
-				for itr.Rewind(); itr.Valid(); itr.Next() {
-					item := itr.Item()
-					data, err := item.ValueCopy(nil)
-					if err != nil {
-						log.Errorf("error %q while getting data from %v\n", err, item)
-						return err
-					}
-					if err = json.Unmarshal(data, &val); err != nil {
-						log.Errorf("error %q while unparsing UUID for data: %v\n", err, data)
-						return err
-					}
-					checks++	//Just to see how many checks we made, for statistical purposes
-					if avatarKey == val.UUID {
-						found = string(item.Key())
-						break
-					}
-				}
-				return nil
-			})
-			checkErr(err)
-			kv.Close()
-		case "buntdb":
-			db, err := buntdb.Open(goslConfig.dbNamePath)
-			checkErrPanic(err)
-			err = db.View(func(tx *buntdb.Tx) error {
-				err := tx.Ascend("", func(key, value string) bool {
-					if err = json.Unmarshal([]byte(value), &val); err != nil {
-						log.Errorf("error %q while unparsing UUID for value: %v\n", err, value)
-					}
-					checks++	//Just to see how many checks we made, for statistical purposes
-					if avatarKey == val.UUID {
-						found = key
-						return false
-					}
-					return true
-				})
-				return err
-			})
-			db.Close()
-		case "leveldb":
-			db, err := leveldb.OpenFile(goslConfig.dbNamePath, nil)
-			checkErrPanic(err)
-			iter := db.NewIterator(nil, nil)
-			for iter.Next() {
-				// Remember that the contents of the returned slice should not be modified, and
-				// only valid until the next call to Next.
-				key := iter.Key()
-				value := iter.Value()
-				if err = json.Unmarshal(value, &val); err != nil {
-					log.Errorf("error %q while unparsing UUID for data: %v\n", err, value)
-					continue // a bit insane, but at least we will skip a few broken records
-				}
-				checks++	//Just to see how many checks we made, for statistical purposes
-				if avatarKey == val.UUID {
-					found = string(key)
-					break
-				}
-			}
-			iter.Release()
-			err = iter.Error()
-			checkErr(err)
-			db.Close()
-	} // /switch
-	log.Debugf("made %d checks for %q in %v\n", checks, avatarKey, time.Since(time_start))
-	return found, val.Grid
-}
-*/
-
 // Universal search, since we put everything in the KV database, we can basically search for anything.
 // *Way* more efficient! (gwyneth 20211031)
+// Returns the unmarshaled record from the KV store, if found;
+// otherwise, avatar name will be the empty string and avatar key will be NullUUID.
 func searchKV(searchItem string) (name string, uuid string, grid string) {
+	// return value.
 	var val = avatarUUID{"", NullUUID, ""}
-	time_start := time.Now()
-	var err error // to deal with scope issues
+	var err error // to deal with scope issues.
+	time_start := time.Now()	// start chroometer to time this transaction.
 	switch goslConfig.database {
 	case "badger":
 		kv, err = badger.Open(Opt)
@@ -202,11 +53,14 @@ func searchKV(searchItem string) (name string, uuid string, grid string) {
 				return err
 			}
 			if err = json.Unmarshal(data, &val); err != nil {
-				log.Errorf("error while unparsing UUID for name: %q (%v)\n", searchItem, err)
+				log.Errorf("error while unmarshalling reply to search item: %q (%v)\n", searchItem, err)
 				return err
 			}
 			return nil
 		})
+		if err != nil {
+			log.Errorf("error while getting or unmarshalling reply to search item: %q (%v)\n", searchItem, err)
+		}
 	case "buntdb":
 		db, err := buntdb.Open(goslConfig.dbNamePath)
 		checkErrPanic(err)
@@ -218,18 +72,19 @@ func searchKV(searchItem string) (name string, uuid string, grid string) {
 		})
 		err = json.Unmarshal([]byte(data), &val)
 		if err != nil {
-			log.Errorf("error while unparsing UUID for name: %q (%v)\n", searchItem, err)
+			log.Errorf("error while unmarshalling reply to search item: %q (%v)\n", searchItem, err)
 		}
 	case "leveldb":
-		db, err := leveldb.OpenFile(goslConfig.dbNamePath, nil)
-		checkErrPanic(err)
+		db, errdb := leveldb.OpenFile(goslConfig.dbNamePath, nil)
+		checkErrPanic(errdb)
 		defer db.Close()
-		data, err := db.Get([]byte(searchItem), nil)
+		var data []byte	// for scoping reasons.
+		data, err = db.Get([]byte(searchItem), nil)
 		if err != nil {
-			log.Errorf("error while getting UUID for name: %q (%v)\n", searchItem, err)
+			log.Errorf("error while unmarshalling reply to search item: %q (%v)\n", searchItem, err)
 		} else {
 			if err = json.Unmarshal(data, &val); err != nil {
-				log.Errorf("error while unparsing UUID for name: %q (%v)\n", searchItem, err)
+				log.Errorf("error while unmarshalling reply to search item: %q (%v)\n", searchItem, err)
 			}
 		}
 	}