webserver up and running for http/https, logger timestamp format change
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -6,7 +6,6 @@
|
|||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
servtex
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
@@ -14,3 +13,8 @@ servtex
|
|||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
|
# Custom Additions
|
||||||
|
servtex
|
||||||
|
servtex.log
|
||||||
|
output
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"git.noctra.dev/noctra/servtex/globals"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.noctra.dev/noctra/servtex/globals"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Returns the current time in the timezone specified in the config file
|
// Returns the current time in the timezone specified in the config file
|
||||||
@@ -21,13 +23,19 @@ func GetLocalTimeRFC() string {
|
|||||||
return GetLocalTime().Format(time.RFC3339)
|
return GetLocalTime().Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetLocalTimeLog() string {
|
||||||
|
return GetLocalTime().Format("2006/01/02 15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the current localtime in custom pretty print format
|
// Returns the current localtime in custom pretty print format
|
||||||
func GetLocalTimePretty() string {
|
func GetLocalTimePretty() string {
|
||||||
return GetLocalTime().Format("02.01.2006 15:04")
|
return GetLocalTime().Format("02.01.2006 15:04")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes to log and prints to screen
|
||||||
func LogLine(message string) {
|
func LogLine(message string) {
|
||||||
logline := "\n" + GetLocalTimeRFC() + " - " + message
|
logline := GetLocalTimeLog() + " ServTeX: " + message + "\n"
|
||||||
|
fmt.Print(logline)
|
||||||
globals.LogFile.WriteString(logline)
|
globals.LogFile.WriteString(logline)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,8 +45,7 @@ func LogLine(message string) {
|
|||||||
func configReaderParse(filePath string, configOptionStorage *globals.Config) error {
|
func configReaderParse(filePath string, configOptionStorage *globals.Config) error {
|
||||||
jsonData, err := os.ReadFile(filePath)
|
jsonData, err := os.ReadFile(filePath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = json.Unmarshal(jsonData, &configOptionStorage)
|
if err = json.Unmarshal(jsonData, &configOptionStorage); err != nil {
|
||||||
if err != nil {
|
|
||||||
return errors.New("Config file could not be read")
|
return errors.New("Config file could not be read")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -89,10 +96,13 @@ func ChangeWatch(path string, callOnChange func()) {
|
|||||||
|
|
||||||
// Intended to be run as goroutine
|
// Intended to be run as goroutine
|
||||||
func LatexCompile(config globals.Config, execution *globals.LatexExecution) error {
|
func LatexCompile(config globals.Config, execution *globals.LatexExecution) error {
|
||||||
if !execution.ExecutionLock.TryLock() {
|
if execution.ExecutionLock.TryLock() {
|
||||||
|
defer execution.ExecutionLock.Unlock()
|
||||||
|
} else {
|
||||||
LogLine("LaTeX execution already underway")
|
LogLine("LaTeX execution already underway")
|
||||||
return errors.New("Execution already in progress")
|
return errors.New("Execution already in progress")
|
||||||
}
|
}
|
||||||
|
|
||||||
LogLine("LaTeX execution started")
|
LogLine("LaTeX execution started")
|
||||||
execution.ExecutionState = "Started"
|
execution.ExecutionState = "Started"
|
||||||
|
|
||||||
@@ -109,7 +119,6 @@ func LatexCompile(config globals.Config, execution *globals.LatexExecution) erro
|
|||||||
execution.ExecutionState = "Unknown Latex Engine"
|
execution.ExecutionState = "Unknown Latex Engine"
|
||||||
execution.Output = []byte{}
|
execution.Output = []byte{}
|
||||||
execution.Timestamp = GetLocalTimePretty()
|
execution.Timestamp = GetLocalTimePretty()
|
||||||
execution.ExecutionLock.Unlock()
|
|
||||||
return errors.New("Unknown Latex Engine")
|
return errors.New("Unknown Latex Engine")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +132,6 @@ func LatexCompile(config globals.Config, execution *globals.LatexExecution) erro
|
|||||||
execution.Output = stdout
|
execution.Output = stdout
|
||||||
execution.Timestamp = GetLocalTimePretty()
|
execution.Timestamp = GetLocalTimePretty()
|
||||||
execution.ExecutionState = "Done"
|
execution.ExecutionState = "Done"
|
||||||
execution.ExecutionLock.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
config.json
10
config.json
@@ -6,9 +6,11 @@
|
|||||||
"latexSourceFilePath": "",
|
"latexSourceFilePath": "",
|
||||||
"latexOutputPath": "./output",
|
"latexOutputPath": "./output",
|
||||||
|
|
||||||
"webserverDomain": "localhost:9876",
|
"webserverDomain": "localhost",
|
||||||
"webserverSecure": false,
|
"webserverPort": "8080",
|
||||||
"certificatePath": "",
|
"webserverSecure": true,
|
||||||
"certificateKeyPath": "",
|
"webserverPortSecure": "8443",
|
||||||
|
"certificatePath": "./testing.crt",
|
||||||
|
"certificateKeyPath": "./testing.key",
|
||||||
"timezone": "Europe/Berlin"
|
"timezone": "Europe/Berlin"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
{{ define "body" }}
|
|
||||||
<body>
|
|
||||||
<div class="container-fluid h-100 d-flex flex-column">
|
|
||||||
<div class="row output flex-grow-1">
|
|
||||||
<div class="col-3 left-sidebar" hx-sse="connect:/sse on:status" hx-swap="innerHTML">
|
|
||||||
Status <br>
|
|
||||||
Last Compilation <br>
|
|
||||||
Such Info <br>
|
|
||||||
Much wow
|
|
||||||
</div>
|
|
||||||
<div class="col-9 p-0">
|
|
||||||
<iframe class="pdf-frame" src="servetex.pdf?ts=0" hx-sse="connect:/sse on:pdf" hx-swap="outerHTML"></iframe>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="command-out" hx-sse="connect:/sse on:output" hx-swap="innerHTML">
|
|
||||||
compile start
|
|
||||||
compile file-x
|
|
||||||
compile file-y
|
|
||||||
example output
|
|
||||||
warning but who cares
|
|
||||||
finished compilation
|
|
||||||
output file created
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
{{ end }}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{{ define "head" }}
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>ServTeX</title>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="/jscss/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="/jscss/custom-view.css">
|
|
||||||
<script src="/jscss/htmx.min.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
@@ -1 +1,41 @@
|
|||||||
{{ template "header" . }}
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>ServTeX</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="/jscss/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="/jscss/custom-view.css">
|
||||||
|
<script src="/jscss/htmx.min.js"></script>
|
||||||
|
<script src="/jscss/htmx-ext-sse.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container-fluid h-100 d-flex flex-column">
|
||||||
|
<div class="row output flex-grow-1">
|
||||||
|
<div class="col-3 left-sidebar" hx-sse="connect:/sse on:status" hx-swap="innerHTML">
|
||||||
|
Status <br>
|
||||||
|
Last Compilation <br>
|
||||||
|
Such Info <br>
|
||||||
|
Much wow
|
||||||
|
</div>
|
||||||
|
<div class="col-9 p-0">
|
||||||
|
<iframe class="pdf-frame" src="/pdf?ts=0" hx-sse="connect:/sse on:pdf" hx-swap="outerHTML"></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="command-out" hx-sse="connect:/sse on:output" hx-swap="innerHTML">
|
||||||
|
compile start<br>
|
||||||
|
compile file-x<br>
|
||||||
|
compile file-y<br>
|
||||||
|
example output<br>
|
||||||
|
warning but who cares<br>
|
||||||
|
finished compilation<br>
|
||||||
|
output file created<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<iframe class="pdf-frame" src="servetex.pdf?ts={{ .timestamp }}" hx-sse="connect:/sse/pdf" hx-swap="outerHTML"></iframe>
|
|
||||||
@@ -3,6 +3,7 @@ package frontend
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
"embed"
|
||||||
"strings"
|
"strings"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -10,6 +11,13 @@ import (
|
|||||||
"git.noctra.dev/noctra/servtex/globals"
|
"git.noctra.dev/noctra/servtex/globals"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed jscss/bootstrap.min.css
|
||||||
|
//go:embed jscss/custom-view.css
|
||||||
|
//go:embed jscss/htmx.min.js
|
||||||
|
//go:embed jscss/htmx-ext-sse.js
|
||||||
|
//go:embed templates/main.html
|
||||||
|
var WebFiles embed.FS
|
||||||
|
|
||||||
// Adds necessary Headers for SSE
|
// Adds necessary Headers for SSE
|
||||||
func sseHeadersAdd(writer *http.ResponseWriter) {
|
func sseHeadersAdd(writer *http.ResponseWriter) {
|
||||||
(*writer).Header().Set("Content-Type", "text/event-stream")
|
(*writer).Header().Set("Content-Type", "text/event-stream")
|
||||||
@@ -74,7 +82,7 @@ func sseOutputSend(writer *http.ResponseWriter) {
|
|||||||
// Server Side Event Handler
|
// Server Side Event Handler
|
||||||
//
|
//
|
||||||
// Sends a Ping instead of actual data when no new data available to save bandwidth
|
// Sends a Ping instead of actual data when no new data available to save bandwidth
|
||||||
func SSEEventSender(writer http.ResponseWriter, request *http.Request) {
|
func SSEventHandler(writer http.ResponseWriter, request *http.Request) {
|
||||||
lastExecution := ""
|
lastExecution := ""
|
||||||
for range time.Tick(time.Second) {
|
for range time.Tick(time.Second) {
|
||||||
if lastExecution == globals.LatexExec.Timestamp {
|
if lastExecution == globals.LatexExec.Timestamp {
|
||||||
@@ -89,3 +97,15 @@ func SSEEventSender(writer http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func PDFHandler(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
http.NotFound(writer, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serves the main page of ServTeX
|
||||||
|
func MainHandler(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
writer.Header().Set("Content-Type", "text/html")
|
||||||
|
main, _ := WebFiles.ReadFile("templates/main.html")
|
||||||
|
writer.Write(main)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ type Config struct {
|
|||||||
|
|
||||||
// webserver
|
// webserver
|
||||||
WebserverDomain string `json:"webserverDomain"`
|
WebserverDomain string `json:"webserverDomain"`
|
||||||
|
WebserverPort string `json:"webserverPort"`
|
||||||
WebserverSecure bool `json:"webserverSecure"`
|
WebserverSecure bool `json:"webserverSecure"`
|
||||||
|
WebserverPortSecure string `json:"webserverPortSecure"`
|
||||||
CertificatePath string `json:"certificatePath"`
|
CertificatePath string `json:"certificatePath"`
|
||||||
CertificateKeyPath string `json:"certificateKeyPath"`
|
CertificateKeyPath string `json:"certificateKeyPath"`
|
||||||
Timezone string `json:"timezone"`
|
Timezone string `json:"timezone"`
|
||||||
@@ -35,3 +37,4 @@ var LatexExec LatexExecution
|
|||||||
|
|
||||||
var LogFile *os.File
|
var LogFile *os.File
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
54
main.go
54
main.go
@@ -2,20 +2,66 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"git.noctra.dev/noctra/servtex/globals"
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"io/fs"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"net/http"
|
||||||
"git.noctra.dev/noctra/servtex/backend"
|
"git.noctra.dev/noctra/servtex/backend"
|
||||||
//"net/http"
|
"git.noctra.dev/noctra/servtex/frontend"
|
||||||
|
"git.noctra.dev/noctra/servtex/globals"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// Exit Codes:
|
// Exit Codes:
|
||||||
// 0 - ok
|
// 0 - ok
|
||||||
// 1 - config file could not be read
|
// 1 - config file could not be read
|
||||||
|
// 2 - log file could not be accessed
|
||||||
func main() {
|
func main() {
|
||||||
|
// application init
|
||||||
err := backend.ConfigReader("config.json", &globals.AppConfig)
|
err := backend.ConfigReader("config.json", &globals.AppConfig)
|
||||||
if err != nil { os.Exit(1) }
|
if err != nil { os.Exit(1) }
|
||||||
|
|
||||||
globals.LogFile, err = os.Open(globals.AppConfig.LogFilePath)
|
globals.LogFile, err = os.OpenFile(globals.AppConfig.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil { os.Exit(2) }
|
if err != nil { os.Exit(2) }
|
||||||
|
|
||||||
|
globals.LatexExec.Timestamp = "mytimestamp"
|
||||||
|
|
||||||
|
// webserver init
|
||||||
|
server := &http.Server{Addr: globals.AppConfig.WebserverDomain + ":" + globals.AppConfig.WebserverPort}
|
||||||
|
serverSecure := &http.Server{Addr: globals.AppConfig.WebserverDomain + ":" + globals.AppConfig.WebserverPortSecure}
|
||||||
|
|
||||||
|
http.HandleFunc("/", frontend.MainHandler)
|
||||||
|
http.HandleFunc("/sse", frontend.SSEventHandler)
|
||||||
|
http.HandleFunc("/pdf", frontend.PDFHandler)
|
||||||
|
jscss, _ := fs.Sub(frontend.WebFiles, "jscss")
|
||||||
|
http.Handle("/jscss/", http.StripPrefix("/jscss/", http.FileServer(http.FS(jscss))))
|
||||||
|
|
||||||
|
go server.ListenAndServe()
|
||||||
|
if globals.AppConfig.WebserverSecure {
|
||||||
|
go serverSecure.ListenAndServeTLS(globals.AppConfig.CertificatePath, globals.AppConfig.CertificateKeyPath)
|
||||||
|
}
|
||||||
|
backend.LogLine("Started")
|
||||||
|
|
||||||
|
// shutdown logic
|
||||||
|
fmt.Println("Press CTRL-C to Exit ServTeX")
|
||||||
|
|
||||||
|
stop := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
<-stop
|
||||||
|
|
||||||
|
context, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
fmt.Print("\r")
|
||||||
|
if err = server.Shutdown(context); err != nil {
|
||||||
|
backend.LogLine("Graceful Shutdown failed")
|
||||||
|
}
|
||||||
|
if err = serverSecure.Shutdown(context); err != nil {
|
||||||
|
backend.LogLine("Graceful Shutdown failed")
|
||||||
|
}
|
||||||
|
backend.LogLine("Stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
testing.crt
Normal file
19
testing.crt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDCTCCAfGgAwIBAgIUfDzMzEHwX7jXT3lKp9+o3MreMNUwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MTIyNTIxNTgzMFoXDTI2MTIy
|
||||||
|
NTIxNTgzMFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
|
||||||
|
AAOCAQ8AMIIBCgKCAQEAyORa1+z/hdvaFX9IRRiadw51xmuVNWenMslb+hu2+PWz
|
||||||
|
yAwYLNm03JAomFV/Qxm3RCUiZ9kPPw+CWjert40BX908k7rb5IeV4pHAsJkvR65T
|
||||||
|
ZFCnCpR+e7nOIhy7zDmlilcATq77/AWhyfodR0lUuSTMSO8dYwZRs2rTAkItAo3j
|
||||||
|
RnMDom742lBjTn7b4F/FZOstbPXX9j1povIyYQ5k92HqRwVeTG+h7w3njnoMOYeW
|
||||||
|
YOWUUB1LyPHdzPJ50ooqvsNdBcYkkAR8C/R5czUaF/KUXHYM0zoz+QPk+KqTRGeJ
|
||||||
|
XNVB99viI6QlNVniY0YtJBWl/TEzSQVbt1lEMf3JmwIDAQABo1MwUTAdBgNVHQ4E
|
||||||
|
FgQUscO27AhUsPrR0NaYDuWgHvgFMrIwHwYDVR0jBBgwFoAUscO27AhUsPrR0NaY
|
||||||
|
DuWgHvgFMrIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEANDUA
|
||||||
|
YrkofOVQ4Y33YGYTpPSf8CKIOMgJuKFihre7fcBevwRqBkhu+QBty3hvfzJSzUEx
|
||||||
|
bT9twiO94F8gke1KAWjZQpd05aAtoa3OHf3JPTvRlPqNMpP+g+gCAj2Fm3NT8yBW
|
||||||
|
nQyIRFg1DVydc61HxvR49DqiigzV+GgjcSS/WAtEDu6l/WhmvGCTHwYxY6w3LT+R
|
||||||
|
3E/JEp/Mp9o55IFR9tz5wL3R5w4R5JwQZOKdbzQPkYjoxXjI3ldfXC9U/h86t5Md
|
||||||
|
QmdWYyIfQxsqGoA0LAsUll/zwv1ywudeK1lxNtywXIKIur90a3D81MiTkzbhytVE
|
||||||
|
DKD9klpayWzekOXrlA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
28
testing.key
Normal file
28
testing.key
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDI5FrX7P+F29oV
|
||||||
|
f0hFGJp3DnXGa5U1Z6cyyVv6G7b49bPIDBgs2bTckCiYVX9DGbdEJSJn2Q8/D4Ja
|
||||||
|
N6u3jQFf3TyTutvkh5XikcCwmS9HrlNkUKcKlH57uc4iHLvMOaWKVwBOrvv8BaHJ
|
||||||
|
+h1HSVS5JMxI7x1jBlGzatMCQi0CjeNGcwOibvjaUGNOftvgX8Vk6y1s9df2PWmi
|
||||||
|
8jJhDmT3YepHBV5Mb6HvDeeOegw5h5Zg5ZRQHUvI8d3M8nnSiiq+w10FxiSQBHwL
|
||||||
|
9HlzNRoX8pRcdgzTOjP5A+T4qpNEZ4lc1UH32+IjpCU1WeJjRi0kFaX9MTNJBVu3
|
||||||
|
WUQx/cmbAgMBAAECggEAY3JboBlT0rVnS44DPiU0TeyME+ns5o+FvsfcLr8qgCrN
|
||||||
|
USHfk9A/zpHUbrigM5zW0raZRhQ3Dm4EhtmZOVdlj0mrM6xkL0iJQ6wIWcOzGoZr
|
||||||
|
BLVCQ6QHywLLTqqvsqT01DtGTS0lU3iMQzp75O6hsLdNI2uvPfaCWlFu3Gba9jBb
|
||||||
|
ZdT+qd9cca3FQSL0fut3msLNr2STtKLgVTEB7IHz2lEbsioBTcd7IlrsXQKTsR9N
|
||||||
|
UOyTbOzDybt5kWmDYvtuQ7cfMfEuv4fWCBtFib1JljswJI2TaE1Gwpb7u8Hcq2w9
|
||||||
|
FCAPtxltYnNRO4Xhru+zkxnG2kVNf/3Z6jzsnfIFHQKBgQDqOl4cwiev8oLwyXbR
|
||||||
|
UVL7dfXjTGv6PphRAvXHwkOAH8xzndQT6ro7g3ftODDnndN/+/orblB3K4iBMQeU
|
||||||
|
GVkmKQb1J2sXhRyf5e60WX3ZrhmW7+n7Fmx+znF98NZNSF6QhoYQmfy2ffXlwped
|
||||||
|
FFyZIkD+MrpNn0hpDa+yS/uA9QKBgQDbkLtxZMo1NKBhC8hKLRO4gzNzTt4n3cbm
|
||||||
|
psT8bo56fJYjWcr6RGlUJXF+Hol+2cn7MUtYJDpfwT72L6+BF0uv6R6s8eL2R5gE
|
||||||
|
/gBkIhvx0fMrP5hR+GPd5Gd7PLudbNL5hVH1uOBOkbscy/XhIon32iD+AZzTkybP
|
||||||
|
DOxO5uZGTwKBgGxkRlkYoDUUDPRQxuNmtvgXRorBOta7UNFshUDD7WjFTl/SkeoF
|
||||||
|
ndkcpcrpTfhhWRbJDKQ8kJAVXT4r6k3mzRKTudyJOU3RE8YLKcPcBhlOMBlhPO4t
|
||||||
|
Glg0QOD/Kqzo6JoJJtFX8VKiR8DjpDXUzmUvLNR1tTFmnKPA6aWg8+phAoGADDww
|
||||||
|
dc0sB3L7TO0fKCMC6lFFWLOYZZhSMSAx8e8nOWQf6bBjQzb0t5+uh1ykRNFWFA1X
|
||||||
|
KX47UoKuQ4G8wfDOYusWroR8JUUwD3coBmxwKjWM22gb0NWKmx7TNWbY/ZjG2Oi4
|
||||||
|
/Hxk43vzdVNYTEdkcM9S71SfrJqSmw8ZS/xJ8LkCgYEA3DaHLR4KNitppL4Tx+5j
|
||||||
|
dpIKUlCVCtxp4cOtpyuDSg8ssfHB3ZsX7j3+KFX0hF4imORAfUlUkzayuAAw6spF
|
||||||
|
luPjDo+9g8mmVi3FArkbmef67L98A8C947EpoaqAeZWmFpG2w5tOB0vZcn/gFzOp
|
||||||
|
hA4tRHe4o26/PRBUb4GFlq8=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
Reference in New Issue
Block a user