php umsetzung anfang

This commit is contained in:
xoy 2023-02-26 13:43:36 +01:00
parent 6fa1b541f6
commit 64242ef723
48 changed files with 31 additions and 817 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -1,7 +0,0 @@
# Readme
```git clone https://git.ctdo.de/xoy/ctdo.de.git```
```cd ./ctdo.de/```
```go run .```

View File

@ -47,7 +47,9 @@
</p>
</main>
<footer>
!FOOTERNAV
<nav>
</nav>
</footer>
</body>
</html>

View File

@ -1,5 +0,0 @@
username: admin
password: password
address: localhost
port: 3306
database: ctdo

View File

@ -1 +0,0 @@
address: :80

61
ctdo.go
View File

@ -1,61 +0,0 @@
package main
import (
"strconv"
"strings"
"time"
)
// jeden ersten donnerstag und dritten dienstag
func getNextTopic() topic {
date := time.Now()
var output topic
for i := 0; i < 31; i++ {
newDate := stringSplit(date.AddDate(0, 0, 1*i).Format(time.UnixDate), " ")
if newDate[0] == "Thu" || newDate[0] == "Tue" {
dayA, errA := strconv.Atoi(newDate[2])
errorPanic(errA)
dayB, errB := strconv.Atoi(newDate[2])
errorPanic(errB)
if ifFloatRange(float64(dayA)/7, 0, 1, false, true) || (ifFloatRange(float64(dayB)/7, 2, 3, false, true) && newDate[0] == "Tue") {
output.date = date.AddDate(0, 0, 1*i).Format("02.01.2006")
output.days = i
break
}
}
}
return output
}
func getRoomState() status {
var err error
body := httpGetBody("https://status.ctdo.de/api/simple/v2")
bodyString := string(body)
temp := []string{}
bodyString = strings.ReplaceAll(bodyString, "{", "")
bodyString = strings.ReplaceAll(bodyString, "}", "")
Temp := strings.Split(bodyString, ",")
for _, element := range Temp {
TEmp := strings.Split(element, ":")
temp = append(temp, TEmp[1])
}
roomState := new(status)
roomState.state = temp[0] == "true"
roomState.power, err = strconv.ParseInt(temp[2], 0, 64)
errorPanic(err)
return *roomState
}

View File

@ -1,13 +0,0 @@
create database ctdo;
use ctdo;
create table events (
id int not null auto_increment,
title varchar(80) not null,
description varchar(500) not null,
media varchar(10000),
date varchar(10) not null,
primary key(id)
);
create table adminKeys (
adminKey varchar(16) not null
);

View File

@ -1,39 +0,0 @@
package main
import (
"database/sql"
"strings"
_ "github.com/go-sql-driver/mysql"
)
func dbConnect(username string, password string, address string, port string, database string) *sql.DB {
db, err := sql.Open("mysql", username+":"+password+"@tcp("+address+":"+port+")/"+database)
errorPanic(err)
return db
}
func dbClose(database *sql.DB) {
database.Close()
}
func dbQuerry(database *sql.DB, sqlCode string) *sql.Rows {
results, err := database.Query(sqlCode)
errorPanic(err)
return results
}
func ctdoConnect() *sql.DB {
dbValues := readDatabaseYML()
return dbConnect(dbValues.username, dbValues.password, dbValues.address, dbValues.port, dbValues.database)
}
func sqlClean(sqlString string) string {
sqlString = strings.ReplaceAll(sqlString, "'", "")
sqlString = strings.ReplaceAll(sqlString, "\"", "")
return sqlString
}

11
elements/nav.html Normal file
View File

@ -0,0 +1,11 @@
<nav>
<ul>
<li> <a href="index.php">home</a> </li>
<li> <a href="about.php">über uns</a> </li>
<li> <a href="treff.php">treff</a> </li>
<li> <a href="events.php">events</a> </li>
<li> <a href="kontakt.php">kontakt</a> </li>
<li> <a href="support.php">support</a> </li>
<li> <a href="verein.php">verein</a> </li>
</ul>
</nav>

View File

@ -1,75 +0,0 @@
package main
func getEvents() []event {
db := ctdoConnect()
defer dbClose(db)
rows := dbQuerry(db, "SELECT * FROM events;")
events := []event{}
for rows.Next() {
Event := new(event)
err := rows.Scan(&Event.id, &Event.title, &Event.description, &Event.media, &Event.date)
if err != nil {
panic(err.Error())
}
events = append(events, *Event)
}
return events
}
func getEventCount() int {
db := ctdoConnect()
defer dbClose(db)
row := dbQuerry(db, "SELECT COUNT(*) FROM events;")
count := 0
for row.Next() {
row.Scan(&count)
}
return count
}
func addEvent(Event event) bool {
db := ctdoConnect()
defer dbClose(db)
if len(Event.title) > 80 || len(Event.description) > 500 || len(Event.media) == 10000 || len(Event.date) > 10 {
return false
}
sqlString := "insert into events (title, description, media, date) values ('" + sqlClean(Event.title) + "', '" + sqlClean(Event.description) + "', '" + sqlClean(Event.media) + "', '" + sqlClean(Event.date) + "');"
dbQuerry(db, sqlString)
return true
}
func getAdminKeys() []string {
db := ctdoConnect()
defer dbClose(db)
rows := dbQuerry(db, "select * from adminKeys;")
output := []string{}
for rows.Next() {
temp := ""
err := rows.Scan(&temp)
if err != nil {
panic(err.Error())
}
output = append(output, temp)
}
if len(output) == 0 {
return nil
}
return output
}

48
file.go
View File

@ -1,48 +0,0 @@
package main
import (
"errors"
"io/ioutil"
"os"
)
func fileRead(src string) string {
content, err := ioutil.ReadFile(src)
errorPanic(err)
return string(content)
}
func fileAddLine(input string, filepath string) {
_, err := os.Stat(filepath)
if errors.Is(err, os.ErrNotExist) {
fileCreate(filepath)
}
var file *os.File
file, err = os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
errorPanic(err)
_, err = file.WriteString(input + "\n")
errorPanic(err)
}
func fileCreate(filepath string) {
_, err := os.Stat(filepath)
if errors.Is(err, os.ErrNotExist) {
_, err := os.Create(filepath)
errorPanic(err)
logger("fileCreate : file created -> " + filepath)
}
}
func fileMkDir(folderpath string) {
_, err := os.Stat(folderpath)
if errors.Is(err, os.ErrNotExist) {
err = os.Mkdir(folderpath, 0755)
errorPanic(err)
logger("fileMkDir : folder created -> " + folderpath)
}
}

42
func.go
View File

@ -1,42 +0,0 @@
package main
import (
"strings"
)
func ifFloatRange(variable float64, min float64, max float64, includeMin bool, includeMax bool) bool {
a, b := false, false
if includeMin {
a = variable >= min
} else {
a = variable > min
}
if includeMax {
b = variable <= max
} else {
b = variable < max
}
return a && b
}
func stringSplit(input string, sep string) []string {
output := *new([]string)
for _, element := range strings.Split(input, sep) {
if element != "" {
output = append(output, element)
}
}
return output
}
func stringListContains(list []string, searched string) bool {
for _, item := range list {
if item == searched {
return true
}
}
return false
}

5
go.mod
View File

@ -1,5 +0,0 @@
module xoy.dev/ctdo
go 1.19
require github.com/go-sql-driver/mysql v1.7.0 // indirect

2
go.sum
View File

@ -1,2 +0,0 @@
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=

106
html.go
View File

@ -1,106 +0,0 @@
package main
import (
"strconv"
"strings"
)
func htmlElement(tag string, innerHTML string, args string) string {
return "<" + tag + " " + args + ">" + innerHTML + "</" + tag + ">"
}
func htmlLinkElement(innerHTML string, destination string, blank bool, args string) string {
b := ""
if blank {
b = "target=\"_blank\" "
}
return htmlElement("a", innerHTML, " href=\""+destination+"\" "+b+args)
}
func htmlInputElement(name string, _type string, value string, args string) string {
return "<input name=\"" + name + "\" type=\"" + _type + "\" value=\"" + value + "\" " + args + ">"
}
func htmlNav(pages [][]string, activePage string) string {
output := ""
for _, page := range pages {
if page[1] == "/"+activePage || (page[1] == "/home" && activePage == "") {
output += htmlElement("li", htmlLinkElement(page[0], page[1], false, "class=\"active\""), "")
} else {
output += htmlElement("li", htmlLinkElement(page[0], page[1], false, ""), "")
}
}
return htmlElement("nav", htmlElement("ul", output, ""), "")
}
func htmlNewBanner(text string, link string) string {
output := ""
output += htmlElement("div", htmlLinkElement(text, link, true, ""), "class=\"newBanner\"")
return output
}
func htmlReplacer(input string, activePage string) string {
output := strings.ReplaceAll(input, "!NAV", htmlNav(getPages(), activePage))
if getRoomState().state {
output = strings.ReplaceAll(output, "!RAUMSTATUS", "<p>Raumstatus: <b class=\"green-text\">offen</b></p>")
} else {
output = strings.ReplaceAll(output, "!RAUMSTATUS", "<p>Raumstatus: <b class=\"red-text\">geschlossen</b></p>")
}
output = strings.ReplaceAll(output, "!FOOTERNAV", htmlNav(getFooterPages(), activePage))
if getNextTopic().days == 0 {
output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet Heute statt!", ""))
} else if getNextTopic().days == 1 {
output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet Morgen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\""))
} else if getNextTopic().days < 10 {
output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet in "+strconv.FormatInt(int64(getNextTopic().days), 10)+" Tagen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\""))
} else {
output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet in "+string(getNextTopic().days)+" Tagen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\""))
}
events := getEvents()
if len(events) == 0 {
output = strings.ReplaceAll(output, "!EVENTS", htmlElement("h4", "Keine Events in der nächsten Zeit.", ""))
output = strings.ReplaceAll(output, "!NEXTEVENTS", htmlElement("h4", "Keine Events in der nächsten Zeit.", ""))
} else {
tempA, tempB := "", ""
for i, Event := range events {
if i == 24 {
break
}
tempA = htmlElement("p", htmlClean(Event.date), "class=\"date\"")
tempA += htmlElement("h2", htmlClean(Event.title), "class=\"title\"")
tempA += htmlElement("p", htmlClean(Event.description), "class=\"desc\"")
tempB += htmlLinkElement(htmlElement("div", tempA, "class=\"event\""), "/event/"+strconv.Itoa(Event.id), false, "class=\"event\"")
tempB += "!SPLIT"
}
output = strings.ReplaceAll(output, "!EVENTS", htmlElement("div", strings.ReplaceAll(tempB, "!SPLIT", ""), "class=\"eventList\""))
//tempC := strings.Split(tempB, "!SPLIT")
//output = strings.ReplaceAll(output, "!NEXTEVENTS", htmlElement("div", tempC[0]+tempC[1]+tempC[2]+tempC[3], "class=\"eventList\""))
}
output = strings.ReplaceAll(output, "!NEWBANNER", htmlNewBanner("Rundgang", "https://www.chaostreff-dortmund.de/rundgang/"))
if strings.Contains(activePage, "/addEvent") {
output = strings.ReplaceAll(output, "!ADMINKEY", activePage)
} else {
output = strings.ReplaceAll(output, "!ADMINKEY", activePage+"/addEvent")
}
return output
}
func htmlClean(htmlString string) string {
htmlString = strings.ReplaceAll(htmlString, "<", "[")
htmlString = strings.ReplaceAll(htmlString, ">", "]")
return htmlString
}

110
http.go
View File

@ -1,110 +0,0 @@
package main
import (
"io"
"net/http"
"os"
"strings"
"time"
)
func httpHandleFunc(urlPath string, filepath string, contentType string) {
urlPath = strings.ToLower(urlPath)
logger(readHttpYML() + "/" + urlPath + " <--> " + filepath + " <" + contentType + ">")
http.HandleFunc("/"+urlPath, func(w http.ResponseWriter, r *http.Request) {
logger(r.Method + " request -> " + readHttpYML() + "/" + urlPath + " <" + contentType + ">")
w.Header().Add("Content-Type", contentType)
io.WriteString(w, htmlReplacer(fileRead(filepath), urlPath))
})
}
func httpHandleFuncWithPOST(urlPath string, filepath string, contentType string) {
Event := new(event)
logger(readHttpYML() + "/" + urlPath + " <--> " + filepath + " <" + contentType + ">")
http.HandleFunc("/"+urlPath, func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
logger(r.Method + " request -> " + readHttpYML() + "/" + urlPath + " <" + contentType + ">")
r.ParseMultipartForm(10 << 20)
err := r.ParseMultipartForm(200000)
errorPanic(err)
formdata := r.MultipartForm
files := formdata.File["media"]
if filepath == "./web/pages/admin/dashboard.html" {
logger("----------------ADD EVENT----------------")
title := formdata.Value["title"]
description := formdata.Value["description"]
media := formdata.File["media"]
mediaString := ""
date := formdata.Value["date"]
if title[0] != "" && description[0] != "" && media != nil && date[0] != "" {
logger("title: " + title[0])
logger("descrtiption: " + description[0])
logger("media: " + string(len(media)))
logger("files uploaded successfully: ")
for i, _ := range files {
if len(media) > 0 {
mediaString += ","
}
mediaString += "./web/images/" + files[i].Filename
logger("./web/images/" + files[i].Filename)
}
Event.id = -1
Event.title = title[0]
Event.description = description[0]
Event.media = mediaString
Event.date = date[0]
logger("date: " + date[0])
if addEvent(*Event) {
for i, _ := range files {
file, err := files[i].Open()
errorPanic(err)
out, err := os.Create("./web/images/" + files[i].Filename)
errorPanic(err, "unable to create the file -> '"+"./web/images/"+files[i].Filename+"' : check your write access privilege")
_, err = io.Copy(out, file)
errorPanic(err)
}
logger("event added!")
handleImages()
} else {
logger("event not added!")
}
} else {
logger("no formdata")
}
logger("----------------ADD END----------------")
}
}
w.Header().Add("Content-Type", contentType)
io.WriteString(w, htmlReplacer(fileRead(filepath), urlPath))
})
}
func httpGetBody(url string) []byte {
c := &http.Client{Timeout: 10 * time.Second}
r, err := c.Get(url)
errorPanic(err)
defer r.Body.Close()
var body []byte
body, err = io.ReadAll(r.Body)
errorPanic(err)
return body
}

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -4,17 +4,25 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ctdo - home</title>
<link rel="stylesheet" href="/style/main.css">
<link rel="stylesheet" href="/style/home.css">
<link rel="stylesheet" href="/style/events.css">
<?php require 'php/generator.php'; ?>
</head>
<body>
!NEWBANNER
<div class="newBanner">
Rundgang
</div>
<header>
<img src="/image/logo_ctdo.svg" alt="ctdo logo">
!NAV
<?php print_element("nav"); ?>
</header>
<main>
<div class="rundgang">
<a href="https://www.chaostreff-dortmund.de/rundgang/" target="_blank" class="imgLink">

BIN
kontakt/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -1,21 +0,0 @@
package main
import (
"time"
)
func logger(input string) {
fileMkDir("./log")
println("[" + time.Now().Format("15:04:05") + "] " + input)
fileAddLine("["+time.Now().Format("15:04:05")+"] "+input, "./log/"+time.Now().Format("2006-02-01")+".log")
}
func errorPanic(err error, logBefore ...string) {
if err != nil {
for _, log := range logBefore {
logger(log)
}
logger(err.Error())
panic("\n----------------ERROR----------------\n")
}
}

158
main.go
View File

@ -1,158 +0,0 @@
package main
import (
"io/ioutil"
"net/http"
"strconv"
"strings"
)
/*
Timezone = UTC
*/
func main() {
addr := readHttpYML()
logger("----------------START----------------")
logger("timezone = UTC")
logger("connection open with address " + addr)
handler()
err := http.ListenAndServe(addr, nil)
errorPanic(err)
}
func handler() {
//reihenfolge ist wichtig!
//admin pages
logger("----------------HANDLE ADMIN LOGIN----------------")
keys := getAdminKeys()
if len(keys) > 0 {
for _, key := range keys {
httpHandleFunc("admin/"+key, "./web/pages/admin/dashboard.html", "text/html")
httpHandleFuncWithPOST("admin/"+key+"/addEvent", "./web/pages/admin/dashboard.html", "text/html")
}
}
logger("----------------HANDLE END----------------")
//events
handleEvents()
//images
handleImages()
//styles
logger("----------------HANDLE STYLES----------------")
handleFilesInFolder("style/", "./web/styles/", false)
logger("----------------HANDLE END----------------")
//pages
logger("----------------HANDLE PAGES----------------")
httpHandleFunc("", "./web/pages/home.html", "text/html")
handleFilesInFolder("", "./web/pages/", true)
logger("----------------HANDLE END----------------")
}
func handleEvents() {
if getEventCount() > 0 {
logger("----------------HANDLE EVENTS----------------")
events := getEvents()
for _, e := range events {
httpHandleFunc("event/"+strconv.Itoa(e.id), "./web/pages/event.html", "text/html")
}
logger("----------------HANDLE END----------------")
}
}
func handleImages() {
logger("----------------HANDLE IMAGES----------------")
handleFilesInFolder("image/", "./web/images/", false)
logger("----------------HANDLE END----------------")
}
var alreadyHandledFiles []string = []string{"./web/pages/admin/dashboard.html", "./web/pages/event.html"}
func handleFilesInFolder(urlPrefix string, folderpath string, handleWithoutFileSuffix bool) {
if folderpath[len(folderpath)-1] != '/' {
folderpath += "/"
}
files, err := ioutil.ReadDir(folderpath)
errorPanic(err)
for _, file := range files {
alreadyHandled := stringListContains(alreadyHandledFiles, folderpath+file.Name())
if !alreadyHandled {
if !file.IsDir() {
f := strings.Split(file.Name(), ".")
ContentType := f[len(f)-1]
filename := ""
if handleWithoutFileSuffix {
for index, item := range f {
if index < len(f)-1 {
filename += item
}
}
} else {
filename = file.Name()
}
switch ContentType {
case "png":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/png")
case "webp":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/webp")
case "svg":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/svg+xml")
case "jpeg":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/jpeg")
case "jpg":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/jpeg")
case "gif":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/gif")
case "css":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "text/css")
case "html":
httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "text/html")
default:
logger("handleFilesInFolder -> content-type unknown : " + folderpath + file.Name())
}
alreadyHandledFiles = append(alreadyHandledFiles, folderpath+file.Name())
} else {
childFolder := file.Name()
handleFilesInFolder(childFolder, folderpath+childFolder, handleWithoutFileSuffix)
}
} else {
logger("handleFilesInFolder -> already handled : " + folderpath + file.Name())
}
}
}
func getPages() [][]string {
output := [][]string{}
output = append(output, []string{"home", "/home"})
output = append(output, []string{"zeiten & location", "/treff"})
output = append(output, []string{"events", "/events"})
output = append(output, []string{"über uns", "/about"})
output = append(output, []string{"kontakt", "/kontakt"})
output = append(output, []string{"verein", "/verein"})
output = append(output, []string{"unterstützung", "/support"})
return output
}
func getFooterPages() [][]string {
output := [][]string{}
output = append(output, []string{"impressum", "/impressum"})
output = append(output, []string{"datenschutz", "/datenschutz"})
return output
}

7
php/generator.php Normal file
View File

@ -0,0 +1,7 @@
<?php
function print_element($element_name) {
print(file_get_contents("/elements/$element_name.html"));
}
?>

View File

@ -1,28 +0,0 @@
package main
type status struct {
state bool
lastchange int64
power int64
}
type event struct {
id int
title string
description string
media string
date string
}
type topic struct {
date string
days int
}
type database struct {
username string
password string
address string
port string
database string
}

View File

@ -1,5 +0,0 @@
package main
func testFuncOutput(functionOutput any, rightOutput any) bool {
return functionOutput == rightOutput
}

View File

@ -1,33 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ctdo - admin</title>
<link rel="stylesheet" href="/style/main.css">
<link rel="stylesheet" href="/style/dashboard.css">
<link rel="stylesheet" href="/style/events.css">
</head>
<body>
<header>
<img src="/image/logo_ctdo.svg" alt="ctdo logo">
!NAV
</header>
<main>
!RAUMSTATUS
!EVENTS
<form action="/!ADMINKEY" method="post" enctype="multipart/form-data">
<input type="text" name="title" placeholder="Titel"><br>
<input type="text" name="description" placeholder="Beschreibung"><br>
<label for="media">Bilder:</label><input type="file" name="media" id="media" multiple><br>
<label for="date">Datum:</label><input type="date" name="date" id="date"><br>
<input type="submit" value="Event Erstellen">
</form>
</main>
<footer>
!FOOTERNAV
</footer>
</body>
</html>

55
yml.go
View File

@ -1,55 +0,0 @@
package main
import "strings"
func readDatabaseYML() database {
file := fileRead("./config/database.yml")
rows := [][]string{}
for _, row := range strings.Split(file, "\n") {
rows = append(rows, strings.Split(row, ": "))
}
output := new(database)
for i, row := range rows {
switch i {
case 0:
output.username = row[1]
case 1:
output.password = row[1]
case 2:
output.address = row[1]
case 3:
output.port = row[1]
case 4:
output.database = row[1]
default:
logger("func.go:259 -> switch-case is out of range")
}
}
return *output
}
func readHttpYML() string {
file := fileRead("./config/http.yml")
rows := [][]string{}
for _, row := range strings.Split(file, "\n") {
rows = append(rows, strings.Split(row, ": "))
}
for i, row := range rows {
switch i {
case 0:
return row[1]
default:
logger("func.go:280 -> switch-case is out of range")
}
}
return ""
}