parent
							
								
									6d3e8028cb
								
							
						
					
					
						commit
						26be9b5104
					
				
							
								
								
									
										15
									
								
								handlers.go
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								handlers.go
									
									
									
									
									
								
							@ -98,7 +98,7 @@ func (rl *rushlink) viewPasteHandlerFlags(w http.ResponseWriter, r *http.Request
 | 
			
		||||
	key := vars["key"]
 | 
			
		||||
	var p *db.Paste
 | 
			
		||||
	var fu *db.FileUpload
 | 
			
		||||
	if err := rl.db.Bolt.View(func(tx *bolt.Tx) error {
 | 
			
		||||
	err := rl.db.Bolt.View(func(tx *bolt.Tx) error {
 | 
			
		||||
		var err error
 | 
			
		||||
		p, err = db.GetPaste(tx, key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@ -113,12 +113,13 @@ func (rl *rushlink) viewPasteHandlerFlags(w http.ResponseWriter, r *http.Request
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if p == nil {
 | 
			
		||||
		rl.renderError(w, r, http.StatusNotFound, "url key not found in the database")
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		status := db.ErrHTTPStatusCode(err)
 | 
			
		||||
		if status == http.StatusInternalServerError {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		rl.renderError(w, r, status, err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
@ -53,6 +54,35 @@ const (
 | 
			
		||||
	PasteStateDeleted
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// minKeyLen specifies the mimimum length of a paste key.
 | 
			
		||||
const minKeyLen = 4
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrKeyInvalidChar occurs when a key contains an invalid character.
 | 
			
		||||
	ErrKeyInvalidChar = errors.New("invalid character in key")
 | 
			
		||||
	// ErrKeyInvalidLength occurs when a key embeds a length that is incorrect.
 | 
			
		||||
	ErrKeyInvalidLength = errors.New("key length encoding is incorrect")
 | 
			
		||||
	// ErrPasteDoesNotExist occurs when a key does not exist in the database.
 | 
			
		||||
	ErrPasteDoesNotExist = errors.New("url key not found in the database")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrHTTPStatusCode returns the HTTP status code that should correspond to
 | 
			
		||||
// the provided error.
 | 
			
		||||
// server error, or false if it is not.
 | 
			
		||||
func ErrHTTPStatusCode(err error) int {
 | 
			
		||||
	switch err {
 | 
			
		||||
	case nil:
 | 
			
		||||
		return 0
 | 
			
		||||
	case ErrKeyInvalidChar:
 | 
			
		||||
		return http.StatusNotFound
 | 
			
		||||
	case ErrKeyInvalidLength:
 | 
			
		||||
		return http.StatusNotFound
 | 
			
		||||
	case ErrPasteDoesNotExist:
 | 
			
		||||
		return http.StatusNotFound
 | 
			
		||||
	}
 | 
			
		||||
	return http.StatusInternalServerError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Base64 encoding and decoding
 | 
			
		||||
var base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
 | 
			
		||||
var base64Encoder = base64.RawURLEncoding.WithPadding(base64.NoPadding)
 | 
			
		||||
@ -87,13 +117,45 @@ func (t PasteState) String() string {
 | 
			
		||||
 | 
			
		||||
// GetPaste retrieves a paste from the database.
 | 
			
		||||
func GetPaste(tx *bolt.Tx, key string) (*Paste, error) {
 | 
			
		||||
	if err := ValidatePasteKey(key); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return GetPasteNoValidate(tx, key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidatePasteKey validates the format of the key that has
 | 
			
		||||
func ValidatePasteKey(key string) error {
 | 
			
		||||
	internalLen := minKeyLen
 | 
			
		||||
	countingOnes := true
 | 
			
		||||
	for _, ch := range key {
 | 
			
		||||
		limb := strings.IndexRune(base64Alphabet, ch)
 | 
			
		||||
		if limb == -1 {
 | 
			
		||||
			return ErrKeyInvalidChar
 | 
			
		||||
		}
 | 
			
		||||
		for i := 5; i >= 0 && countingOnes; i-- {
 | 
			
		||||
			if (limb>>uint(i))&0x1 == 0 {
 | 
			
		||||
				countingOnes = false
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			internalLen++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if internalLen != len(key) {
 | 
			
		||||
		return ErrKeyInvalidLength
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPasteNoValidate retrieves a paste from the database without validating
 | 
			
		||||
// the key format first.
 | 
			
		||||
func GetPasteNoValidate(tx *bolt.Tx, key string) (*Paste, error) {
 | 
			
		||||
	pastesBucket := tx.Bucket([]byte(BucketPastes))
 | 
			
		||||
	if pastesBucket == nil {
 | 
			
		||||
		return nil, errors.Errorf("bucket %v does not exist", BucketPastes)
 | 
			
		||||
	}
 | 
			
		||||
	storedBytes := pastesBucket.Get([]byte(key))
 | 
			
		||||
	if storedBytes == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
		return nil, ErrPasteDoesNotExist
 | 
			
		||||
	}
 | 
			
		||||
	return decodePaste(storedBytes)
 | 
			
		||||
}
 | 
			
		||||
@ -214,7 +276,6 @@ func GeneratePasteKey(tx *bolt.Tx, minimumEntropy int) (string, error) {
 | 
			
		||||
// is used to ensure that a new key has at least some amount of guessing
 | 
			
		||||
// entropy.
 | 
			
		||||
func generatePasteKeyInner(epoch, entropy int) (string, error) {
 | 
			
		||||
	minKeyLen := 4
 | 
			
		||||
	entropyEpoch := entropy
 | 
			
		||||
	entropyEpoch -= minKeyLen * 6         // First 4 characters provide 24 bits.
 | 
			
		||||
	entropyEpoch++                        // One bit less because of '0' bit.
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user