// Package main defines the entry point of the Go application. package main // Importing necessary packages for database interaction, web server functionality, logging, and more. import ( "database/sql" "fmt" "html/template" "io" "log/slog" "net/http" "os" "strings" "time" _ "modernc.org/sqlite" // Importing SQLite driver for database interaction. ) var c chan bool // readHtml function reads an HTML file and applies a CSS template to it before sending it to the client. func readHtml(res http.ResponseWriter, _ *http.Request) { g := template.CSS("./html/public/mod.css") // Define the CSS path. f, err := template.ParseFiles("./html/wsb.html") // Parse the HTML file. if err != nil { slog.Error(err.Error()) // Log any errors encountered. } err = f.Execute(res, g) // Execute the template with the CSS and send it to the client. if err != nil { slog.Error(err.Error()) // Log any errors encountered. } } // simpRequestResp sends a simple response to the client. func simpRequestResp(res http.ResponseWriter, _ *http.Request) { fmt.Fprint(res, "Hello, M'Lord", 153*4, " I'm here to serveè") // Print a formatted string to the client. } // getMsgFromDB retrieves a message from the database based on the provided ID and language. func getMsgFromDB(sqldb *sql.DB, id string, lang string) string { var lngs []string lngs = append(lngs, lang) // Append the language to the slice. query := generateSQL("msgs", lngs, [2]string{"content", id}) // Generate the SQL query. res := sqldb.QueryRow(query) // Execute the query. lng := "" dt := res.Scan(&lng) // Scan the result into the lng variable. if dt != nil { return "" // Return an empty string if there's an error. } return lng // Return the retrieved message. } // queryPacks retrieves a list of packages from the database. func queryPacks(sqldb *sql.DB, element *elements) []packages { pkg_list := getPkgIdFromDB(sqldb) // Get the list of package IDs from the database. pkgs := make([]packages, 0) // Initialize a slice to hold the packages. for _, p := range pkg_list { query := generateSQL("packs_all", []string{"*"}, [2]string{"id", p}) // Generate the SQL query for each package. res, err := sqldb.Query(query) // Execute the query. defer res.Close() // Ensure the result set is closed after the function returns. err = res.Err() // Check for any errors during query execution. if err != nil { slog.Error(err.Error()) // Log and panic on any errors. } for res.Next() { npkg := packages{} // Create a new package instance. err := res.Scan(&npkg.Id, &npkg.Name, &npkg.Version, &npkg.ExtraCommand, &npkg.Tag, &npkg.Warning) // Scan the result into the package instance. if err != nil { slog.Error(err.Error()) // Log and exit on any errors. } npkg.Element = element // Associate the element with the package. pkgs = append(pkgs, npkg) // Append the package to the slice. } } return pkgs // Return the slice of packages. } // queryDatabase executes a SQL query expecting a single row and returns the result as a slice of strings. // sqldb: The database connection object. // queryRow: The SQL query string to be executed. // Returns: A slice of strings representing the query result. func queryDatabase(sqldb *sql.DB, queryRow string) []string { res := sqldb.QueryRow(queryRow) var values []string err := res.Scan(&values) if err != nil { slog.Error(err.Error()) } return values } // generateSQL constructs a SQL SELECT statement with optional WHERE clauses. // table: The name of the database table. // columns: A slice of strings representing the column names to be selected. // arg: A variadic slice of string pairs representing WHERE clause conditions. // Returns: A string representing the complete SQL SELECT statement. func generateSQL(table string, columns []string, arg ...[2]string) string { cols := strings.Join(columns, ",") table = "SELECT " + cols + " FROM " + table if len(arg) > 0 { table += " WHERE " for i, a := range arg { table += a[0] + " like '" + a[1] + "'" if i+1 < len(arg) { table += " and " } } } return table } // searchDownloads performs a database query to retrieve download statistics. // sqldb: The database connection object. // table: The name of the database table. // columns: A variadic number of strings representing the column names to be selected. // Returns: A slice of DownloadElements structs containing the query results. func searchDownloads(sqldb *sql.DB, table string, columns ...string) []DownloadElements { query := generateSQL(table, columns) runquery, err := sqldb.Query(query) defer runquery.Close() err = runquery.Err() if err != nil { slog.Error(err.Error()) } var elems []DownloadElements var e DownloadElements for runquery.Next() { if len(columns) > 2 { err = runquery.Scan(&e.ID, &e.Version, &e.Counter) } else { err = runquery.Scan(&e.ID, &e.Counter) } elems = append(elems, e) } return elems } // stats creates an HTTP handler that serves a statistics page with data from the database. // sqldb: The database connection object. // lang: The language code to localize the content. // Returns: An http.Handler that serves the statistics page. func stats(sqldb *sql.DB, lang string) http.Handler { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { Counter := struct{ ElementsData elements VersionStats []DownloadElements TotalStats []DownloadElements BodyClass string Lang string }{ ElementsData: elements{ Title: getMsgFromDB(sqldb, "title", lang), Header: getMsgFromDB(sqldb, "header", lang), Help: getMsgFromDB(sqldb, "help", lang), Packagename: getMsgFromDB(sqldb, "packagename", lang), Packageversion: getMsgFromDB(sqldb, "packageversion", lang), Allow: getMsgFromDB(sqldb, "allow", lang), Warning: getMsgFromDB(sqldb, "warning", lang), Explain: getMsgFromDB(sqldb, "explain", lang), }, BodyClass: "m", VersionStats: searchDownloads(sqldb, "counterd", "program", "version","download_count"), TotalStats: searchDownloads(sqldb, "count_all", "program","download_count"), Lang: lang, } templates, err := template.ParseFiles("html/master.html", "html/statsitics.html") if err != nil { slog.Error(err.Error()) } err = templates.ExecuteTemplate(res, "master", Counter) if err != nil { slog.Error(err.Error()) } res.WriteHeader(http.StatusOK) }) } // getPkgIdFromDB retrieves a list of package IDs from the database. // sqldb: The database connection object. // Returns: A slice of strings containing package IDs. func getPkgIdFromDB(sqldb *sql.DB) []string { query, err := sqldb.Query("SELECT id FROM packs_all") defer query.Close() err = query.Err() if err != nil { slog.Error(err.Error()) } var pkgs []string var tmpstr string for query.Next() { err = query.Scan(&tmpstr) if err != nil { slog.Error(err.Error()) } pkgs = append(pkgs, tmpstr) } // query.Scan(&pkgs) if err != nil { slog.Error(err.Error()) } return pkgs } // fullSearchPackagesDB performs a full search of packages in the database. // sqldb: The database connection object. // Returns: A slice of packages structs containing the full package details. func fullSearchPackagesDB(sqldb *sql.DB) []packages { pkg_list := getPkgIdFromDB(sqldb) var pkgs []packages for _, p := range pkg_list { query := generateSQL("packs_all", []string{"*"}, [2]string{"id", p}) res := queryDatabase(sqldb, query) var pkg packages pkg, _ = ConvertStringsToPackage(res) pkgs = append(pkgs, pkg) } return pkgs } func uploadFileForServer(sqldb *sql.DB, lang string) http.Handler{ return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { pageDataFromDatabase := elements{ Title: getMsgFromDB(sqldb, "title", lang), Header: getMsgFromDB(sqldb, "header", lang), Help: getMsgFromDB(sqldb, "help", lang), Packagename: getMsgFromDB(sqldb, "packagename", lang), Packageversion: getMsgFromDB(sqldb, "packageversion", lang), Allow: getMsgFromDB(sqldb, "allow", lang), Warning: getMsgFromDB(sqldb, "warning", lang), Explain: getMsgFromDB(sqldb, "explain", lang), } data := struct { BodyClass string ElementsData elements Lang string }{ ElementsData: pageDataFromDatabase, BodyClass: "", Lang: lang, } templates, err := template.ParseFiles("html/master.html", "html/uploadfile.html") if err != nil { slog.Error(err.Error()) } err = templates.ExecuteTemplate(res, "master", data) if err != nil { slog.Error(err.Error()) } // upload(res, req) res.WriteHeader(http.StatusOK) }) } func upload() http.Handler { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request){ file, header, _ := req.FormFile("myFile") req.ParseMultipartForm(10000000<<20) defer file.Close() filename := header.Filename tempFile, _ :=os.CreateTemp("Data",header.Filename) defer tempFile.Close() fileBytes,_:=io.ReadAll(file) tempFile.Write(fileBytes) fn,_:=os.OpenFile("Data/"+filename, os.O_WRONLY|os.O_CREATE, 0666) defer fn.Close() fn.Write(fileBytes) slog.Info(fmt.Sprint(getDataFromFile("Data/"+filename))) })} // index creates an HTTP handler that serves the main page with data from the database. // sqldb: The database connection object. // lang: The language code to localize the content. // Returns: An http.Handler that serves the main page. func index(sqldb *sql.DB, lang string) http.Handler { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { pageDataFromDatabase := elements{ Title: getMsgFromDB(sqldb, "title", lang), Header: getMsgFromDB(sqldb, "header", lang), Help: getMsgFromDB(sqldb, "help", lang), Packagename: getMsgFromDB(sqldb, "packagename", lang), Packageversion: getMsgFromDB(sqldb, "packageversion", lang), Allow: getMsgFromDB(sqldb, "allow", lang), Warning: getMsgFromDB(sqldb, "warning", lang), Explain: getMsgFromDB(sqldb, "explain", lang), } data := struct { BodyClass string ElementsData elements PackagesData []packages Lang string }{ ElementsData: pageDataFromDatabase, BodyClass: "", PackagesData: queryPacks(sqldb, &pageDataFromDatabase), Lang: lang, } templates, err := template.ParseFiles("html/master.html", "html/main.html") if err != nil { slog.Error(err.Error()) } err = templates.ExecuteTemplate(res, "master", data) if err != nil { slog.Error(err.Error()) } res.WriteHeader(http.StatusOK) }) } // public serves static files from the "public" directory. // Returns: An http.Handler that serves static files. func public() http.Handler { return http.StripPrefix("/public/", http.FileServer(http.Dir("./public"))) } // main initializes the application, sets up logging, database connection, HTTP routing, and starts the server. func main() { // Check if the directory exists if _, err := os.Stat("Logs/"); os.IsNotExist(err) { // Create your directory if it does not exist err = os.Mkdir("Logs/", 0755) if err != nil { fmt.Println(err) } } handlerOpts := &slog.HandlerOptions{ Level: slog.LevelDebug, } logfilename := "Logs/" + time.Now().Format("2006-01-02--15-04-05") + ".log" file, err := os.OpenFile(logfilename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777) defer file.Close() log:=slog.New(slog.NewTextHandler(file,handlerOpts )) slog.SetDefault(log) if err != nil { panic(err) } // Write a log entry slog.Info("This is a test log entry") db, _ := sql.Open("sqlite", "file:progs.db") mux := http.NewServeMux() mux.Handle("/public/", public()) mux.Handle("/", index(db, "heb")) mux.Handle("/en", index(db, "eng")) mux.Handle("/stats", stats(db,"eng")) mux.Handle("/up", uploadFileForServer(db,"eng")) mux.Handle("/upload",upload()) mux.Handle("/pkg",getJson(db)) addr := fmt.Sprintf(":%s", "12312") server := http.Server{ Addr: addr, Handler: mux, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 15 * time.Second, } if err := server.ListenAndServe(); err != nil { log.Error("main: couldn't start simple server: %v\n", err) } lang := "heb" log.Info(getMsgFromDB(db, "title", lang)) }