Initial commit
This commit is contained in:
commit
e0e19240b5
|
@ -0,0 +1,227 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"strings"
|
||||
"time"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type BookInfo struct {
|
||||
Title string
|
||||
GpubVersion string
|
||||
Index string
|
||||
Author string
|
||||
Language string
|
||||
Charset string
|
||||
Description string
|
||||
Published string
|
||||
PublishDate string
|
||||
RevisionDate string
|
||||
Copyright string
|
||||
License string
|
||||
Version string
|
||||
Cover string
|
||||
}
|
||||
|
||||
var fileSystem map[string]*zip.File
|
||||
var bookInfo BookInfo
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("USAGE:", os.Args[0], "filename")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Opening", os.Args[1])
|
||||
file, err := zip.OpenReader(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Println("Failed to open", os.Args[1], err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileSystem = make(map[string]*zip.File)
|
||||
if !validate(&file.Reader) {
|
||||
fmt.Println(os.Args[1], "could not be validated...")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
fmt.Println(os.Args[1], "has been validated")
|
||||
printBookInfo()
|
||||
}
|
||||
}
|
||||
|
||||
func printBookInfo() {
|
||||
if bookInfo.Title != "" {
|
||||
fmt.Println("Title:", bookInfo.Title)
|
||||
}
|
||||
if bookInfo.GpubVersion != "" {
|
||||
fmt.Println("GpubVersion:", bookInfo.GpubVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func validate(archive *zip.Reader) bool {
|
||||
isThereMetadata := false
|
||||
|
||||
for _, f := range archive.File { // looking for metadata first, and put all files in map
|
||||
if f.Name == "metadata.txt" {
|
||||
if !isValidMetadata(f) {
|
||||
fmt.Println("FATAL:", f.Name,"present but not valid")
|
||||
return false
|
||||
}
|
||||
|
||||
isThereMetadata = true
|
||||
}
|
||||
|
||||
fileSystem[f.Name] = f
|
||||
}
|
||||
|
||||
if isThereMetadata {
|
||||
if bookInfo.Index == "" {
|
||||
fmt.Println("WARNING: No index provided, checking default index.gmi")
|
||||
return isValidContent("index.gmi")
|
||||
} else {
|
||||
return isValidContent(bookInfo.Index)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("WARNING: This is not a book but a capsule archive")
|
||||
|
||||
f, ok := fileSystem["index.gmi"]
|
||||
if !ok {
|
||||
fmt.Println("FATAL: This is a capsule archive but index.gmi is not present at root")
|
||||
return false
|
||||
}
|
||||
|
||||
if f.FileHeader.FileInfo().IsDir() {
|
||||
fmt.Println("FATAL:", f.Name, "is a directory")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func isValidMetadata(file *zip.File) bool {
|
||||
isThereTitle := false
|
||||
isThereGpubVersion := false
|
||||
|
||||
if file.FileHeader.FileInfo().IsDir() {
|
||||
fmt.Println("FATAL:", file.Name, "is a directory !")
|
||||
return false
|
||||
}
|
||||
|
||||
reader, err := file.Open()
|
||||
if err != nil {
|
||||
fmt.Println("FATAL:", file.Name, "can't be opened")
|
||||
return false
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Trim(line, " ") != "" {
|
||||
columnPosition := strings.Index(line, ":")
|
||||
if columnPosition == -1 {
|
||||
fmt.Println("FATAL: invalid line in", file.Name, line)
|
||||
return false
|
||||
}
|
||||
|
||||
key := strings.Trim(line[:columnPosition], " ")
|
||||
value := strings.Trim(line[columnPosition+1:], " ")
|
||||
|
||||
switch key {
|
||||
case "title":
|
||||
bookInfo.Title = value
|
||||
isThereTitle = true
|
||||
case "gpubVersion":
|
||||
bookInfo.GpubVersion = value
|
||||
isThereGpubVersion = true
|
||||
case "index":
|
||||
bookInfo.Index = value
|
||||
case "author":
|
||||
bookInfo.Author = value
|
||||
case "language":
|
||||
//todo is language tag valid ? BCP 47
|
||||
bookInfo.Language = value
|
||||
case "charset":
|
||||
bookInfo.Charset = value
|
||||
case "description":
|
||||
bookInfo.Description = value
|
||||
case "published":
|
||||
_, err := strconv.ParseUint(value, 10, 32)
|
||||
if err != nil {
|
||||
fmt.Println("FATAL: Bad format in", key, err)
|
||||
}
|
||||
bookInfo.Published = value
|
||||
case "publishDate":
|
||||
_, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
fmt.Println("FATAL: Bad date format in", key, err)
|
||||
return false
|
||||
}
|
||||
bookInfo.PublishDate = value
|
||||
case "revisionDate":
|
||||
_, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
fmt.Println("FATAL: Bad date format in", key, err)
|
||||
return false
|
||||
}
|
||||
bookInfo.RevisionDate = value
|
||||
case "copyright":
|
||||
bookInfo.Copyright = value
|
||||
case "license":
|
||||
bookInfo.License = value
|
||||
case "version":
|
||||
bookInfo.Version = value
|
||||
case "cover":
|
||||
bookInfo.Cover = value
|
||||
default:
|
||||
fmt.Println("FATAL: Unknown key in", file.Name, key)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Println("FATAL: error while scanning", file.Name, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if !isThereTitle { // only two fields are mandatory
|
||||
fmt.Println("FATAL: No title provided !")
|
||||
return false
|
||||
} else if !isThereGpubVersion {
|
||||
fmt.Println("FATAL: No GpubVersion provided !")
|
||||
return false
|
||||
} else { // the last thing we need to test is version validity
|
||||
return isVersionValid()
|
||||
}
|
||||
}
|
||||
|
||||
func isValidContent(filePath string) bool {
|
||||
if filePath == "" || filePath == "/" { //we want index
|
||||
filePath = "index.gmi"
|
||||
} else if strings.HasPrefix(filePath, "/") { //we must ingore the leading slash
|
||||
filePath = filePath[1:]
|
||||
}
|
||||
|
||||
file, ok := fileSystem[filePath]
|
||||
if !ok {
|
||||
fmt.Println("FATAL:", filePath, "doesn't exist !")
|
||||
return false
|
||||
}
|
||||
|
||||
if file.FileHeader.FileInfo().IsDir() { //this is a dir, we look at index.gmi
|
||||
return isValidContent(filePath + "index.gmi")
|
||||
}
|
||||
|
||||
//todo
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isVersionValid() bool {
|
||||
return bookInfo.GpubVersion == "1.0.0"
|
||||
}
|
Loading…
Reference in New Issue