this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

New quotes won't URI encode escape sequences in the DB

+67 -3
+3 -2
internal/handler/quote.go
··· 2 2 3 3 import ( 4 4 "fmt" 5 + "html" 5 6 "net/http" 6 7 ) 7 8 ··· 9 10 func (h *Handler) QuoteHandler(w http.ResponseWriter, r *http.Request) { 10 11 ctx := r.Context() 11 12 12 - quote := r.FormValue("quote") 13 - author := r.FormValue("author") 13 + quote := html.UnescapeString(r.FormValue("quote")) 14 + author := html.UnescapeString(r.FormValue("author")) 14 15 15 16 if quote != "" && author != "" { 16 17 // Perl code did uri_unescape. net/http request parsing handles standard form encoding.
+63
internal/handler/quote_test.go
··· 1 + package handler 2 + 3 + import ( 4 + "context" 5 + "net/http" 6 + "net/http/httptest" 7 + "net/url" 8 + "strings" 9 + "testing" 10 + "tumble/internal/config" 11 + "tumble/internal/data" 12 + ) 13 + 14 + // MockStore implements data.Store for testing 15 + type MockStore struct { 16 + data.Store // Embed interface to skip implementing everything 17 + LastQuote string 18 + LastAuthor string 19 + } 20 + 21 + func (m *MockStore) InsertQuote(ctx context.Context, quote, author string) error { 22 + m.LastQuote = quote 23 + m.LastAuthor = author 24 + return nil 25 + } 26 + 27 + func TestQuoteHandler_UnescapesInput(t *testing.T) { 28 + // Setup 29 + mockStore := &MockStore{} 30 + h := &Handler{ 31 + Store: mockStore, 32 + Config: &config.Config{}, 33 + } 34 + 35 + // Test Case: Encoded HTML entities 36 + // "I&quot;ve been to fort Dicks" -> "I"ve been to fort Dicks" 37 + form := url.Values{} 38 + form.Add("quote", "I&quot;ve been to fort Dicks") 39 + form.Add("author", "james&lt;white&gt;") 40 + 41 + req := httptest.NewRequest("POST", "/quote/", strings.NewReader(form.Encode())) 42 + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 43 + w := httptest.NewRecorder() 44 + 45 + // Execute 46 + h.QuoteHandler(w, req) 47 + 48 + // Verify 49 + if w.Code != http.StatusOK { 50 + t.Errorf("Expected status 200, got %d", w.Code) 51 + } 52 + 53 + // Check if the store received the UNESCAPED string 54 + expectedQuote := "I\"ve been to fort Dicks" 55 + if mockStore.LastQuote != expectedQuote { 56 + t.Errorf("Expected quote %q, got %q", expectedQuote, mockStore.LastQuote) 57 + } 58 + 59 + expectedAuthor := "james<white>" 60 + if mockStore.LastAuthor != expectedAuthor { 61 + t.Errorf("Expected author %q, got %q", expectedAuthor, mockStore.LastAuthor) 62 + } 63 + }
+1 -1
internal/templates/views/index.html
··· 162 162 return div.innerHTML; 163 163 } 164 164 165 - // Global handler for video replacement 165 + // Global handler for video replacemen 166 166 window.replaceWithVideo = function(container) { 167 167 // Find URL from parent item 168 168 var item = container.closest('.item');