Restructure repository: organize tools by purpose, create what search tool

- Move single-file tools to tools/ organized by category (security, forensics, data, etc.)
- Move multi-file projects to projects/ (go-tools, puzzlebox, timesketch, rust-tools)
- Move system scripts to scripts/ (proxy, display, setup, windows)
- Organize config files in config/ (shell, visidata, applications)
- Move experimental tools to archive/experimental
- Create 'what' fuzzy search tool with progressive enhancement (ollama->fzf->grep)
- Add initial metadata database for intelligent tool discovery
- Preserve git history using 'git mv' commands
This commit is contained in:
tobias
2025-08-24 19:50:00 +02:00
parent 9518290544
commit 619b0bc432
124 changed files with 1063 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
package main
import (
"encoding/csv"
"encoding/json"
"flag"
"fmt"
"log"
"os"
)
func csvToJson(inputSource *os.File) {
csvReader := csv.NewReader(inputSource)
headers, err := csvReader.Read()
if err != nil {
log.Fatal("Failed to read headers: ", err)
}
for {
record, err := csvReader.Read()
if err != nil {
if err.Error() == "EOF" {
break
}
log.Fatal("Failed to read the data: ", err)
}
if len(record) == len(headers) {
jsonData := make(map[string]string)
for i, value := range record {
jsonData[headers[i]] = value
}
jsonOutput, err := json.Marshal(jsonData)
if err != nil {
log.Fatal("Failed to convert to json: ", err)
}
fmt.Println(string(jsonOutput))
} else {
log.Fatal("The number of columns in the record is not equal to the number of headers")
}
}
}
func main() {
inputSource := os.Stdin
flag.Parse()
var err error
if flag.NArg() > 0 {
inputSource, err = os.Open(flag.Args()[0])
if err != nil {
log.Fatalf("Failed to open file: %v\n", err)
}
defer inputSource.Close()
}
csvToJson(inputSource)
}

View File

@@ -0,0 +1,140 @@
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
)
func printUsage() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] <range specification> [file]\n", os.Args[0])
fmt.Fprintln(os.Stderr, "Options:")
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, "\nRange specification examples:")
fmt.Fprintln(os.Stderr, "10,20 Reads lines 10 to 20 from the input")
fmt.Fprintln(os.Stderr, "15:+5 Reads 5 lines starting from line 15")
fmt.Fprintln(os.Stderr, "3 Reads from line 3 to the end of the file")
fmt.Fprintln(os.Stderr, "+2 Reads the first 2 lines")
fmt.Fprintln(os.Stderr, "Please ensure you input valid range specifications and file paths.")
os.Exit(1)
}
func parseArgs(args []string) (int, int, string, error) {
var filename string
var start, length, end int
found := false
// Concatenate all arguments to a single string for easier parsing
joinedArgs := strings.Join(args, " ")
// Regular expression to match ranges and numbers
rangeRegex := regexp.MustCompile(`((\d+)?([ :,;-]))(\+)?(\d+)`)
range2Regex := regexp.MustCompile(`((\d+)([ :,;-]))`)
range3Regex := regexp.MustCompile(`(\+)?(\d+)`)
matches := rangeRegex.FindStringSubmatch(joinedArgs)
if matches != nil {
//check if start was defined
if matches[2] != "" {
start, _ = strconv.Atoi(matches[2]) // Convert start line to integer
} else {
start = 1
}
if matches[4] == "+" { // Check if it's a relative length
length, _ = strconv.Atoi(matches[5]) // Convert length to integer
end = start + length - 1
} else {
end, _ = strconv.Atoi(matches[5]) // Convert end line to integer
}
// Remove the matched part from the arguments
joinedArgs = strings.Replace(joinedArgs, matches[0], "", 1)
found = true
} else {
matches = range2Regex.FindStringSubmatch(joinedArgs)
if matches != nil {
start, _ = strconv.Atoi(matches[2]) // Convert start line to integer
end = -1
// Remove the matched part from the arguments
joinedArgs = strings.Replace(joinedArgs, matches[0], "", 1)
found = true
} else {
matches = range3Regex.FindStringSubmatch(joinedArgs)
if matches != nil {
if matches[1] == "+" { // Check if it's a relative length
length, _ := strconv.Atoi(matches[2]) // Convert length to integer
start = 1
end = start + length - 1
} else { // Otherwise convert it to an absolute length
start, _ = strconv.Atoi(matches[2]) // Convert start line to integer
end = -1
// Remove the matched part from the arguments
}
joinedArgs = strings.Replace(joinedArgs, matches[0], "", 1)
found = true
} else {
found = false
printUsage()
}
}
}
// Clean up and identify the filename, if present
joinedArgs = strings.TrimSpace(joinedArgs)
if joinedArgs != "" && !found {
// If we didn't find numbers, interpret the remaining as filename
filename = joinedArgs
} else if joinedArgs != "" {
// Otherwise, interpret any non-empty remaining part as filename
filename = joinedArgs
}
if !found {
return 0, 0, "", fmt.Errorf("no valid range or line number found")
}
return start, end, filename, nil
}
func main() {
flag.Parse()
args := flag.Args()
if len(args) < 1 {
printUsage()
os.Exit(1)
}
startIndex, endIndex, filename, err := parseArgs(args)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing arguments: %v\n", err)
os.Exit(1)
}
// Detemine the input source (file or stdin)
inputSource := os.Stdin
if filename != "" {
inputSource, err = os.Open(filename)
if err != nil {
log.Fatalf("Failed to open file: %v\n", err)
}
defer inputSource.Close()
}
scanner := bufio.NewScanner(inputSource)
//print all lines from line buner start to linenumber end unless linenumber end is -1
for i := 1; scanner.Scan(); i++ {
if startIndex <= i && (i <= endIndex || endIndex == -1) {
fmt.Println(scanner.Text())
}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,3 @@
module git.ktf.ninja/tabledevil/goinfo
go 1.22.5

View File

@@ -0,0 +1,52 @@
package main
import (
"fmt"
"log"
"net"
"os"
"os/user"
)
func getHostname() string {
hostname, err := os.Hostname()
if err != nil {
log.Println("Could not retrieve Hostname")
return ""
} else {
return hostname
}
}
func getUsernameDomain() string {
user, err := user.Current()
if err != nil {
log.Fatal(err)
}
return user.Username
}
func getIP(hostname string) string {
addrs, err := net.LookupIP(hostname)
if err != nil {
log.Fatal(err)
}
return addrs[0].String()
}
func getGroups() []int {
groups, err := os.Getgroups()
if err != nil {
log.Fatal(err)
}
return groups
}
func main() {
fmt.Println("hostname: ", getHostname())
fmt.Println("username: ", getUsernameDomain())
fmt.Println("groups: ", getGroups())
fmt.Println("google: ", getIP("www.google.de"))
}

Binary file not shown.

View File

@@ -0,0 +1,376 @@
// ipgrep.go
package main
import (
"bytes"
"encoding/csv"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"regexp"
"sort"
"sync"
"time"
)
// IPInfo holds the data we want from ipinfo.io
type IPInfo struct {
IP string `json:"ip"`
Hostname string `json:"hostname"`
City string `json:"city"`
Region string `json:"region"`
Country string `json:"country"`
Org string `json:"org"`
}
func main() {
// Command-line flags.
var (
sortFlag bool
uniqFlag bool
macFlag bool
pingable bool
resolveFlag bool
lookupFlag bool
fileName string
)
flag.BoolVar(&uniqFlag, "u", false, "only show uniq IPs/MACs (implies -s)")
flag.BoolVar(&sortFlag, "s", false, "sort output")
flag.BoolVar(&macFlag, "m", false, "grep MAC-IDs instead of IPs")
flag.BoolVar(&pingable, "p", false, "only show 'pingable' entries (MACs still beta)")
flag.BoolVar(&resolveFlag, "r", false, "resolve (uses host for ip and arping for mac)")
flag.BoolVar(&lookupFlag, "l", false, "lookup ip info using ipinfo.io and output CSV: ip,country,region,city,org,hostname")
flag.StringVar(&fileName, "f", "", "input file")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [-u] [-s] [-m] [-p] [-r] [-l] [-f filename] [file...]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
// If pingable is set, force sorting and uniqueness.
if pingable || lookupFlag {
sortFlag = true
uniqFlag = true
}
if lookupFlag && macFlag {
fmt.Fprintln(os.Stderr, "Lookup mode (-l) only works for IP addresses, not MAC addresses.")
os.Exit(1)
}
// Regular expressions for IPs or MACs.
var pattern string
if macFlag {
// Supports MAC formats: xx:xx:xx:xx:xx:xx or xxxx.xxxx.xxxx
pattern = `(([a-fA-F0-9]{2}[:-]){5}[a-fA-F0-9]{2})|([a-fA-F0-9]{4}\.[a-fA-F0-9]{4}\.[a-fA-F0-9]{4})`
} else {
// Matches valid IPv4 addresses.
pattern = `(((25[0-5])|(2[0-4][0-9])|([0-1]?\d?\d))\.){3}((25[0-5])|(2[0-4][0-9])|([0-1]?\d?\d))`
}
re, err := regexp.Compile(pattern)
if err != nil {
fmt.Fprintf(os.Stderr, "Error compiling regex: %v\n", err)
os.Exit(1)
}
// Read input from -f file, extra args, or stdin.
var inputData []byte
if fileName != "" {
inputData, err = ioutil.ReadFile(fileName)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading file %s: %v\n", fileName, err)
os.Exit(1)
}
} else if flag.NArg() > 0 {
var buf bytes.Buffer
for _, fname := range flag.Args() {
data, err := ioutil.ReadFile(fname)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading file %s: %v\n", fname, err)
continue
}
buf.Write(data)
buf.WriteByte('\n')
}
inputData = buf.Bytes()
} else {
inputData, err = io.ReadAll(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading stdin: %v\n", err)
os.Exit(1)
}
}
// Filter matches using the regex.
matches := re.FindAllString(string(inputData), -1)
if matches == nil {
os.Exit(0)
}
if sortFlag {
sort.Strings(matches)
}
if uniqFlag {
matches = unique(matches)
}
if pingable {
matches = filterPingable(matches, macFlag)
if sortFlag {
sort.Strings(matches)
}
}
// If lookup flag is set, perform ipinfo.io lookups with caching.
if lookupFlag {
cache := loadCache()
var cacheMu sync.Mutex
results := lookupIPInfo(matches, cache, &cacheMu)
// Sort the results by IP.
sort.Slice(results, func(i, j int) bool {
return results[i].IP < results[j].IP
})
// Save the updated cache.
saveCache(cache)
// Output CSV using csv.Writer for proper CSV formatting.
w := csv.NewWriter(os.Stdout)
// Write header.
if err := w.Write([]string{"ip", "country", "region", "city", "org", "hostname"}); err != nil {
fmt.Fprintf(os.Stderr, "Error writing CSV header: %v\n", err)
os.Exit(1)
}
for _, info := range results {
record := []string{
info.IP,
info.Country,
info.Region,
info.City,
info.Org,
info.Hostname,
}
if err := w.Write(record); err != nil {
fmt.Fprintf(os.Stderr, "Error writing CSV record: %v\n", err)
os.Exit(1)
}
}
w.Flush()
if err := w.Error(); err != nil {
fmt.Fprintf(os.Stderr, "Error flushing CSV data: %v\n", err)
}
return
}
// If resolve flag is set, perform resolution.
if resolveFlag {
results := resolveEntries(matches, macFlag)
for _, r := range results {
fmt.Print(r)
if !macFlag {
fmt.Println()
}
}
return
}
// Otherwise, just output the matches.
for _, m := range matches {
fmt.Println(m)
}
}
// unique removes duplicate strings from a slice.
func unique(input []string) []string {
seen := make(map[string]struct{})
var result []string
for _, s := range input {
if _, ok := seen[s]; !ok {
seen[s] = struct{}{}
result = append(result, s)
}
}
return result
}
// filterPingable runs ping (or arping) concurrently on each entry.
func filterPingable(entries []string, mac bool) []string {
var wg sync.WaitGroup
var mu sync.Mutex
var result []string
for _, entry := range entries {
wg.Add(1)
go func(e string) {
defer wg.Done()
if isPingable(e, mac) {
mu.Lock()
result = append(result, e)
mu.Unlock()
}
}(entry)
}
wg.Wait()
return result
}
// isPingable tests if an entry is reachable using ping (or arping for MACs).
func isPingable(entry string, mac bool) bool {
var cmd *exec.Cmd
if mac {
cmd = exec.Command("arping", "-c", "1", "-w", "5000000", entry)
} else {
cmd = exec.Command("ping", "-c", "1", "-w", "1", entry)
}
cmd.Stdout = nil
cmd.Stderr = nil
err := cmd.Run()
return err == nil
}
// resolveEntries performs resolution via external commands.
func resolveEntries(entries []string, mac bool) []string {
var wg sync.WaitGroup
results := make([]string, len(entries))
for i, entry := range entries {
wg.Add(1)
go func(i int, e string) {
defer wg.Done()
if mac {
cmd := exec.Command("arping", "-q", "-c", "1", "-w", "5000000", e)
if err := cmd.Run(); err == nil {
cmd2 := exec.Command("arping", "-c", "1", e)
out, err := cmd2.CombinedOutput()
if err == nil {
results[i] = string(out)
} else {
results[i] = e + "\n"
}
} else {
results[i] = e + "\n"
}
} else {
cmd := exec.Command("host", e)
out, err := cmd.CombinedOutput()
if err == nil {
// Extract the hostname via regex (similar to grep -Po '(?<=pointer ).*')
reHost := regexp.MustCompile(`(?i)(?<=pointer\s)(\S+)`)
match := reHost.FindString(string(out))
if match != "" {
results[i] = fmt.Sprintf("%s %s", e, match)
} else {
results[i] = e
}
} else {
results[i] = e
}
}
}(i, entry)
}
wg.Wait()
return results
}
// lookupIPInfo queries ipinfo.io for each IP concurrently,
// checking a local cache before going to the network.
// It returns a slice of IPInfo.
func lookupIPInfo(entries []string, cache map[string]IPInfo, cacheMu *sync.Mutex) []IPInfo {
var wg sync.WaitGroup
var mu sync.Mutex
var results []IPInfo
client := &http.Client{
Timeout: 5 * time.Second,
}
for _, ip := range entries {
wg.Add(1)
go func(ip string) {
defer wg.Done()
// Check cache first.
cacheMu.Lock()
info, found := cache[ip]
cacheMu.Unlock()
if found {
mu.Lock()
results = append(results, info)
mu.Unlock()
return
}
// Not in cache; perform HTTP lookup.
url := fmt.Sprintf("https://ipinfo.io/%s", ip)
resp, err := client.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return
}
var newInfo IPInfo
if err := json.Unmarshal(body, &newInfo); err != nil {
return
}
// Only add valid responses.
if newInfo.IP == "" {
return
}
// Update cache.
cacheMu.Lock()
cache[ip] = newInfo
cacheMu.Unlock()
mu.Lock()
results = append(results, newInfo)
mu.Unlock()
}(ip)
}
wg.Wait()
return results
}
// loadCache reads the cache from ~/.ipgrep.db (if present)
// and returns it as a map[string]IPInfo.
func loadCache() map[string]IPInfo {
home, err := os.UserHomeDir()
if err != nil {
return make(map[string]IPInfo)
}
cachePath := home + "/.ipgrep.db"
data, err := ioutil.ReadFile(cachePath)
if err != nil {
// File doesn't exist or can't be read, start with an empty cache.
return make(map[string]IPInfo)
}
var cache map[string]IPInfo
if err := json.Unmarshal(data, &cache); err != nil {
// If unmarshal fails, use an empty cache.
return make(map[string]IPInfo)
}
return cache
}
// saveCache writes the cache map to ~/.ipgrep.db.
func saveCache(cache map[string]IPInfo) {
home, err := os.UserHomeDir()
if err != nil {
return
}
cachePath := home + "/.ipgrep.db"
data, err := json.MarshalIndent(cache, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "Error marshaling cache: %v\n", err)
return
}
if err := ioutil.WriteFile(cachePath, data, 0644); err != nil {
fmt.Fprintf(os.Stderr, "Error writing cache file: %v\n", err)
}
}

Binary file not shown.

View File

@@ -0,0 +1,502 @@
package main
import (
"encoding/json"
"fmt"
"log"
"os/exec"
"regexp"
"runtime"
"strings"
"time"
)
// Software holds information about installed software
type Software struct {
Source string `json:"source"`
Name string `json:"name"`
Version string `json:"version"`
InstallDate string `json:"install_date"`
}
func main() {
var softwareList []Software
if runtime.GOOS == "windows" {
softwareList = append(softwareList, enumerateWindows()...)
} else if runtime.GOOS == "linux" {
softwareList = append(softwareList, enumerateLinux()...)
}
output, err := json.MarshalIndent(softwareList, "", " ")
if err != nil {
log.Println("Error marshalling software list:", err)
return
}
fmt.Println(string(output))
}
// Add to the enumerateWindows function
func enumerateWindows() []Software {
var softwareList []Software
// Winget
softwareList = append(softwareList, enumerateWinget()...)
// Chocolatey
softwareList = append(softwareList, enumerateChocolatey()...)
// Scoop
softwareList = append(softwareList, enumerateScoop()...)
// Common Windows Installations
softwareList = append(softwareList, enumerateCommonWindows()...)
// NuGet
softwareList = append(softwareList, enumerateNuGet()...)
// Microsoft Store
softwareList = append(softwareList, enumerateMicrosoftStore()...)
return softwareList
}
// Add to the enumerateLinux function
func enumerateLinux() []Software {
var softwareList []Software
// APT
softwareList = append(softwareList, enumerateApt()...)
// Snap
softwareList = append(softwareList, enumerateSnap()...)
// Pip
softwareList = append(softwareList, enumeratePip()...)
// NPM
softwareList = append(softwareList, enumerateNpm()...)
// Flatpak
softwareList = append(softwareList, enumerateFlatpak()...)
// RPM
softwareList = append(softwareList, enumerateRpm()...)
// Pacman
softwareList = append(softwareList, enumeratePacman()...)
// Homebrew
softwareList = append(softwareList, enumerateHomebrew()...)
// Conda
softwareList = append(softwareList, enumerateConda()...)
return softwareList
}
func enumerateNuGet() []Software {
var softwareList []Software
output, err := runCommand("nuget", "list", "-AllVersions")
if err != nil {
log.Println("Error enumerating NuGet packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "nuget",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateMicrosoftStore() []Software {
var softwareList []Software
output, err := runCommand("powershell", "Get-AppxPackage", "|", "Select-Object", "Name,PackageFullName,InstallDate")
if err != nil {
log.Println("Error enumerating Microsoft Store packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 3 {
continue
}
softwareList = append(softwareList, Software{
Source: "microsoft store",
Name: parts[0],
Version: parts[1],
InstallDate: parseInstallDate(parts[2]),
})
}
return softwareList
}
func enumerateFlatpak() []Software {
var softwareList []Software
output, err := runCommand("flatpak", "list")
if err != nil {
log.Println("Error enumerating Flatpak packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "flatpak",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateRpm() []Software {
var softwareList []Software
output, err := runCommand("rpm", "-qa", "--queryformat", "%{NAME} %{VERSION}\n")
if err != nil {
log.Println("Error enumerating RPM packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "rpm",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumeratePacman() []Software {
var softwareList []Software
output, err := runCommand("pacman", "-Q")
if err != nil {
log.Println("Error enumerating Pacman packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "pacman",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateHomebrew() []Software {
var softwareList []Software
output, err := runCommand("brew", "list", "--versions")
if err != nil {
log.Println("Error enumerating Homebrew packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "homebrew",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateConda() []Software {
var softwareList []Software
output, err := runCommand("conda", "list", "--json")
if err != nil {
log.Println("Error enumerating Conda packages:", err)
return softwareList
}
var condaPackages []map[string]interface{}
err = json.Unmarshal([]byte(output), &condaPackages)
if err != nil {
log.Println("Error parsing Conda JSON output:", err)
return softwareList
}
for _, pkg := range condaPackages {
softwareList = append(softwareList, Software{
Source: "conda",
Name: pkg["name"].(string),
Version: pkg["version"].(string),
})
}
return softwareList
}
func runCommand(cmd string, args ...string) (string, error) {
out, err := exec.Command(cmd, args...).Output()
if err != nil {
return "", err
}
return string(out), nil
}
func parseInstallDate(dateString string) string {
layout := "2006-01-02"
date, err := time.Parse(layout, dateString)
if err != nil {
return ""
}
return date.Format(layout)
}
func enumerateWinget() []Software {
var softwareList []Software
output, err := runCommand("winget", "list", "--source", "winget")
if err != nil {
log.Println("Error enumerating Winget packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := regexp.MustCompile(`\s+`).Split(line, -1)
if len(parts) < 4 {
continue
}
softwareList = append(softwareList, Software{
Source: "winget",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateChocolatey() []Software {
var softwareList []Software
output, err := runCommand("choco", "list", "--local-only")
if err != nil {
log.Println("Error enumerating Chocolatey packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Split(line, "|")
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "chocolatey",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateScoop() []Software {
var softwareList []Software
output, err := runCommand("scoop", "list")
if err != nil {
log.Println("Error enumerating Scoop packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
if strings.HasPrefix(line, "Installed apps") {
continue
}
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "scoop",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateCommonWindows() []Software {
var softwareList []Software
output, err := runCommand("powershell", "Get-WmiObject", "-Class", "Win32_Product", "|", "Select-Object", "Name,Version,InstallDate")
if err != nil {
log.Println("Error enumerating common Windows installations:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 3 {
continue
}
softwareList = append(softwareList, Software{
Source: "common windows installation",
Name: parts[0],
Version: parts[1],
InstallDate: parseInstallDate(parts[2]),
})
}
return softwareList
}
func enumerateApt() []Software {
var softwareList []Software
output, err := runCommand("dpkg-query", "-W", "-f=${binary:Package} ${Version} ${Installed-Size}\n")
if err != nil {
log.Println("Error enumerating APT packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
softwareList = append(softwareList, Software{
Source: "apt",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumerateSnap() []Software {
var softwareList []Software
output, err := runCommand("snap", "list")
if err != nil {
log.Println("Error enumerating Snap packages:", err)
return softwareList
}
lines := strings.Split(output, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 3 {
continue
}
softwareList = append(softwareList, Software{
Source: "snap",
Name: parts[0],
Version: parts[1],
})
}
return softwareList
}
func enumeratePip() []Software {
var softwareList []Software
output, err := runCommand("pip", "list", "--format=json")
if err != nil {
log.Println("Error enumerating Pip packages:", err)
return softwareList
}
var pipPackages []map[string]string
err = json.Unmarshal([]byte(output), &pipPackages)
if err != nil {
log.Println("Error parsing Pip JSON output:", err)
return softwareList
}
for _, pkg := range pipPackages {
softwareList = append(softwareList, Software{
Source: "pip",
Name: pkg["name"],
Version: pkg["version"],
})
}
return softwareList
}
func enumerateNpm() []Software {
var softwareList []Software
output, err := runCommand("npm", "list", "-g", "--depth=0", "--json")
if err != nil {
log.Println("Error enumerating NPM packages:", err)
return softwareList
}
var npmPackages map[string]interface{}
err = json.Unmarshal([]byte(output), &npmPackages)
if err != nil {
log.Println("Error parsing NPM JSON output:", err)
return softwareList
}
dependencies := npmPackages["dependencies"].(map[string]interface{})
for name, info := range dependencies {
infoMap := info.(map[string]interface{})
version := infoMap["version"].(string)
softwareList = append(softwareList, Software{
Source: "npm",
Name: name,
Version: version,
})
}
return softwareList
}

View File

@@ -0,0 +1,75 @@
package main
import (
"bufio"
"flag"
"fmt"
"hash/fnv"
"log"
"os"
)
func hashLine(s string) uint32 {
hasher := fnv.New32a()
hasher.Write([]byte(s))
return hasher.Sum32()
}
func main() {
// Define command line flags
reverse := flag.Bool("d", false, "Print only lines that appear more than once.")
help := flag.Bool("h", false, "Display help and usage information.")
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
fmt.Println("This program reads from a file or standard input, deduplicates lines, and outputs the results.")
fmt.Println("Options:")
flag.PrintDefaults()
fmt.Println("Example usage:")
fmt.Println("\t", os.Args[0], "[options] [filename]")
fmt.Println("\t", os.Args[0], "-d filename # Only print duplicates")
fmt.Println("\t", "cat /some/text/file |", os.Args[0], "# Read from standard input")
}
flag.Parse()
// Check for help flag
if *help {
flag.Usage()
os.Exit(0)
}
// Detemine the input source (file or stdin)
inputSource := os.Stdin
var err error
if flag.NArg() > 0 {
inputSource, err = os.Open(flag.Args()[0])
if err != nil {
log.Fatalf("Failed to open file: %v\n", err)
}
defer inputSource.Close()
}
seenLines := make(map[uint32]int)
scanner := bufio.NewScanner(inputSource)
//Readin lines
for scanner.Scan() {
line := scanner.Text()
hash := hashLine(line)
seenLines[hash]++
if *reverse {
// Print only lines that appear more than once
if seenLines[hash] > 1 {
fmt.Println(line)
}
} else {
// Normal mode, print only unique lines
if seenLines[hash] == 1 {
fmt.Println(line)
}
}
}
//Check for errors during scanning
if err := scanner.Err(); err != nil {
log.Fatalf("Failed to read input: %v\n", err)
}
}

View File

@@ -0,0 +1,25 @@
[[[1, 1, 1, 1, 22],
[6, 6, 6, 6, 22],
[2, 6, 9, 22, 22],
[9, 9, 9, 9, 22],
[10, 15, 15, 15, 15]],
[[2, 11, 1, 19, 20],
[2, 11, 13, 19, 21],
[2, 11, 11, 19, 23],
[2, 11, 17, 19, 24],
[10, 14, 18, 15, 25]],
[[3, 3, 3, 3, 20],
[4, 13, 13, 19, 21],
[8, 8, 8, 8, 23],
[10, 14, 17, 17, 24],
[10, 14, 18, 18, 25]],
[[4, 12, 3, 20, 20],
[4, 12, 13, 21, 21],
[4, 12, 8, 23, 23],
[4, 12, 17, 24, 24],
[10, 14, 18, 25, 25]],
[[5, 5, 5, 5, 20],
[7, 5, 13, 16, 21],
[7, 12, 16, 16, 23],
[7, 7, 17, 16, 24],
[7, 14, 18, 16, 25]]]

129
projects/puzzlebox/solve.py Normal file
View File

@@ -0,0 +1,129 @@
import pprint
import operator
import numpy as np
import math
from copy import copy, deepcopy
piece=[[0,0,0],[0,1,0],[0,2,0],[0,3,0],[1,2,0]]
sizeofcube=5
def init_cube(size=sizeofcube):
return [[[0 for x in range(0,size)] for y in range(0,size)] for z in range(0,size)]
def move_start_position(piece,index):
return [np.subtract(x, piece[index]) for x in piece]
def draw_cube(cube):
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect('equal')
ax.set_xlabel('x', fontsize=10)
ax.set_ylabel('y', fontsize=10)
ax.set_zlabel('z', fontsize=10)
ma=np.array(cube)
ax.voxels(ma, edgecolor="k")
plt.show()
def put_piece_in_cube(piece,cube,position,index):
cursors = [np.add(position,p) for p in piece]
in_cube = [ max(c) < len(cube) and min(c) >= 0 for c in cursors]
if all(in_cube):
for cursor in cursors:
try:
if cube[cursor[0]][cursor[1]][cursor[2]]!=0:
return False
except:
return False
for cursor in cursors:
cube[cursor[0]][cursor[1]][cursor[2]]=index
return True
else:
return False
def rotate_vector(vector,axis,angle):
x,y,z=vector
angle=math.radians(angle)
if axis == "z":
return (int(round((x*math.cos(angle)) - (y*math.sin(angle)))),int(round((x*math.sin(angle)) + (y*math.cos(angle)))),z)
if axis == "y":
return (int(round(x*math.cos(angle) + z*math.sin(angle))),y,int(round(-x*math.sin(angle) + z*math.cos(angle))))
if axis == "x":
return (x,int(round(y*math.cos(angle) - z*math.sin(angle))),int(round(y*math.sin(angle) + z*math.cos(angle))))
def rotate_piece(piece,axis,angle):
return [rotate_vector(x, axis, angle) for x in piece]
def shift_piece(piece,anchor_index):
anchor=piece[anchor_index]
return [np.subtract(p,anchor) for p in piece]
def generate_rotations(piece):
all_rotations=set()
for i in range(0,4):
for j in range(0,4):
for k in range(0,4):
for p in range(0,5):
rotated_piece=rotate_piece(rotate_piece(rotate_piece(shift_piece(piece,p),"x",k*90),"y",j*90),"z",i*90)
all_rotations.add(tuple(rotated_piece))
return frozenset(all_rotations)
def find_empty_spot(cube):
for z in range(0,sizeofcube):
for y in range(0,sizeofcube):
for x in range(0,sizeofcube):
if cube[x][y][z]==0:
return (x,y,z)
return None
def solve(cube,index):
#make copy of cube
global maxindex
if index > maxindex:
print(index)
maxindex=index
backup=deepcopy(cube)
# draw_cube(backup)
#make copy of available pieces
global all_rotations
pieces=set(all_rotations.copy())
# print("{}:find empty spot#########################".format(index))
empty_pos=find_empty_spot(backup)
if empty_pos==None:
pprint.pprint(cube)
draw_cube(cube)
return True
else:
(x,y,z)=empty_pos
# print("{}:empty_spot at ({},{},{})".format(index,x,y,z))
#found empty space > trying to fill it
while len(pieces)>0:
#use copy of cube without my parts
local_cube=deepcopy(backup)
piece=pieces.pop()
if put_piece_in_cube(piece, local_cube, (x,y,z), index):
# print("{}:found fitting piece {} ({} left)".format(index,piece,len(pieces)))
if solve(local_cube, index+1):
return True
else:
# print("{}:removing ({},{},{}):{}".format(index,x,y,z,len(pieces)))
pass
#nothing fits return fail
return False
maxindex=0
def main():
global all_rotations
all_rotations=generate_rotations(piece)
solve(init_cube(),1)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,85 @@
import numpy as np
import math
from operator import add
import matplotlib.pyplot as plt
import pprint
from mpl_toolkits.mplot3d import Axes3D
# g_cube=np.zeros((10,10,10))
n=6
g_cube=[[[0 for k in range(0,n)] for j in range(0,n)] for i in range(0,n)]
form=[[0,0,0],[1,0,0],[2,0,0],[3,0,0],[2,1,0]]
def set_origin(form,index):
newform=list()
for x in form:
newform.append(np.subtract(x,form[index]))
return newform
def vector_rotate(vector,angle,axis):
if axis=='x':
result=[vector[0],( ( vector[1]*math.cos(angle) ) - ( vector[2]*math.sin(angle) ) ),( ( vector[1]*math.sin(angle) ) + ( vector[2]*math.cos(angle) ) )]
if axis=='y':
result=[( ( vector[0]*math.cos(angle) ) + ( vector[2]*math.sin(angle) ) ),vector[1],( ( -vector[0]*math.sin(angle) ) + ( vector[2]*math.cos(angle) ) )]
if axis=='z':
result=[( ( vector[0]*math.cos(angle) ) - ( vector[1]*math.sin(angle) ) ),( ( vector[0]*math.sin(angle) ) + ( vector[1]*math.cos(angle) ) )]
def form_in_cube(form):
for cursor in form:
for element in cursor:
if element<=0 or element>=n:
return False
return True
def put_in(form,cube,offset,piece=1):
form_positions=[(x+offset[0],y+offset[1],z+offset[2]) for (x,y,z) in form]
# form_positions=list([map(add,p,offset) for p in form])
if form_in_cube(form_positions):
for cursor in form_positions:
cube[cursor[0]][cursor[1]][cursor[2]]=piece
print("set ({},{},{}) to {}".format(cursor[0],cursor[1],cursor[2],piece))
else:
print("out")
def draw_field(g_cube):
# g_cube=np.zeros((6,6,6))
# g_cube=cube
# prepare some coordinates
# x, y, z = np.indices((6, 6, 6))
x, y, z = np.indices((len(g_cube),len(g_cube[0]), len(g_cube[0][0])))
farben=["red","blue","green","cyan","magenta","yellow"]
list_of_cubes =list()
for x_pos in range(0,len(g_cube)):
for y_pos in range(0,len(g_cube[x_pos])):
for z_pos in range(0,len(g_cube[x_pos][y_pos])):
color=(g_cube[x_pos][y_pos][z_pos])
if color>0:
print("Voxel by ({},{},{}) : {}".format(x_pos,y_pos,z_pos,type(g_cube[x_pos][y_pos][z_pos])))
farbe=farben[int((color+1)%len(farben))]
list_of_cubes.append({"cube":(x < x_pos) & (x >= (x_pos-1) ) & (y < y_pos) & (y >= (y_pos-1) ) & (z < z_pos) & (z >= (z_pos-1) ),"farbe":farbe})
voxels=list_of_cubes[0]["cube"]
colors = np.empty(voxels.shape, dtype=object)
for x in list_of_cubes:
voxels=voxels | x["cube"]
colors[x["cube"]]=x["farbe"]
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.voxels(voxels, facecolors=colors, edgecolor='k')
plt.show()
put_in(set_origin(form,3),g_cube,(1,2,1),1)
put_in(set_origin(form,4),g_cube,(2,2,2),2)
put_in(set_origin(form,3),g_cube,(3,2,3),1)
put_in(set_origin(form,4),g_cube,(4,2,4),2)
draw_field(g_cube)

View File

@@ -0,0 +1,175 @@
import pprint
import operator
import numpy as np
import math
from copy import copy, deepcopy
import profile
piece=[[0,0,0],[0,1,0],[0,2,0],[0,3,0],[1,2,0]]
sizeofcube=5
def init_cube(size=sizeofcube):
return [[[0 for x in range(0,size)] for y in range(0,size)] for z in range(0,size)]
def move_start_position(piece,index):
return [np.subtract(x, piece[index]) for x in piece]
def draw_cube(cube):
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect('equal')
ax.set_xlabel('x', fontsize=10)
ax.set_ylabel('y', fontsize=10)
ax.set_zlabel('z', fontsize=10)
ma=np.array(cube)
ax.voxels(ma, edgecolor="k")
plt.show()
def set_cube_vals(cursors,cube,value):
for cursor in cursors:
cube[cursor[0]][cursor[1]][cursor[2]]=value
def is_valid(piece,position):
global sizeofcube
upper_x=sizeofcube-position[0]
upper_y=sizeofcube-position[1]
upper_z=sizeofcube-position[2]
for (x,y,z) in piece:
if x<-position[0] or x>upper_x:
return False
if y<-position[1] or y>upper_y:
return False
if z<-position[2] or z>upper_z:
return False
return True
def put_piece_in_cube(piece,cube,position,index):
if is_valid(piece,position):
# cursors = [np.add(position,p) for p in piece]
# for cursor in cursors:
cursors=[]
for (x,y,z) in piece:
cursor=[(x+position[0]),(y+position[1]),(z+position[2])]
cursors.append(cursor)
try:
if cube[cursor[0]][cursor[1]][cursor[2]]!=0:
return False
except:
return False
set_cube_vals(cursors, cube, index)
return True
else:
return False
def remove_piece_in_cube(piece,cube,position):
cursors = [np.add(position,p) for p in piece]
set_cube_vals(cursors, cube, 0)
def rotate_vector(vector,axis,angle):
x,y,z=vector
angle=math.radians(angle)
if axis == "z":
return (int(round((x*math.cos(angle)) - (y*math.sin(angle)))),int(round((x*math.sin(angle)) + (y*math.cos(angle)))),z)
if axis == "y":
return (int(round(x*math.cos(angle) + z*math.sin(angle))),y,int(round(-x*math.sin(angle) + z*math.cos(angle))))
if axis == "x":
return (x,int(round(y*math.cos(angle) - z*math.sin(angle))),int(round(y*math.sin(angle) + z*math.cos(angle))))
def rotate_piece(piece,axis,angle):
return [rotate_vector(x, axis, angle) for x in piece]
def shift_piece(piece,anchor_index):
anchor=piece[anchor_index]
return [np.subtract(p,anchor) for p in piece]
def generate_rotations(piece):
all_rotations=set()
for i in range(0,4):
for j in range(0,4):
for k in range(0,4):
for p in range(0,len(piece)):
rotated_piece=rotate_piece(rotate_piece(rotate_piece(shift_piece(piece,p),"x",k*90),"y",j*90),"z",i*90)
all_rotations.add(tuple(rotated_piece))
return frozenset(all_rotations)
def find_empty_spot(cube):
for z in range(0,sizeofcube):
for y in range(0,sizeofcube):
for x in range(0,sizeofcube):
if cube[x][y][z]==0:
return (x,y,z)
return None
def printstats():
global stat_counter
global stats
stat_counter=stat_counter+1
if stat_counter%10000==0:
print(stat_counter)
for x in stats:
print("{}:{}".format(x,stats[x]))
if x>5:
break
def parallel_pool_init():
global stats
global solutions
stats=dict()
solutions=list()
def parallel_solve(cube):
global all_rotations
all_rotations=generate_rotations(piece)
pieces=set(all_rotations.copy())
first_position=(0,0,0)
while len(pieces)>0:
piece=pieces.pop()
if put_piece_in_cube(piece, cube, first_position, index):
solve(cube, 2,):
def solve(cube,index):
global stats
global solutions
global all_rotations
pieces=set(all_rotations.copy())
# print("{}:find empty spot#########################".format(index))
empty_pos=find_empty_spot(cube)
if empty_pos==None:
pprint.pprint(cube)
draw_cube(cube)
solutions.append(cube)
return False
else:
(x,y,z)=empty_pos
while len(pieces)>0:
#use copy of cube without my parts
piece=pieces.pop()
if put_piece_in_cube(piece, cube, (x,y,z), index):
# print("{}:found fitting piece {} ({} left)".format(index,piece,len(pieces)))
stats[index]=len(pieces)
if solve(cube, index+1):
return True
else:
remove_piece_in_cube(piece, cube, (x,y,z))
#nothing fits return fail
return False
# maxindex=0
# stat_counter=0
# stats=dict()
# last_stats=dict()
def main():
parallel_solve(init_cube())
if __name__ == '__main__':
# profile.run('main()')
main()

View File

@@ -0,0 +1,177 @@
import pprint
import operator
import numpy as np
import math
from copy import copy, deepcopy
import profile
piece=[[0,0,0],[0,1,0],[0,2,0],[0,3,0],[1,2,0]]
sizeofcube=5
def init_cube(size=sizeofcube):
return [[[0 for x in range(0,size)] for y in range(0,size)] for z in range(0,size)]
def move_start_position(piece,index):
return [np.subtract(x, piece[index]) for x in piece]
def draw_cube(cube):
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect('equal')
ax.set_xlabel('x', fontsize=10)
ax.set_ylabel('y', fontsize=10)
ax.set_zlabel('z', fontsize=10)
ma=np.array(cube)
ax.voxels(ma, edgecolor="k")
plt.show()
def set_cube_vals(cursors,cube,value):
for cursor in cursors:
cube[cursor[0]][cursor[1]][cursor[2]]=value
def is_valid(piece,position):
global sizeofcube
upper_x=sizeofcube-position[0]
upper_y=sizeofcube-position[1]
upper_z=sizeofcube-position[2]
for (x,y,z) in piece:
if x<-position[0] or x>upper_x:
return False
if y<-position[1] or y>upper_y:
return False
if z<-position[2] or z>upper_z:
return False
return True
def put_piece_in_cube(piece,cube,position,index):
if is_valid(piece,position):
# cursors = [np.add(position,p) for p in piece]
# for cursor in cursors:
cursors=[]
for (x,y,z) in piece:
cursor=[(x+position[0]),(y+position[1]),(z+position[2])]
cursors.append(cursor)
try:
if cube[cursor[0]][cursor[1]][cursor[2]]!=0:
return False
except:
return False
set_cube_vals(cursors, cube, index)
return True
else:
return False
def remove_piece_in_cube(piece,cube,position):
cursors = [np.add(position,p) for p in piece]
set_cube_vals(cursors, cube, 0)
def rotate_vector(vector,axis,angle):
x,y,z=vector
angle=math.radians(angle)
if axis == "z":
return (int(round((x*math.cos(angle)) - (y*math.sin(angle)))),int(round((x*math.sin(angle)) + (y*math.cos(angle)))),z)
if axis == "y":
return (int(round(x*math.cos(angle) + z*math.sin(angle))),y,int(round(-x*math.sin(angle) + z*math.cos(angle))))
if axis == "x":
return (x,int(round(y*math.cos(angle) - z*math.sin(angle))),int(round(y*math.sin(angle) + z*math.cos(angle))))
def rotate_piece(piece,axis,angle):
return [rotate_vector(x, axis, angle) for x in piece]
def shift_piece(piece,anchor_index):
anchor=piece[anchor_index]
return [np.subtract(p,anchor) for p in piece]
def generate_rotations(piece):
all_rotations=set()
for i in range(0,4):
for j in range(0,4):
for k in range(0,4):
for p in range(0,len(piece)):
rotated_piece=rotate_piece(rotate_piece(rotate_piece(shift_piece(piece,p),"x",k*90),"y",j*90),"z",i*90)
all_rotations.add(tuple(rotated_piece))
return frozenset(all_rotations)
def find_empty_spot(cube):
for z in range(0,sizeofcube):
for y in range(0,sizeofcube):
for x in range(0,sizeofcube):
if cube[x][y][z]==0:
return (x,y,z)
return None
def printstats():
global stat_counter
global stats
stat_counter=stat_counter+1
if stat_counter%10000==0:
print(stat_counter)
for x in stats:
print("{}:{}".format(x,stats[x]))
if x>5:
break
def parallel_pool_init():
global stats
global solutions
stats=dict()
solutions=list()
def parallel_solve(cube):
global all_rotations
all_rotations=generate_rotations(piece)
pieces=set(all_rotations.copy())
first_position=(0,0,0)
while len(pieces)>0:
piece=pieces.pop()
if put_piece_in_cube(piece, cube, first_position, index):
stats["jobid"]={"0"=>len(pieces)}
solve(cube, 2,):
def solve(cube,index,jobid):
global stats
global solutions
global all_rotations
pieces=set(all_rotations.copy())
# print("{}:find empty spot#########################".format(index))
empty_pos=find_empty_spot(cube)
if empty_pos==None:
pprint.pprint(cube)
draw_cube(cube)
solutions.append(cube)
return False
else:
(x,y,z)=empty_pos
while len(pieces)>0:
#use copy of cube without my parts
piece=pieces.pop()
if put_piece_in_cube(piece, cube, (x,y,z), index):
# print("{}:found fitting piece {} ({} left)".format(index,piece,len(pieces)))
stats[index]=len(pieces)
if solve(cube, index+1):
return True
else:
remove_piece_in_cube(piece, cube, (x,y,z))
#nothing fits return fail
return False
# maxindex=0
# stat_counter=0
# stats=dict()
# last_stats=dict()
def main():
parallel_solve(init_cube())
if __name__ == '__main__':
# profile.run('main()')
main()

View File

@@ -0,0 +1,99 @@
'''
==========================
3D voxel / volumetric plot
==========================
Demonstrates plotting 3D volumetric objects with ``ax.voxels``
'''
import matplotlib.pyplot as plt
import numpy as np
import pprint
import random
from matplotlib import colors as mcolors
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
g_cube=np.zeros((6,6,6))
# prepare some coordinates
x, y, z = np.indices((6, 6, 6))
# farben=["red","blue","green","cyan","magenta","yellow"]
farben=[name for name in mcolors.CSS4_COLORS]
random.shuffle(farben)
g_cube=[[[1, 1, 1, 1, 22],
[6, 6, 6, 6, 22],
[2, 6, 9, 22, 22],
[9, 9, 9, 9, 22],
[10, 15, 15, 15, 15]],
[[2, 11, 1, 19, 20],
[2, 11, 13, 19, 21],
[2, 11, 11, 19, 23],
[2, 11, 17, 19, 24],
[10, 14, 18, 15, 25]],
[[3, 3, 3, 3, 20],
[4, 13, 13, 19, 21],
[8, 8, 8, 8, 23],
[10, 14, 17, 17, 24],
[10, 14, 18, 18, 25]],
[[4, 12, 3, 20, 20],
[4, 12, 13, 21, 21],
[4, 12, 8, 23, 23],
[4, 12, 17, 24, 24],
[10, 14, 18, 25, 25]],
[[5, 5, 5, 5, 20],
[7, 5, 13, 16, 21],
[7, 12, 16, 16, 23],
[7, 7, 17, 16, 24],
[7, 14, 18, 16, 25]]]
list_of_cubes =list()
color_counter=0
for x_pos in range(0,len(g_cube)):
for y_pos in range(0,len(g_cube[x_pos])):
for z_pos in range(0,len(g_cube[x_pos][y_pos])):
if g_cube[x_pos][y_pos][z_pos]!=0:
cur_farbe=g_cube[x_pos][y_pos][z_pos]%len(farben)
print("Voxel by in {} for ({}>x>={}//{}>y>={}//{}>z>={}) )".format(farben[cur_farbe],x_pos,x_pos+1,y_pos,y_pos+1,z_pos,z_pos+1))
list_of_cubes.append({"cube":(x > x_pos) & (x <= (x_pos+1) ) & (y > y_pos) & (y <= (y_pos+1) ) & (z > z_pos) & (z <= (z_pos+1) ),"farbe":farben[cur_farbe]})
color_counter=(color_counter + 1) % len (farben)
voxels=list_of_cubes[0]["cube"]
colors = np.empty(voxels.shape, dtype=object)
for x in list_of_cubes:
voxels=voxels | x["cube"]
colors[x["cube"]]=x["farbe"]
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.voxels(voxels, facecolors=colors, edgecolor='k')
plt.show()
# draw cuboids in the top left and bottom right corners, and a link between them
#
# cube1 = (x < 3) & (y < 3) & (z < 3)
# cube2 = (x >= 5) & (y >= 5) & (z >= 5)
# link = abs(x - y) + abs(y - z) + abs(z - x) <= 2
#
# # combine the objects into a single boolean array
# voxels = cube1 | cube2 | link
#
# # set the colors of each object
# colors = np.empty(voxels.shape, dtype=object)
# colors[link] = 'red'
# colors[cube1] = 'blue'
# colors[cube2] = 'green'
#
# # and plot everything
# fig = plt.figure()
# ax = fig.gca(projection='3d')
# ax.voxels(voxels, facecolors=colors, edgecolor='k')
#
# plt.show()

View File

@@ -0,0 +1,55 @@
use std::env;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
fn main() -> io::Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} start-end [count] [file...]", args[0]);
std::process::exit(1);
}
let range = &args[1];
let (start, mut end) = if let Some(dash_pos) = range.find('-') {
(range[..dash_pos].parse().unwrap(), range[dash_pos + 1..].parse().unwrap())
} else {
(range.parse().unwrap(), 0)
};
let mut count = 1;
let mut files_start = 2;
if end == 0 {
if args.len() > 2 {
if let Ok(c) = args[2].parse::<usize>() {
count = c;
files_start = 3;
}
}
end = start + count - 1;
}
if args.len() > files_start {
for filename in &args[files_start..] {
let file = File::open(filename)?;
let reader = BufReader::new(file);
process_lines(reader, start, end)?;
}
} else {
// No files provided, read from stdin
let stdin = io::stdin();
let reader = stdin.lock();
process_lines(reader, start, end)?;
}
Ok(())
}
fn process_lines<R: BufRead>(reader: R, start: usize, end: usize) -> io::Result<()> {
reader.lines()
.enumerate()
.filter_map(|(i, line)| if i + 1 >= start && i + 1 <= end { line.ok() } else { None })
.for_each(|line| println!("{}", line));
Ok(())
}

BIN
projects/rust-tools/uniq Executable file

Binary file not shown.

View File

@@ -0,0 +1,41 @@
use std::env;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::collections::HashSet;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
fn main() -> io::Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() > 1 {
for filename in &args[1..] {
let file = File::open(filename)?;
let reader = BufReader::new(file);
remove_duplicates(reader)?;
}
} else {
// No files provided, read from stdin
let stdin = io::stdin();
let reader = stdin.lock();
remove_duplicates(reader)?;
}
Ok(())
}
fn remove_duplicates<R: BufRead>(reader: R) -> io::Result<()> {
let mut seen_hashes = HashSet::new();
for line in reader.lines() {
let line = line?;
let mut hasher = DefaultHasher::new();
line.hash(&mut hasher);
let hash = hasher.finish();
if seen_hashes.insert(hash) {
println!("{}", line);
}
}
Ok(())
}

BIN
projects/rust-tools/uniq2 Executable file

Binary file not shown.

View File

@@ -0,0 +1,36 @@
use std::collections::HashSet;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
struct HashOnlySet {
set: HashSet<u64>,
}
impl HashOnlySet {
fn new() -> HashOnlySet {
HashOnlySet { set: HashSet::new() }
}
fn insert<T: Hash>(&mut self, item: &T) -> bool {
let hash = Self::hash_item(item);
self.set.insert(hash)
}
fn contains<T: Hash>(&self, item: &T) -> bool {
let hash = Self::hash_item(item);
self.set.contains(&hash)
}
fn hash_item<T: Hash>(item: &T) -> u64 {
let mut hasher = DefaultHasher::new();
item.hash(&mut hasher);
hasher.finish()
}
}
fn main() {
let mut set = HashOnlySet::new();
set.insert(&"Hello, world!");
println!("Contains 'Hello, world!': {}", set.contains(&"Hello, world!"));
println!("Contains 'Goodbye, world!': {}", set.contains(&"Goodbye, world!"));
}

View File

@@ -0,0 +1,72 @@
#!/bin/bash
# Create dirs
mkdir -p timesketch/{data/postgresql,data/elasticsearch,logs,etc,etc/timesketch,etc/timesketch/sigma/rules,upload}
echo -n "* Setting default config parameters.."
POSTGRES_USER="timesketch"
POSTGRES_PASSWORD="$(< /dev/urandom tr -dc A-Za-z0-9 | head -c 32 ; echo)"
POSTGRES_ADDRESS="postgres"
POSTGRES_PORT=5432
SECRET_KEY="$(< /dev/urandom tr -dc A-Za-z0-9 | head -c 32 ; echo)"
ELASTIC_ADDRESS="elasticsearch"
ELASTIC_PORT=9200
REDIS_ADDRESS="redis"
REDIS_PORT=6379
GITHUB_BASE_URL="https://raw.githubusercontent.com/google/timesketch/master"
ELASTIC_MEM_USE_GB=$(cat /proc/meminfo | grep MemTotal | awk '{printf "%.0f", ($2 / 1000000 / 2)}')
echo "OK"
echo "* Setting Elasticsearch memory allocation to ${ELASTIC_MEM_USE_GB}GB"
# Docker compose and configuration
echo -n "* Fetching configuration files.."
curl $GITHUB_BASE_URL/docker/release/docker-compose.yml > timesketch/docker-compose.yml
curl $GITHUB_BASE_URL/docker/release/config.env > timesketch/config.env
# Fetch default Timesketch config files
curl $GITHUB_BASE_URL/data/timesketch.conf > timesketch/etc/timesketch/timesketch.conf
curl $GITHUB_BASE_URL/data/tags.yaml > timesketch/etc/timesketch/tags.yaml
curl $GITHUB_BASE_URL/data/plaso.mappings > timesketch/etc/timesketch/plaso.mappings
curl $GITHUB_BASE_URL/data/generic.mappings > timesketch/etc/timesketch/generic.mappings
curl $GITHUB_BASE_URL/data/features.yaml > timesketch/etc/timesketch/features.yaml
curl $GITHUB_BASE_URL/data/sigma_config.yaml > timesketch/etc/timesketch/sigma_config.yaml
curl $GITHUB_BASE_URL/data/sigma/rules/lnx_susp_zenmap.yml > timesketch/etc/timesketch/sigma/rules/lnx_susp_zenmap.yml
curl $GITHUB_BASE_URL/contrib/nginx.conf > timesketch/etc/nginx.conf
echo "OK"
# Create a minimal Timesketch config
echo -n "* Edit configuration files.."
sed -i 's#SECRET_KEY = \x27\x3CKEY_GOES_HERE\x3E\x27#SECRET_KEY = \x27'$SECRET_KEY'\x27#' timesketch/etc/timesketch/timesketch.conf
# Set up the Elastic connection
sed -i 's#^ELASTIC_HOST = \x27127.0.0.1\x27#ELASTIC_HOST = \x27'$ELASTIC_ADDRESS'\x27#' timesketch/etc/timesketch/timesketch.conf
sed -i 's#^ELASTIC_PORT = 9200#ELASTIC_PORT = '$ELASTIC_PORT'#' timesketch/etc/timesketch/timesketch.conf
# Set up the Redis connection
sed -i 's#^UPLOAD_ENABLED = False#UPLOAD_ENABLED = True#' timesketch/etc/timesketch/timesketch.conf
sed -i 's#^UPLOAD_FOLDER = \x27/tmp\x27#UPLOAD_FOLDER = \x27/usr/share/timesketch/upload\x27#' timesketch/etc/timesketch/timesketch.conf
sed -i 's#^CELERY_BROKER_URL =.*#CELERY_BROKER_URL = \x27redis://'$REDIS_ADDRESS':'$REDIS_PORT'\x27#' timesketch/etc/timesketch/timesketch.conf
sed -i 's#^CELERY_RESULT_BACKEND =.*#CELERY_RESULT_BACKEND = \x27redis://'$REDIS_ADDRESS':'$REDIS_PORT'\x27#' timesketch/etc/timesketch/timesketch.conf
# Set up the Postgres connection
sed -i 's#postgresql://<USERNAME>:<PASSWORD>@localhost#postgresql://'$POSTGRES_USER':'$POSTGRES_PASSWORD'@'$POSTGRES_ADDRESS':'$POSTGRES_PORT'#' timesketch/etc/timesketch/timesketch.conf
sed -i 's#^POSTGRES_PASSWORD=#POSTGRES_PASSWORD='$POSTGRES_PASSWORD'#' timesketch/config.env
sed -i 's#^ELASTIC_MEM_USE_GB=#ELASTIC_MEM_USE_GB='$ELASTIC_MEM_USE_GB'#' timesketch/config.env
ln -s ./config.env ./timesketch/.env
echo "OK"
echo "* Installation done."
echo
echo "Start the system:"
echo "1. cd timesketch"
echo "2. docker-compose up -d"
echo "3. docker-compose exec timesketch-web tsctl add_user --username <USERNAME>"
echo
echo "WARNING: The server is running without encryption."
echo "Follow the instructions to enable SSL to secure the communications:"
echo "https://github.com/google/timesketch/blob/master/docs/Installation.md"
echo
echo