<commit_before>package handlers

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"fmt"
	"net/http"
	"net/url"
	"runtime"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/maxibanki/golang-url-shortener/handlers/auth"
	"github.com/maxibanki/golang-url-shortener/store"
	"github.com/maxibanki/golang-url-shortener/util"
	"golang.org/x/crypto/bcrypt"
)

// requestHelper is used to help in- and outgoing requests for json
// un- and marshalling
type requestHelper struct {
	URL                       string `binding:"required"`
	ID, DeletionURL, Password string
	Expiration                *time.Time
}

// handleLookup is the http handler for getting the infos
func (h *Handler) handleLookup(c *gin.Context) {
	var data struct {
		ID string `binding:"required"`
	}
	if err := c.ShouldBind(&data); err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	entry, err := h.store.GetEntryByID(data.ID)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	if !h.oAuthPropertiesEquals(c, entry.OAuthID, entry.OAuthProvider) {
		c.JSON(http.StatusOK, store.Entry{
			Public: store.EntryPublicData{
				URL: entry.Public.URL,
			},
		})
		return
	}
	c.JSON(http.StatusOK, entry.Public)
}

// handleAccess handles the access for incoming requests
func (h *Handler) handleAccess(c *gin.Context) {
	id := c.Request.URL.Path[1:]
	entry, err := h.store.GetEntryAndIncrease(id)
	if err == store.ErrNoEntryFound {
		return
	} else if err != nil {
		http.Error(c.Writer, fmt.Sprintf("could not get and crease visitor counter: %v, ", err), http.StatusInternalServerError)
		return
	}
	// No password set
	if len(entry.Password) == 0 {
		c.Redirect(http.StatusTemporaryRedirect, entry.Public.URL)
		go h.registerVisitor(id, c)
		c.Abort()
	} else {
		templateError := ""
		if c.Request.Method == "POST" {
			templateError = func() string {
				pw, exists := c.GetPostForm("password")
				if exists {
					if err := bcrypt.CompareHashAndPassword(entry.Password, []byte(pw)); err != nil {
						return fmt.Sprintf("could not validate password: %v", err)
					}
					return ""
				}
				return "No password set"
			}()
			if templateError == "" {
				c.Redirect(http.StatusTemporaryRedirect, entry.Public.URL)
				go h.registerVisitor(id, c)
				c.Abort()
				return
			}
		}
		c.HTML(http.StatusOK, "protected.html", gin.H{
			"ID":    id,
			"Error": templateError,
		})
	}
}

// handleCreate handles requests to create an entry
func (h *Handler) handleCreate(c *gin.Context) {
	var data requestHelper<commit_msg>Fixed protected entry redirection (fix #55) Now using 'StatusSeeOther' status code which changes POST to GET responses.<commit_after>package handlers

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"fmt"
	"net/http"
	"net/url"
	"runtime"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/maxibanki/golang-url-shortener/handlers/auth"
	"github.com/maxibanki/golang-url-shortener/store"
	"github.com/maxibanki/golang-url-shortener/util"
	"golang.org/x/crypto/bcrypt"
)

// requestHelper is used to help in- and outgoing requests for json
// un- and marshalling
type requestHelper struct {
	URL                       string `binding:"required"`
	ID, DeletionURL, Password string
	Expiration                *time.Time
}

// handleLookup is the http handler for getting the infos
func (h *Handler) handleLookup(c *gin.Context) {
	var data struct {
		ID string `binding:"required"`
	}
	if err := c.ShouldBind(&data); err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	entry, err := h.store.GetEntryByID(data.ID)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	if !h.oAuthPropertiesEquals(c, entry.OAuthID, entry.OAuthProvider) {
		c.JSON(http.StatusOK, store.Entry{
			Public: store.EntryPublicData{
				URL: entry.Public.URL,
			},
		})
		return
	}
	c.JSON(http.StatusOK, entry.Public)
}

// handleAccess handles the access for incoming requests
func (h *Handler) handleAccess(c *gin.Context) {
	id := c.Request.URL.Path[1:]
	entry, err := h.store.GetEntryAndIncrease(id)
	if err == store.ErrNoEntryFound {
		return
	} else if err != nil {
		http.Error(c.Writer, fmt.Sprintf("could not get and crease visitor counter: %v, ", err), http.StatusInternalServerError)
		return
	}
	// No password set
	if len(entry.Password) == 0 {
		c.Redirect(http.StatusTemporaryRedirect, entry.Public.URL)
		go h.registerVisitor(id, c)
		c.Abort()
	} else {
		templateError := ""
		if c.Request.Method == "POST" {
			templateError = func() string {
				pw, exists := c.GetPostForm("password")
				if exists {
					if err := bcrypt.CompareHashAndPassword(entry.Password, []byte(pw)); err != nil {
						return fmt.Sprintf("could not validate password: %v", err)
					}
					return ""
				}
				return "No password set"
			}()
			if templateError == "" {
				c.Redirect(http.StatusSeeOther, entry.Public.URL)
				go h.registerVisitor(id, c)
				c.Abort()
				return
			}
		}
		c.HTML(http.StatusOK, "protected.html", gin.H{
			"ID":    id,
			"Error": templateError,
		})
	}
}

// handleCreate handles requests to create an entry
func (h *Handler) handleCreate(c *gin.Context) {
	var data requestHelper
{'fraction_non_alphanumeric': 0.13894657353218803, 'fraction_numerical': 0.0030205776854823484, 'mean_word_length': 3.528205128205128, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2836169', 'n_tokens_mistral': 2036, 'n_tokens_neox': 1825, 'n_words': 425}