110 lines
4.5 KiB
Go
110 lines
4.5 KiB
Go
package tui
|
||
|
||
import (
|
||
"net/http"
|
||
"strings"
|
||
|
||
"github.com/charmbracelet/lipgloss"
|
||
|
||
"github.com/r3g1tpr0cs/burterm/internal/project"
|
||
"github.com/r3g1tpr0cs/burterm/internal/scanner"
|
||
)
|
||
|
||
// Цвета подобраны по классам HTTP-статуса — тот же принцип, что и
|
||
// цветовая маркировка в Burp: 2xx зелёный, 3xx голубой, 4xx жёлтый,
|
||
// 5xx красный. Сетевые ошибки (таймаут, обрыв соединения — не HTTP-
|
||
// статус вовсе) получают отдельный цвет, чтобы не путать с 5xx.
|
||
var (
|
||
style2xx = lipgloss.NewStyle().Foreground(lipgloss.Color("42"))
|
||
style3xx = lipgloss.NewStyle().Foreground(lipgloss.Color("51"))
|
||
style4xx = lipgloss.NewStyle().Foreground(lipgloss.Color("220"))
|
||
style5xx = lipgloss.NewStyle().Foreground(lipgloss.Color("196"))
|
||
styleErrStatus = lipgloss.NewStyle().Foreground(lipgloss.Color("201"))
|
||
styleDim = lipgloss.NewStyle().Foreground(lipgloss.Color("245"))
|
||
|
||
// styleHighlight — единый стиль для строк, подпавших под пользовательское
|
||
// regex-правило подсветки. Намеренно НЕ комбинируется с statusStyle на
|
||
// одной строке: lipgloss.Style.Render оборачивает текст кодами
|
||
// ESC[...]...ESC[0m, а ESC[0m сбрасывает вообще все атрибуты, включая
|
||
// внешние — если вложить один Render внутрь другого, первый же
|
||
// внутренний сброс "съест" стиль снаружи для остатка строки. Поэтому
|
||
// для подсвеченных строк весь рендер идёт через один-единственный
|
||
// styleHighlight, без отдельной раскраски статуса внутри.
|
||
styleHighlight = lipgloss.NewStyle().Bold(true).Background(lipgloss.Color("58")).Foreground(lipgloss.Color("230"))
|
||
)
|
||
|
||
// statusStyle подбирает стиль по классу статус-кода.
|
||
func statusStyle(code int) lipgloss.Style {
|
||
switch {
|
||
case code >= 200 && code < 300:
|
||
return style2xx
|
||
case code >= 300 && code < 400:
|
||
return style3xx
|
||
case code >= 400 && code < 500:
|
||
return style4xx
|
||
case code >= 500 && code < 600:
|
||
return style5xx
|
||
default:
|
||
return styleDim
|
||
}
|
||
}
|
||
|
||
// colorLabelStyle раскрашивает пользовательскую цветовую метку проекта
|
||
// (project.ColorLabel) в её собственный цвет — не путать с statusStyle,
|
||
// которая красит по автоматическому классу HTTP-статуса: это разные
|
||
// вещи, метка выставляется руками (клавиша "c" на вкладке Project).
|
||
func colorLabelStyle(c project.ColorLabel) lipgloss.Style {
|
||
switch c {
|
||
case project.ColorRed:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("196"))
|
||
case project.ColorOrange:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("208"))
|
||
case project.ColorYellow:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("220"))
|
||
case project.ColorGreen:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("42"))
|
||
case project.ColorCyan:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("51"))
|
||
case project.ColorBlue:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("33"))
|
||
case project.ColorPurple:
|
||
return lipgloss.NewStyle().Foreground(lipgloss.Color("129"))
|
||
default:
|
||
return styleDim
|
||
}
|
||
}
|
||
|
||
// severityStyle подбирает стиль для находок Scanner — переиспользует
|
||
// ту же цветовую шкалу, что и statusStyle, просто с другим входом.
|
||
func severityStyle(sev scanner.Severity) lipgloss.Style {
|
||
switch sev {
|
||
case scanner.SeverityHigh:
|
||
return style5xx
|
||
case scanner.SeverityMedium:
|
||
return style4xx
|
||
case scanner.SeverityLow:
|
||
return style3xx
|
||
default:
|
||
return styleDim
|
||
}
|
||
}
|
||
|
||
// contentTypeLabel вытаскивает короткую метку типа контента из заголовка
|
||
// Content-Type: "application/json; charset=utf-8" → "json".
|
||
func contentTypeLabel(h http.Header) string {
|
||
if h == nil {
|
||
return ""
|
||
}
|
||
ct := h.Get("Content-Type")
|
||
if ct == "" {
|
||
return ""
|
||
}
|
||
if idx := strings.Index(ct, ";"); idx != -1 {
|
||
ct = ct[:idx]
|
||
}
|
||
ct = strings.TrimSpace(ct)
|
||
if idx := strings.LastIndex(ct, "/"); idx != -1 {
|
||
return ct[idx+1:]
|
||
}
|
||
return ct
|
||
}
|