Skip to content

Commit

Permalink
Handle *.tar, *.gz, *.tar.gz, *.tgz
Browse files Browse the repository at this point in the history
  • Loading branch information
Crosse committed Aug 24, 2022
1 parent ee3c42d commit 1ccfa6b
Showing 1 changed file with 112 additions and 23 deletions.
135 changes: 112 additions & 23 deletions install.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package main

import (
"archive/tar"
"archive/zip"
"bytes"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
Expand Down Expand Up @@ -43,23 +46,38 @@ func InstallFont(fontPath string) (err error) {
return fmt.Errorf("unhandled URL scheme: %v", u.Scheme)
}

if isZipFile(b) {
filename := path.Base(u.Path)

ct := getContentType(b)
log.Debugf("content type: %s", ct)

switch ct {
case "application/zip":
return installFromZIP(b)
}
case "application/x-gzip":
return installFromGZIP(filename, b)
case "application/octet-stream":
if strings.ToLower(path.Ext(filename)) == ".tar" {
return installFromTarball(bytes.NewReader(b))
}

fontData, err = NewFontData(path.Base(u.Path), b)
if err != nil {
return err
fallthrough
default:
fontData, err = NewFontData(filename, b)
if err != nil {
return err
}

return install(fontData)
}

return install(fontData)
}

func isZipFile(data []byte) bool {
func getContentType(data []byte) string {
contentType := http.DetectContentType(data)
log.Debugf("Detected content type: %v", contentType)

return contentType == "application/zip"
return contentType
}

func getRemoteFile(url string) (data []byte, err error) {
Expand Down Expand Up @@ -94,12 +112,75 @@ func getLocalFile(filename string) (data []byte, err error) {
return
}

func installFromGZIP(filename string, data []byte) (err error) {
log.Debug("reading gzipped file")

bytesReader := bytes.NewReader(data)

gzipReader, err := gzip.NewReader(bytesReader)
if err != nil {
return fmt.Errorf("cannot read gzip file: %w", err)
}
defer gzipReader.Close()

uncompressedFilename := strings.TrimSuffix(filename, ".gz")
ext := strings.ToLower(path.Ext(uncompressedFilename))

if ext == ".tar" || ext == ".tgz" {
return installFromTarball(gzipReader)
}

// Gzipped files only contain a single compressed file, so we'll just assume that it's one compressed font.
b, err := io.ReadAll(gzipReader)
if err != nil {
return fmt.Errorf("cannot read compressed file: %w", err)
}

fontData, err := NewFontData(path.Base(uncompressedFilename), b)
if err != nil {
return err
}

return install(fontData)
}

func installFromTarball(r io.Reader) (err error) {
log.Debug("reading tarball")

tarReader := tar.NewReader(r)

fonts := make(map[string]*FontData)

log.Debug("Scanning tarball for fonts")

for {
hdr, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("cannot read tarball: %w", err)
}

data, err := io.ReadAll(tarReader)
if err != nil {
return fmt.Errorf("unable to read file %s from tarball: %w", hdr.Name, err)
}

appendFont(fonts, hdr.Name, data)
}

return installFonts(fonts)
}

func installFromZIP(data []byte) (err error) {
log.Debug("reading zipfile")

bytesReader := bytes.NewReader(data)

zipReader, err := zip.NewReader(bytesReader, int64(bytesReader.Len()))
if err != nil {
return
return fmt.Errorf("cannot read zip file: %w", err)
}

fonts := make(map[string]*FontData)
Expand All @@ -118,25 +199,33 @@ func installFromZIP(data []byte) (err error) {
return err
}

fontData, err := NewFontData(zf.Name, data)
if err != nil {
log.Errorf(`Skipping non-font file "%s"`, zf.Name)
continue
}
appendFont(fonts, zf.Name, data)
}

if _, ok := fonts[fontData.Name]; !ok {
return installFonts(fonts)
}

func appendFont(fonts map[string]*FontData, fileName string, data []byte) {
fontData, err := NewFontData(fileName, data)
if err != nil {
log.Errorf(`Skipping non-font file "%s"`, fileName)
return
}

if _, ok := fonts[fontData.Name]; !ok {
fonts[fontData.Name] = fontData
} else {
// Prefer OTF over TTF; otherwise prefer the first font we found.
first := strings.ToLower(path.Ext(fonts[fontData.Name].FileName))
second := strings.ToLower(path.Ext(fontData.FileName))
if first != second && second == ".otf" {
log.Infof(`Preferring "%s" over "%s"`, fontData.FileName, fonts[fontData.Name].FileName)
fonts[fontData.Name] = fontData
} else {
// Prefer OTF over TTF; otherwise prefer the first font we found.
first := strings.ToLower(path.Ext(fonts[fontData.Name].FileName))
second := strings.ToLower(path.Ext(fontData.FileName))
if first != second && second == ".otf" {
log.Infof(`Preferring "%s" over "%s"`, fontData.FileName, fonts[fontData.Name].FileName)
fonts[fontData.Name] = fontData
}
}
}
}

func installFonts(fonts map[string]*FontData) (err error) {
for _, font := range fonts {
if strings.Contains(strings.ToLower(font.Name), "windows compatible") {
if runtime.GOOS != "windows" {
Expand Down

0 comments on commit 1ccfa6b

Please sign in to comment.