]> Cypherpunks.ru repositories - gocheese.git/blobdiff - gocheese.go
Fix digest mismatch error
[gocheese.git] / gocheese.go
index 4b47f3c51a72deda900a457e07f9e59166d184a8..c2a4d0b8028bd99367d8153a4a3f47d716c0a2ee 100644 (file)
@@ -93,6 +93,8 @@ var (
        warranty         = flag.Bool("warranty", false, "Print warranty information")
 
        killed bool
+
+       normalizationRe *regexp.Regexp = regexp.MustCompilePOSIX("[-_.]+")
 )
 
 func mkdirForPkg(w http.ResponseWriter, r *http.Request, dir string) bool {
@@ -149,12 +151,21 @@ func refreshDir(
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return false
                }
+               if !strings.HasPrefix(pkgURL.Fragment, SHA256Prefix) {
+                       log.Println(r.RemoteAddr, "pypi", filename, "no SHA256 digest provided")
+                       http.Error(w, "no SHA256 digest provided", http.StatusBadGateway)
+                       return false
+               }
                digest, err = hex.DecodeString(strings.TrimPrefix(pkgURL.Fragment, SHA256Prefix))
                if err != nil {
                        http.Error(w, err.Error(), http.StatusBadGateway)
                        return false
                }
                pkgURL.Fragment = ""
+               uri = pkgURL.String()
+               if pkgURL.Host == "" {
+                       uri = *pypiURL + strings.TrimPrefix(uri, "/")
+               }
                path = filepath.Join(dirPath, filename)
                if filename == filenameGet {
                        if killed {
@@ -163,8 +174,9 @@ func refreshDir(
                                return false
                        }
                        log.Println(r.RemoteAddr, "pypi download", filename)
-                       resp, err = http.Get(pkgURL.String())
+                       resp, err = http.Get(uri)
                        if err != nil {
+                               log.Println(r.RemoteAddr, "pypi download error:", err.Error())
                                http.Error(w, err.Error(), http.StatusBadGateway)
                                return false
                        }
@@ -186,7 +198,7 @@ func refreshDir(
                                log.Println(r.RemoteAddr, "pypi", filename, "digest mismatch")
                                os.Remove(dst.Name())
                                dst.Close()
-                               http.Error(w, err.Error(), http.StatusBadGateway)
+                               http.Error(w, "digest mismatch", http.StatusBadGateway)
                                return false
                        }
                        if err = dst.Sync(); err != nil {
@@ -200,22 +212,35 @@ func refreshDir(
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return false
                        }
+                       if err = DirSync(dirPath); err != nil {
+                               http.Error(w, err.Error(), http.StatusInternalServerError)
+                               return false
+                       }
                }
                if filename == filenameGet || gpgUpdate {
-                       if _, err = os.Stat(path); err == nil {
-                               if resp, err := http.Get(pkgURL.String() + GPGSigExt); err == nil {
-                                       sig, err := ioutil.ReadAll(resp.Body)
-                                       resp.Body.Close()
-                                       if err == nil {
-                                               if err = WriteFileSync(dirPath, path+GPGSigExt, sig); err != nil {
-                                                       http.Error(w, err.Error(), http.StatusInternalServerError)
-                                                       return false
-                                               }
-                                               log.Println(r.RemoteAddr, "pypi downloaded signature", filename)
-                                       }
-                               }
+                       if _, err = os.Stat(path); err != nil {
+                               goto GPGSigSkip
+                       }
+                       resp, err := http.Get(uri + GPGSigExt)
+                       if err != nil {
+                               goto GPGSigSkip
+                       }
+                       if resp.StatusCode != http.StatusOK {
+                               resp.Body.Close()
+                               goto GPGSigSkip
+                       }
+                       sig, err := ioutil.ReadAll(resp.Body)
+                       resp.Body.Close()
+                       if err != nil {
+                               goto GPGSigSkip
+                       }
+                       if err = WriteFileSync(dirPath, path+GPGSigExt, sig); err != nil {
+                               http.Error(w, err.Error(), http.StatusInternalServerError)
+                               return false
                        }
+                       log.Println(r.RemoteAddr, "pypi downloaded signature", filename)
                }
+       GPGSigSkip:
                path = path + SHA256Ext
                _, err = os.Stat(path)
                if err == nil {
@@ -326,6 +351,7 @@ func servePkg(w http.ResponseWriter, r *http.Request, dir, filename string) {
 }
 
 func serveUpload(w http.ResponseWriter, r *http.Request) {
+       // Authentication
        username, password, ok := r.BasicAuth()
        if !ok {
                log.Println(r.RemoteAddr, "unauthenticated", username)
@@ -338,11 +364,20 @@ func serveUpload(w http.ResponseWriter, r *http.Request) {
                http.Error(w, "unauthenticated", http.StatusUnauthorized)
                return
        }
+
+       // Form parsing
        var err error
        if err = r.ParseMultipartForm(1 << 20); err != nil {
                http.Error(w, err.Error(), http.StatusBadRequest)
                return
        }
+       pkgNames, exists := r.MultipartForm.Value["name"]
+       if !exists || len(pkgNames) != 1 {
+               http.Error(w, "single name is expected in request", http.StatusBadRequest)
+               return
+       }
+       dir := normalizationRe.ReplaceAllString(pkgNames[0], "-")
+       dirPath := filepath.Join(*root, dir)
        var digestExpected []byte
        if digestExpectedHex, exists := r.MultipartForm.Value["sha256_digest"]; exists {
                digestExpected, err = hex.DecodeString(digestExpectedHex[0])
@@ -352,37 +387,34 @@ func serveUpload(w http.ResponseWriter, r *http.Request) {
                }
        }
        gpgSigsExpected := make(map[string]struct{})
+
+       // Checking is it internal package
+       if _, err = os.Stat(filepath.Join(dirPath, InternalFlag)); err != nil {
+               log.Println(r.RemoteAddr, "non-internal package", dir)
+               http.Error(w, "unknown internal package", http.StatusUnauthorized)
+               return
+       }
+
        for _, file := range r.MultipartForm.File["content"] {
                filename := file.Filename
                gpgSigsExpected[filename+GPGSigExt] = struct{}{}
                log.Println(r.RemoteAddr, "put", filename, "by", username)
-               dir := filename[:strings.LastIndex(filename, "-")]
-               dirPath := filepath.Join(*root, dir)
                path := filepath.Join(dirPath, filename)
                if _, err = os.Stat(path); err == nil {
                        log.Println(r.RemoteAddr, "already exists", filename)
-                       http.Error(w, "Already exists", http.StatusBadRequest)
+                       http.Error(w, "already exists", http.StatusBadRequest)
                        return
                }
                if !mkdirForPkg(w, r, dir) {
                        return
                }
-               internalPath := filepath.Join(dirPath, InternalFlag)
-               var dst *os.File
-               if _, err = os.Stat(internalPath); os.IsNotExist(err) {
-                       if dst, err = os.Create(internalPath); err != nil {
-                               http.Error(w, err.Error(), http.StatusInternalServerError)
-                               return
-                       }
-                       dst.Close()
-               }
                src, err := file.Open()
                defer src.Close()
                if err != nil {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                }
-               dst, err = TempFile(dirPath)
+               dst, err := TempFile(dirPath)
                if err != nil {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
@@ -417,6 +449,10 @@ func serveUpload(w http.ResponseWriter, r *http.Request) {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                }
+               if err = DirSync(dirPath); err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
                if err = WriteFileSync(dirPath, path+SHA256Ext, digest); err != nil {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
@@ -430,12 +466,10 @@ func serveUpload(w http.ResponseWriter, r *http.Request) {
                }
                delete(gpgSigsExpected, filename)
                log.Println(r.RemoteAddr, "put", filename, "by", username)
-               dir := filename[:strings.LastIndex(filename, "-")]
-               dirPath := filepath.Join(*root, dir)
                path := filepath.Join(dirPath, filename)
                if _, err = os.Stat(path); err == nil {
                        log.Println(r.RemoteAddr, "already exists", filename)
-                       http.Error(w, "Already exists", http.StatusBadRequest)
+                       http.Error(w, "already exists", http.StatusBadRequest)
                        return
                }
                src, err := file.Open()
@@ -529,10 +563,10 @@ func goodIntegrity() bool {
                                log.Fatal(err)
                        }
                        if bytes.Compare(hasher.Sum(digest[:0]), data) == 0 {
-                               log.Println(pkgName, "GOOD")
+                               fmt.Println(pkgName, "GOOD")
                        } else {
                                isGood = false
-                               log.Println(pkgName, "BAD")
+                               fmt.Println(pkgName, "BAD")
                        }
                        hasher.Reset()
                }