You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
4.2 KiB
190 lines
4.2 KiB
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)
|
|
}
|
|
|