Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat screenshot html #1226

Merged
merged 14 commits into from
Jul 10, 2023
151 changes: 151 additions & 0 deletions runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,148 @@ retry:
gologger.Error().Msgf("Could not write screenshot at path '%s', to disk: %s", screenshotPath, err)
}
}

// HTML Output
HTMLBeginning := `
<!DOCTYPE html>
<html>
<head>
<title>Screenshot Table</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
}

table {
margin-top: 20px;
border-collapse: collapse;
}

th, td {
padding: 10px;
text-align: center;
border: 1px solid black;
}

.thumbnail {
width: 400px;
height: 300px;
object-fit: cover;
}
</style>
</head>
<body>
<table style="margin: 20px auto; border-collapse: collapse;">
<thead>
<tr>
<th style="padding: 10px; text-align: center; border: 1px solid black;"><strong>Response Info</strong></th>
<th style="padding: 10px; text-align: center; border: 1px solid black;"><strong>Screenshot</strong></th>
</tr>
</thead>
<tbody>
`
HTMLEnd := ` </tbody>
</table>
</body>
</html>`
HTMLRow := fmt.Sprintf(`
<tr>
<td style="padding: 10px; border: 1px solid black;">
<ul style="list-style-type: none; padding-left: 0;">
<li><strong>Host:</strong> <a style="text-decoration: none; color: blue;">%s</a></li>
</ul>
</td>
<td style="padding: 10px; border: 1px solid black;">
<a href="%s" target="_blank">
<img src="%s" alt="Screenshot" style="width: 400px; height: 300px;">
</a>
</td>
</tr>`, fullURL, screenshotPath, screenshotPath)
if scanopts.OutputStatusCode {
HTMLRow = appendLineToRow(HTMLRow, "Status Code", resp.StatusCode)
}
if scanopts.OutputTitle {
HTMLRow = appendLineToRow(HTMLRow, "Title", title)
}
if scanopts.OutputContentLength {
HTMLRow = appendLineToRow(HTMLRow, "Content-Length", resp.ContentLength)
}
if scanopts.OutputLocation {
HTMLRow = appendLineToRow(HTMLRow, "Location", resp.GetHeaderPart("Location", ";"))
}
if scanopts.Favicon {
HTMLRow = appendLineToRow(HTMLRow, "Favicon", faviconMMH3)
}
if scanopts.OutputResponseTime {
HTMLRow = appendLineToRow(HTMLRow, "Response Duration", resp.Duration)
}
if scanopts.OutputLinesCount {
HTMLRow = appendLineToRow(HTMLRow, "Response Line Count", resp.Lines)
}
if scanopts.OutputWordsCount {
HTMLRow = appendLineToRow(HTMLRow, "Response Word Count", resp.Words)
}
if scanopts.OutputServerHeader {
HTMLRow = appendLineToRow(HTMLRow, "Server", serverHeader)
}
if scanopts.TechDetect {
technologiesString := strings.Join(technologies, ", ")
HTMLRow = appendLineToRow(HTMLRow, "Technologies", technologiesString)
}
if scanopts.OutputIP {
HTMLRow = appendLineToRow(HTMLRow, "IP", ip)
}
if scanopts.OutputCDN && isCDN && err == nil {
HTMLRow = appendLineToRow(HTMLRow, "CDN", cdnName)
}

var HTMLScreenshotFile *os.File
defer HTMLScreenshotFile.Close()
HTMLPath := filepath.Join(domainScreenshotBaseDir, "screenshot.html")

_, err = os.Stat(HTMLPath)
if os.IsNotExist(err) {
if HTMLScreenshotFile, err = os.Create(HTMLPath); err != nil {
gologger.Error().Msgf("Could not create a new HTML file at path '%s': %s", HTMLPath, err)
}

if _, err = HTMLScreenshotFile.WriteString(HTMLBeginning); err != nil {
gologger.Error().Msgf("Could not write the base HTML to the HTML file: %s", err)
}

if _, err = HTMLScreenshotFile.WriteString(HTMLRow); err != nil {
gologger.Error().Msgf("Could not write the new row to the HTML file: %s", err)
}
} else {
if HTMLScreenshotFile, err = os.OpenFile(HTMLPath, os.O_RDWR, 0600); err != nil {
gologger.Error().Msgf("Could not open the HTML file at path '%s': %s", HTMLPath, err)
}

HTMLByte, _ := io.ReadAll(HTMLScreenshotFile)
HTMLString := string(HTMLByte)

index := strings.Index(HTMLString, HTMLEnd)
if index == -1 {
gologger.Error().Msgf("Could not find the end of the HTML file: %s", err)
}

HTMLString = HTMLString[:index]
HTMLString += HTMLRow

if err = os.WriteFile(HTMLPath, []byte(HTMLString), 0600); err != nil {
gologger.Error().Msgf("Could not write to the HTML file: %s", err)
}
}

if _, err = HTMLScreenshotFile.Seek(0, io.SeekEnd); err != nil {
gologger.Error().Msgf("Could not find the end of the HTML file: %s", err)
}

if _, err = HTMLScreenshotFile.WriteString(HTMLEnd); err != nil {
gologger.Error().Msgf("Could not write the end of the HTML file: %s", err)
}
}

result := Result{
Expand Down Expand Up @@ -1955,3 +2097,12 @@ func normalizeHeaders(headers map[string][]string) map[string]interface{} {
}
return normalized
}

func appendLineToRow(HTMLRow, title string, value interface{}) string {
line := fmt.Sprintf("<li><strong>%s:</strong> <a style=\"text-decoration: none; color: blue;\">%v</a></li>\n</ul>", title, value)
before, after, _ := strings.Cut(HTMLRow, "</ul>")
before += line
before += after

return before
}