package main import ( "path/filepath" "os" "database/sql" "flag" "fmt" "log" "strings" "strconv" _ "github.com/mattn/go-sqlite3" ) var version = "0.0.1" func main() { // Define a command-line flags help := flag.Bool("help", false, "print a short usage message") dbPtr := flag.String("db", "./english_words.db", "SQLite3 DB file to use") filenamePtr := flag.String("file", "results.txt", "Name of the file to write results to") pwdPtr := flag.String("pwd", "", "Enter a password") flag.Parse() if *help { usage() return } // Open the SQLite3 database file db, err := sql.Open("sqlite3", *dbPtr) if err != nil { log.Fatal(err) } defer db.Close() for { // Get user input for the test query fmt.Print("Enter keyword: ") var searchTerm string fmt.Scanln(&searchTerm) // Exit the loop if Enter key is pressed without entering a search term if searchTerm == "" { break } // Execute the first query with case-sensitive like query := "SELECT id FROM words WHERE word COLLATE BINARY = ?" rows, err := db.Query(query, searchTerm) if err != nil { log.Fatal(err) } defer rows.Close() // If no results, try case-insensitive like if !rows.Next() { rows.Close() // Close the previous result set before executing a new query // Execute the second query with case-insensitive like query = "SELECT id FROM words WHERE LOWER(word) LIKE ?" rows, err = db.Query(query, strings.ToLower(searchTerm)) if err != nil { log.Fatal(err) } defer rows.Close() if rows.Next() { // Process the results //fmt.Println("Results for case-insensitive LIKE:") writeResultsToFile(*filenamePtr, rows) } else { if strings.Contains(searchTerm, "*") { result := strings.Replace(searchTerm, "*", "", -1) if (*pwdPtr != "") { writeDataToFile(*filenamePtr, xorStringWithPassword(compressRLE(result), *pwdPtr)) } else { writeDataToFile(*filenamePtr, xorBy13(compressRLE(result))) } } else { fmt.Println("Not found! Please retype and add an * at the end to save") } } } else { // Process the results //fmt.Println("Results for case-sensitive LIKE:") writeResultsToFile(*filenamePtr, rows) } } } func writeDataToFile(filename string, data string) { file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } defer file.Close() result := fmt.Sprintf("_%s ", data) _, err = file.WriteString(result) if err != nil { log.Fatal(err) } //fmt.Printf("Added to %s\n", filename) } func writeResultsToFile(filename string, rows *sql.Rows) { file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } defer file.Close() var id int err = rows.Scan(&id) if err != nil { log.Fatal(err) } fmt.Printf("Added ID %d\n", id) result := fmt.Sprintf("%d ", id) _, err = file.WriteString(result) if err != nil { log.Fatal(err) } if err := rows.Err(); err != nil { log.Fatal(err) } //fmt.Printf("Results written to %s\n", filename) } func xorBy13(input string) string { var result strings.Builder for _, char := range input { xored := char ^ 13 result.WriteRune(xored) } return result.String() } func xorStringWithPassword(input string, password string) string { inputBytes := []byte(input) passwordBytes := []byte(password) for i := 0; i < len(inputBytes); i++ { inputBytes[i] ^= passwordBytes[i%len(passwordBytes)] } return string(inputBytes) } // compressRLE compresses a string using Run-Length Encoding func compressRLE(input string) string { result := "" count := 1 for i := 1; i < len(input); i++ { if input[i-1] == input[i] { count++ } else { result += string(input[i-1]) + strconv.Itoa(count) count = 1 } } // Add the last character and its count result += string(input[len(input)-1]) + strconv.Itoa(count) return result } func usage() { progName := filepath.Base(os.Args[0]) fmt.Printf(`%s version %s, (c) 2024 Bob Usage: %s [-help] [-db english_words.db] [-file results.txt] [-pwd MyPassword] -db SQLite3 DB file to use -file Name of the file to write results to -pwd Enter a password `, progName, version, progName) }