2018-01-29 19:44:18 +00:00
|
|
|
// Copyright 2017 The go-ethereum Authors
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
2018-09-05 15:36:14 +00:00
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
2018-01-29 19:44:18 +00:00
|
|
|
"html/template"
|
|
|
|
"path"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/swarm/api"
|
|
|
|
)
|
|
|
|
|
|
|
|
type htmlListData struct {
|
|
|
|
URI *api.URI
|
|
|
|
List *api.ManifestList
|
|
|
|
}
|
|
|
|
|
2018-09-05 15:36:14 +00:00
|
|
|
var TemplatesMap = make(map[string]*template.Template)
|
|
|
|
var faviconBytes []byte
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
for _, v := range []struct {
|
|
|
|
templateName string
|
|
|
|
partial string
|
|
|
|
funcs template.FuncMap
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
templateName: "error",
|
|
|
|
partial: errorResponse,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
templateName: "bzz-list",
|
|
|
|
partial: bzzList,
|
|
|
|
funcs: template.FuncMap{
|
|
|
|
"basename": path.Base,
|
|
|
|
"leaflink": leafLink,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
templateName: "landing-page",
|
|
|
|
partial: landing,
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
TemplatesMap[v.templateName] = template.Must(template.New(v.templateName).Funcs(v.funcs).Parse(baseTemplate + css + v.partial + logo))
|
|
|
|
}
|
|
|
|
|
|
|
|
bytes, err := hex.DecodeString(favicon)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
faviconBytes = bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
func leafLink(URI api.URI, manifestEntry api.ManifestEntry) string {
|
|
|
|
return fmt.Sprintf("/bzz:/%s/%s", URI.Addr, manifestEntry.Path)
|
|
|
|
}
|
|
|
|
|
|
|
|
const bzzList = `{{ define "content" }}
|
|
|
|
<h3 class="top-space">Swarm index of {{ .URI }}</h3>
|
|
|
|
<hr>
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Path</th>
|
|
|
|
<th>Type</th>
|
|
|
|
<th>Size</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
|
|
|
|
<tbody>
|
|
|
|
{{ range .List.CommonPrefixes }}
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<a class="normal-link" href="{{ basename . }}/">{{ basename . }}/</a>
|
|
|
|
</td>
|
|
|
|
<td>DIR</td>
|
|
|
|
<td>-</td>
|
|
|
|
</tr>
|
|
|
|
{{ end }}
|
|
|
|
{{ range .List.Entries }}
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<a class="normal-link" href="{{ leaflink $.URI . }}">{{ basename .Path }}</a>
|
|
|
|
</td>
|
|
|
|
<td>{{ .ContentType }}</td>
|
|
|
|
<td>{{ .Size }}</td>
|
|
|
|
</tr>
|
|
|
|
{{ end }}
|
|
|
|
</table>
|
|
|
|
<hr>
|
|
|
|
|
|
|
|
{{ end }}`
|
|
|
|
|
|
|
|
const errorResponse = `{{ define "content" }}
|
|
|
|
<div class="container">
|
|
|
|
<div class="logo">
|
|
|
|
{{ template "logo" . }}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="separate-block">
|
|
|
|
<h3>{{.Msg}}</h3>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<h5>Error code: {{.Code}}</h5>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="footer">
|
|
|
|
<p>{{.Timestamp}}</p>
|
|
|
|
<p>Swarm: Serverless Hosting Incentivised Peer-To-Peer Storage And Content Distribution</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{{ end }}`
|
|
|
|
|
|
|
|
const landing = `{{ define "content" }}
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
|
function goToPage() {
|
|
|
|
var page = document.getElementById('page').value;
|
|
|
|
if (page == "") {
|
|
|
|
var page = "theswarm.eth"
|
|
|
|
}
|
|
|
|
var address = "/bzz:/" + page;
|
|
|
|
location.href = address;
|
|
|
|
console.log(address)
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<div class="container">
|
|
|
|
<div class="logo">
|
|
|
|
{{ template "logo" . }}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="searchbar">
|
|
|
|
<form class="separate-block" action="javascript:goToPage();">
|
|
|
|
<input type="text" id="page" autofocus name="search" placeholder="Please enter an ENS name or swarm hash to retrieve ..">
|
|
|
|
<button class="button" type="submit" value="submit" onclick="goToPage();">Go!</button>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
<div class="footer">
|
|
|
|
<p>{{.Timestamp}}</p>
|
|
|
|
<p>Swarm: Serverless Hosting Incentivised Peer-To-Peer Storage And Content Distribution</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{{ end }}`
|
|
|
|
|
|
|
|
const baseTemplate = `<html>
|
2018-01-29 19:44:18 +00:00
|
|
|
<head>
|
2018-09-05 15:36:14 +00:00
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
|
|
|
<meta http-equiv="X-UA-Compatible" ww="chrome=1"/>
|
|
|
|
<link rel="icon" type="image/x-icon" href="favicon.ico"/>
|
|
|
|
<style>
|
|
|
|
{{ template "css" . }}
|
|
|
|
</style>
|
2018-01-29 19:44:18 +00:00
|
|
|
</head>
|
|
|
|
<body>
|
2018-09-05 15:36:14 +00:00
|
|
|
{{ template "content" . }}
|
2018-01-29 19:44:18 +00:00
|
|
|
</body>
|
2018-03-07 21:29:21 +00:00
|
|
|
</html>
|
2018-09-05 15:36:14 +00:00
|
|
|
`
|
|
|
|
|
|
|
|
const css = `{{ define "css" }}
|
|
|
|
html {
|
|
|
|
font-size: 18px;
|
|
|
|
font-size: 1.13rem;
|
|
|
|
-webkit-text-size-adjust: 100%;
|
|
|
|
-ms-text-size-adjust: 100%;
|
|
|
|
font-family: Helvetica, Arial, sans-serif;
|
|
|
|
}
|
|
|
|
|
|
|
|
body {
|
|
|
|
background: #f6f6f6;
|
|
|
|
color: #333;
|
|
|
|
}
|
|
|
|
|
|
|
|
a, a:visited, a:active {
|
|
|
|
color: darkorange;
|
|
|
|
}
|
|
|
|
|
|
|
|
a.normal-link, a.normal-link:active { color: #0000EE; }
|
|
|
|
a.normal-link:visited { color: #551A8B; }
|
|
|
|
|
|
|
|
table {
|
|
|
|
border-collapse: separate;
|
|
|
|
}
|
|
|
|
|
|
|
|
td {
|
|
|
|
padding: 3px 10px;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.container {
|
|
|
|
max-width: 600px;
|
|
|
|
margin: 40px auto 40px;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.separate-block {
|
|
|
|
margin: 40px 0;
|
|
|
|
word-wrap: break-word;
|
|
|
|
}
|
|
|
|
|
|
|
|
.footer {
|
|
|
|
font-size: 12px;
|
|
|
|
font-size: 0.75rem;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.orange {
|
|
|
|
color: #ffa500;
|
|
|
|
}
|
|
|
|
|
|
|
|
.top-space {
|
|
|
|
margin-top: 20px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SVG Logos, editable */
|
|
|
|
|
|
|
|
.searchbar {
|
|
|
|
padding: 20px 20px 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.logo {
|
|
|
|
margin: 100px 80px 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.logo a img {
|
|
|
|
max-width: 140px;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tablet < 600p*/
|
|
|
|
|
|
|
|
@media only screen and (max-width: 600px) {}
|
|
|
|
|
|
|
|
/* Mobile phone < 360p*/
|
|
|
|
|
|
|
|
@media only screen and (max-width: 360px) {
|
|
|
|
h1 {
|
|
|
|
font-size: 20px;
|
|
|
|
font-size: 1.5rem;
|
|
|
|
}
|
|
|
|
h2 {
|
|
|
|
font-size: 0.88rem;
|
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
.logo {
|
|
|
|
margin: 50px 40px 0;
|
|
|
|
}
|
|
|
|
.footer {
|
|
|
|
font-size: 0.63rem;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
input[type=text] {
|
|
|
|
width: 100%;
|
|
|
|
box-sizing: border-box;
|
|
|
|
border: 2px solid #777;
|
|
|
|
border-radius: 2px;
|
|
|
|
font-size: 16px;
|
|
|
|
padding: 12px 20px 12px 20px;
|
|
|
|
transition: border 250ms ease-in-out;
|
|
|
|
}
|
|
|
|
|
|
|
|
input[type=text]:focus {
|
|
|
|
border: 2px solid #ffce73;
|
|
|
|
}
|
|
|
|
|
|
|
|
.button {
|
|
|
|
background-color: #ffa500;
|
|
|
|
margin: 20px 0;
|
|
|
|
border: none;
|
|
|
|
border-radius: 2px;
|
|
|
|
color: #222;
|
|
|
|
padding: 15px 32px;
|
|
|
|
text-align: center;
|
|
|
|
text-decoration: none;
|
|
|
|
display: inline-block;
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
{{ end }}`
|
|
|
|
|
|
|
|
const logo = `{{ define "logo" }}
|
|
|
|
<a href="/bzz:/theswarm.eth"><img src="data:image/png;base64,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
|
|
|
|
{{ end }}`
|
|
|
|
|
|
|
|
const favicon = `000001000400101000000000200068040000460000002020000000002000a8100000ae0400003030000000002000a825000056150000404000000000200028420000fe3a000028000000100000002000000001002000000000004004000000000000000000000000000000000000ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff017e7e7e0362626263545454c548484849ffffff01ffffff01ffffff01ffffff01646464375b5b5bbf4545457758585809ffffff01ffffff01ffffff0164646443626262cf626262ff535353ff454545ff454545b74949492b6868681d626262a5626262fd5c5c5cff464646ff454545dd47474755ffffff01ffffff013f3f3feb565656ff636363ff535353ff464646ff3f3f3fff373737ab393939894d4d4dff626262ff5c5c5cff464646ff424242ff3a3a3af7ffffff01ffffff01383838e9353535ff424242ff474747ff383838ff353535ff363636ab35353587363636ff3a3a3aff4a4a4aff3b3b3bff353535ff363636f5ffffff01ffffff01383838e9303030ff181818ff131313ff232323ff343434ff363636ab35353587343434ff202020ff101010ff1d1d1dff303030ff373737f5ffffff01ffffff01232323c50c0c0cff0d0d0dff131313ff171717ff171717ff2929298b2727276b0f0f0ffd0d0d0dff101010ff171717ff161616ff232323d9ffffff01ffffff014d4d4d030f0f0f650c0c0ce7131313ff161616d51d1d1d4b63636363464646691717173b0d0d0dc50f0f0fff161616ef171717752e2e2e07ffffff01ffffff01ffffff01ffffff011d1d1d0f1515155360606045626262cf636363ff464646ff454545d3484848491414144d24242417ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff013c3c3c374f4f4fff636363ff636363ff464646ff464646ff3f3f3fff3c3c3c41ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff013636363d353535ff3c3c3cff575757ff363636ff181818ff282828ff37373747ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff013636363d363636ff303030ff181818ff292929ff131313ef17171771696969136565653bffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01323232371e1e1eff0d0d0dff0c0c0cff363636ff363636a3ffffff0185858515606060ff4747476bffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01111111450d0d0dd10c0c0cff1b1b1bff2a2a2a993e3e3e0b30303085292929ff37373787ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01363636030e0e0e671616166b45454505323232432e2e2ed9151515c31d1d1d2dffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff014e4e4e05ffffff01ffffff01ffffff01ffffff010000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff28000000200000004000000001002000000000008010000000000000000000000000000000000000ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff017272721b646464a54646466f72727205ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff0168686845575757b74f4f4f39ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff017e7e7e0b6262627d616161f3636363ff424242ff444444d74f4f4f49ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff016c6c6c27636363b5616161ff555555ff434343ff464646a35858581dffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff01ffffff016666665d616161e3626262ff636363ff636363ff444444ff464646ff434343ff454545b95252522bffffff01ffffff01ffffff01ffffff016c6c6c1363636393616161fb636363ff636363ff555555ff464646ff464646ff444444f5464646836666660bffffff01ffffff01ffffff01ffffff01ffffff016a6a6a3f626262c9616161ff636363ff636363ff636363ff636363ff444444ff464646ff464646ff464646ff434343fb48484897545454135b5b5b036868686f616161ef626262ff636363ff636363ff636363ff555555ff464646ff464646ff464646ff454545ff444444e54a4a4a5fffffff01ffffff01ffffff01ffffff013b3b3bd7505050ff646464ff636363ff636363ff636363ff63
|