/*
GoCheese -- Python private package repository and caching proxy
-Copyright (C) 2019-2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2019-2022 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
"crypto/sha512"
"encoding/hex"
"encoding/json"
+ "errors"
"hash"
"io"
- "io/ioutil"
"log"
"net/http"
"net/url"
http.Error(w, "PyPI has non 200 status code", http.StatusBadGateway)
return false
}
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ resp.Body.Close()
+ log.Println("error", r.RemoteAddr, "refresh-json", pkgName, err)
+ http.Error(w, "can not read body", http.StatusBadGateway)
+ return false
+ }
resp.Body.Close()
var buf bytes.Buffer
var description string
err = json.Unmarshal(body, &meta)
if err == nil {
for _, m := range [][2]string{
- {MetadataFieldName, meta.Info.Name},
- {MetadataFieldVersion, meta.Info.Version},
- {MetadataFieldSummary, meta.Info.Summary},
- {MetadataFieldDescriptionContentType, meta.Info.DescriptionContentType},
- {MetadataFieldKeywords, meta.Info.Keywords},
- {MetadataFieldHomePage, meta.Info.HomePage},
- {MetadataFieldAuthor, meta.Info.Author},
- {MetadataFieldAuthorEmail, meta.Info.AuthorEmail},
- {MetadataFieldMaintainer, meta.Info.Maintainer},
- {MetadataFieldMaintainerEmail, meta.Info.MaintainerEmail},
- {MetadataFieldLicense, meta.Info.License},
- {MetadataFieldRequiresPython, meta.Info.RequiresPython},
+ {MDFieldName, meta.Info.Name},
+ {MDFieldVersion, meta.Info.Version},
+ {MDFieldSummary, meta.Info.Summary},
+ {MDFieldDescriptionContentType, meta.Info.DescriptionContentType},
+ {MDFieldKeywords, meta.Info.Keywords},
+ {MDFieldHomePage, meta.Info.HomePage},
+ {MDFieldAuthor, meta.Info.Author},
+ {MDFieldAuthorEmail, meta.Info.AuthorEmail},
+ {MDFieldMaintainer, meta.Info.Maintainer},
+ {MDFieldMaintainerEmail, meta.Info.MaintainerEmail},
+ {MDFieldLicense, meta.Info.License},
+ {MDFieldRequiresPython, meta.Info.RequiresPython},
} {
recField, jsonField := m[0], m[1]
if jsonField == "" {
continue
}
if _, err = wr.WriteFields(recfile.Field{
- Name: metadataFieldToRecField(recField),
+ Name: MDFieldToRecField[recField],
Value: jsonField,
}); err != nil {
log.Fatalln(err)
}
}
for _, m := range []RecFieldToValuesMap{
- {MetadataFieldClassifier, meta.Info.Classifier},
- {MetadataFieldPlatform, meta.Info.Platform},
- {MetadataFieldSupportedPlatform, meta.Info.SupportedPlatform},
- {MetadataFieldRequiresDist, meta.Info.RequiresDist},
- {MetadataFieldRequiresExternal, meta.Info.RequiresExternal},
- {MetadataFieldProjectURL, meta.Info.ProjectURL},
- {MetadataFieldProvidesExtra, meta.Info.ProvidesExtra},
+ {MDFieldClassifier, meta.Info.Classifier},
+ {MDFieldPlatform, meta.Info.Platform},
+ {MDFieldSupportedPlatform, meta.Info.SupportedPlatform},
+ {MDFieldRequiresDist, meta.Info.RequiresDist},
+ {MDFieldRequiresExternal, meta.Info.RequiresExternal},
+ {MDFieldProjectURL, meta.Info.ProjectURL},
+ {MDFieldProvidesExtra, meta.Info.ProvidesExtra},
} {
for _, v := range m.jsonFields {
if _, err = wr.WriteFields(recfile.Field{
- Name: metadataFieldToRecField(m.recField),
+ Name: MDFieldToRecField[m.recField],
Value: v,
}); err != nil {
log.Fatalln(err)
return false
}
for _, m := range [][2]string{
- {MetadataFieldName, metaStripped.Info.Name},
- {MetadataFieldVersion, metaStripped.Info.Version},
- {MetadataFieldSummary, metaStripped.Info.Summary},
- {MetadataFieldDescriptionContentType, metaStripped.Info.DescriptionContentType},
- {MetadataFieldKeywords, metaStripped.Info.Keywords},
- {MetadataFieldHomePage, metaStripped.Info.HomePage},
- {MetadataFieldAuthor, metaStripped.Info.Author},
- {MetadataFieldAuthorEmail, metaStripped.Info.AuthorEmail},
- {MetadataFieldMaintainer, metaStripped.Info.Maintainer},
- {MetadataFieldMaintainerEmail, metaStripped.Info.MaintainerEmail},
- {MetadataFieldLicense, metaStripped.Info.License},
- {MetadataFieldRequiresPython, metaStripped.Info.RequiresPython},
+ {MDFieldName, metaStripped.Info.Name},
+ {MDFieldVersion, metaStripped.Info.Version},
+ {MDFieldSummary, metaStripped.Info.Summary},
+ {MDFieldDescriptionContentType, metaStripped.Info.DescriptionContentType},
+ {MDFieldKeywords, metaStripped.Info.Keywords},
+ {MDFieldHomePage, metaStripped.Info.HomePage},
+ {MDFieldAuthor, metaStripped.Info.Author},
+ {MDFieldAuthorEmail, metaStripped.Info.AuthorEmail},
+ {MDFieldMaintainer, metaStripped.Info.Maintainer},
+ {MDFieldMaintainerEmail, metaStripped.Info.MaintainerEmail},
+ {MDFieldLicense, metaStripped.Info.License},
+ {MDFieldRequiresPython, metaStripped.Info.RequiresPython},
} {
recField, jsonField := m[0], m[1]
if jsonField == "" {
continue
}
if _, err = wr.WriteFields(recfile.Field{
- Name: metadataFieldToRecField(recField),
+ Name: MDFieldToRecField[recField],
Value: jsonField,
}); err != nil {
log.Fatalln(err)
}
for _, m := range []RecFieldToValuesMap{
- {MetadataFieldClassifier, metaStripped.Info.Classifier},
- {MetadataFieldRequiresDist, metaStripped.Info.RequiresDist},
+ {MDFieldClassifier, metaStripped.Info.Classifier},
+ {MDFieldRequiresDist, metaStripped.Info.RequiresDist},
} {
for _, v := range m.jsonFields {
if _, err = wr.WriteFields(recfile.Field{
- Name: metadataFieldToRecField(m.recField),
+ Name: MDFieldToRecField[m.recField],
Value: v,
}); err != nil {
log.Fatalln(err)
lines := strings.Split(description, "\n")
if len(lines) > 0 {
if _, err = wr.WriteFieldMultiline(
- MetadataFieldDescription, lines,
+ MDFieldDescription, lines,
); err != nil {
log.Fatalln(err)
}
if !mkdirForPkg(w, r, pkgName) {
return false
}
- path := filepath.Join(dirPath, MetadataFile)
- existing, err := ioutil.ReadFile(path)
+ path := filepath.Join(dirPath, MDFile)
+ existing, err := os.ReadFile(path)
if err != nil || bytes.Compare(existing, buf.Bytes()) != 0 {
if err = WriteFileSync(dirPath, path, buf.Bytes(), now); err != nil {
log.Println("error", r.RemoteAddr, "refresh-json", path, err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return false
}
- log.Println(r.RemoteAddr, "pypi", pkgName+"/"+MetadataFile, "touch")
+ log.Println(r.RemoteAddr, "pypi", pkgName+"/"+MDFile, "touch")
}
}
mtimes := make(map[string]time.Time)
http.Error(w, "PyPI has non 200 status code", http.StatusBadGateway)
return false
}
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
log.Println("error", r.RemoteAddr, "refresh", pkgName, err)
hasherNew = blake2b256New
hashSize = blake2b.Size256
default:
- log.Println("error", r.RemoteAddr, "pypi", filename, "unknown digest", hashAlgo)
+ log.Println(
+ "error", r.RemoteAddr, "pypi",
+ filename, "unknown digest", hashAlgo,
+ )
http.Error(w, "unknown digest algorithm", http.StatusBadGateway)
return false
}
if len(digest) != hashSize {
- log.Println("error", r.RemoteAddr, "pypi", filename, "invalid digest length")
+ log.Println(
+ "error", r.RemoteAddr, "pypi",
+ filename, "invalid digest length")
http.Error(w, "invalid digest length", http.StatusBadGateway)
return false
}
http.Error(w, "digest mismatch", http.StatusBadGateway)
return false
}
+ if digestStored, err := os.ReadFile(path + "." + hashAlgo); err == nil &&
+ bytes.Compare(digest, digestStored) != 0 {
+ err = errors.New("stored digest mismatch")
+ log.Println("error", r.RemoteAddr, "pypi", filename, err)
+ os.Remove(dst.Name())
+ dst.Close()
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return false
+ }
if !NoSync {
if err = dst.Sync(); err != nil {
os.Remove(dst.Name())
}
if filename == filenameGet || gpgUpdate {
- if _, err = os.Stat(path); err != nil {
- goto GPGSigSkip
- }
resp, err := c.Do(agentedReq(uri + GPGSigExt))
if err != nil {
goto GPGSigSkip
resp.Body.Close()
goto GPGSigSkip
}
- sig, err := ioutil.ReadAll(resp.Body)
+ sig, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
goto GPGSigSkip
}
path = path + "." + hashAlgo
stat, err := os.Stat(path)
- if err == nil &&
- (mtimeExists && stat.ModTime().Truncate(time.Second).Equal(mtime)) {
+ if err == nil && (!mtimeExists ||
+ (mtimeExists && stat.ModTime().Truncate(time.Second).Equal(mtime))) {
continue
}
if err != nil && !os.IsNotExist(err) {