Added an experimental content security policy.
Added support for Open Graph Descriptions. Nox now officially supports notices. Tweaked the language detection algorithm to cover more cases. Tweaked the user agent parser to accomodate DotBot better. Added a non-JS fallback for the theme selector. Tweaked the padding on widget simple. Scripts should now execute properly for individual language charts in the analytics panel.
This commit is contained in:
parent
1fb497adf8
commit
fe33112827
|
@ -33,7 +33,8 @@ type Header struct {
|
||||||
Path string
|
Path string
|
||||||
MetaDesc string
|
MetaDesc string
|
||||||
//OGImage string
|
//OGImage string
|
||||||
//OGDesc string
|
OGDesc string
|
||||||
|
LooseCSP bool
|
||||||
StartedAt time.Time
|
StartedAt time.Time
|
||||||
Elapsed1 string
|
Elapsed1 string
|
||||||
Writer http.ResponseWriter
|
Writer http.ResponseWriter
|
||||||
|
|
|
@ -85,6 +85,7 @@ type config struct {
|
||||||
|
|
||||||
DisableLiveTopicList bool
|
DisableLiveTopicList bool
|
||||||
DisableJSAntispam bool
|
DisableJSAntispam bool
|
||||||
|
//LooseCSP bool
|
||||||
|
|
||||||
Noavatar string // ? - Move this into the settings table?
|
Noavatar string // ? - Move this into the settings table?
|
||||||
ItemsPerPage int // ? - Move this into the settings table?
|
ItemsPerPage int // ? - Move this into the settings table?
|
||||||
|
|
|
@ -768,7 +768,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
for _, item := range StringToBytes(ua) {
|
for _, item := range StringToBytes(ua) {
|
||||||
if (item > 64 && item < 91) || (item > 96 && item < 123) {
|
if (item > 64 && item < 91) || (item > 96 && item < 123) {
|
||||||
buffer = append(buffer, item)
|
buffer = append(buffer, item)
|
||||||
} else if item == ' ' || item == '(' || item == ')' || item == '-' || (item > 47 && item < 58) || item == '_' || item == ';' || item == ':' || item == '.' || item == '+' || item == '~' || (item == ':' && bytes.Equal(buffer,[]byte("http"))) || item == ',' || item == '/' {
|
} else if item == ' ' || item == '(' || item == ')' || item == '-' || (item > 47 && item < 58) || item == '_' || item == ';' || item == ':' || item == '.' || item == '+' || item == '~' || item == '@' || (item == ':' && bytes.Equal(buffer,[]byte("http"))) || item == ',' || item == '/' {
|
||||||
if len(buffer) != 0 {
|
if len(buffer) != 0 {
|
||||||
if len(buffer) > 2 {
|
if len(buffer) > 2 {
|
||||||
// Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append
|
// Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append
|
||||||
|
@ -862,8 +862,9 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
if lang != "" {
|
if lang != "" {
|
||||||
lang = strings.TrimSpace(lang)
|
lang = strings.TrimSpace(lang)
|
||||||
lLang := strings.Split(lang,"-")
|
lLang := strings.Split(lang,"-")
|
||||||
common.DebugDetail("lLang:", lLang)
|
llLang := strings.Split(strings.Split(lLang[0],";")[0],",")
|
||||||
validCode := counters.LangViewCounter.Bump(lLang[0])
|
common.DebugDetail("llLang:", llLang)
|
||||||
|
validCode := counters.LangViewCounter.Bump(llLang[0])
|
||||||
if !validCode {
|
if !validCode {
|
||||||
r.DumpRequest(req,"Invalid ISO Code")
|
r.DumpRequest(req,"Invalid ISO Code")
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,7 +560,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
for _, item := range StringToBytes(ua) {
|
for _, item := range StringToBytes(ua) {
|
||||||
if (item > 64 && item < 91) || (item > 96 && item < 123) {
|
if (item > 64 && item < 91) || (item > 96 && item < 123) {
|
||||||
buffer = append(buffer, item)
|
buffer = append(buffer, item)
|
||||||
} else if item == ' ' || item == '(' || item == ')' || item == '-' || (item > 47 && item < 58) || item == '_' || item == ';' || item == ':' || item == '.' || item == '+' || item == '~' || (item == ':' && bytes.Equal(buffer,[]byte("http"))) || item == ',' || item == '/' {
|
} else if item == ' ' || item == '(' || item == ')' || item == '-' || (item > 47 && item < 58) || item == '_' || item == ';' || item == ':' || item == '.' || item == '+' || item == '~' || item == '@' || (item == ':' && bytes.Equal(buffer,[]byte("http"))) || item == ',' || item == '/' {
|
||||||
if len(buffer) != 0 {
|
if len(buffer) != 0 {
|
||||||
if len(buffer) > 2 {
|
if len(buffer) > 2 {
|
||||||
// Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append
|
// Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append
|
||||||
|
@ -654,8 +654,9 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
if lang != "" {
|
if lang != "" {
|
||||||
lang = strings.TrimSpace(lang)
|
lang = strings.TrimSpace(lang)
|
||||||
lLang := strings.Split(lang,"-")
|
lLang := strings.Split(lang,"-")
|
||||||
common.DebugDetail("lLang:", lLang)
|
llLang := strings.Split(strings.Split(lLang[0],";")[0],",")
|
||||||
validCode := counters.LangViewCounter.Bump(lLang[0])
|
common.DebugDetail("llLang:", llLang)
|
||||||
|
validCode := counters.LangViewCounter.Bump(llLang[0])
|
||||||
if !validCode {
|
if !validCode {
|
||||||
r.DumpRequest(req,"Invalid ISO Code")
|
r.DumpRequest(req,"Invalid ISO Code")
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,6 +200,7 @@ func AccountRegister(w http.ResponseWriter, r *http.Request, user common.User, h
|
||||||
return common.LocalError("You're already logged in.", w, r, user)
|
return common.LocalError("You're already logged in.", w, r, user)
|
||||||
}
|
}
|
||||||
header.Title = phrases.GetTitlePhrase("register")
|
header.Title = phrases.GetTitlePhrase("register")
|
||||||
|
header.LooseCSP = true
|
||||||
pi := common.Page{header, tList, nil}
|
pi := common.Page{header, tList, nil}
|
||||||
return renderTemplate("register", w, r, header, pi)
|
return renderTemplate("register", w, r, header, pi)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,13 @@ func ParseSEOURL(urlBit string) (slug string, id int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderTemplate(tmplName string, w http.ResponseWriter, r *http.Request, header *common.Header, pi interface{}) common.RouteError {
|
func renderTemplate(tmplName string, w http.ResponseWriter, r *http.Request, header *common.Header, pi interface{}) common.RouteError {
|
||||||
|
if header.MetaDesc != "" && header.OGDesc == "" {
|
||||||
|
header.OGDesc = header.MetaDesc
|
||||||
|
}
|
||||||
|
// TODO: Expand this to non-HTTPS requests too
|
||||||
|
if !header.LooseCSP && common.Site.EnableSsl {
|
||||||
|
w.Header().Set("Content-Security-Policy", "default-src https: 'unsafe-eval'; style-src https: 'unsafe-eval' 'unsafe-inline'; img-src https: 'unsafe-eval' 'unsafe-inline'; connect-src * 'unsafe-eval' 'unsafe-inline'; upgrade-insecure-requests")
|
||||||
|
}
|
||||||
if header.CurrentUser.IsAdmin {
|
if header.CurrentUser.IsAdmin {
|
||||||
header.Elapsed1 = time.Since(header.StartedAt).String()
|
header.Elapsed1 = time.Since(header.StartedAt).String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ func ViewForum(w http.ResponseWriter, r *http.Request, user common.User, header
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
header.Title = forum.Name
|
header.Title = forum.Name
|
||||||
|
header.OGDesc = forum.Desc
|
||||||
|
|
||||||
// TODO: Does forum.TopicCount take the deleted items into consideration for guests? We don't have soft-delete yet, only hard-delete
|
// TODO: Does forum.TopicCount take the deleted items into consideration for guests? We don't have soft-delete yet, only hard-delete
|
||||||
offset, page, lastPage := common.PageOffset(forum.TopicCount, page, common.Config.ItemsPerPage)
|
offset, page, lastPage := common.PageOffset(forum.TopicCount, page, common.Config.ItemsPerPage)
|
||||||
|
|
|
@ -31,6 +31,7 @@ func init() {
|
||||||
func ViewProfile(w http.ResponseWriter, r *http.Request, user common.User, header *common.Header) common.RouteError {
|
func ViewProfile(w http.ResponseWriter, r *http.Request, user common.User, header *common.Header) common.RouteError {
|
||||||
// TODO: Preload this?
|
// TODO: Preload this?
|
||||||
header.AddSheet(header.Theme.Name + "/profile.css")
|
header.AddSheet(header.Theme.Name + "/profile.css")
|
||||||
|
header.LooseCSP = true
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var replyCreatedAt time.Time
|
var replyCreatedAt time.Time
|
||||||
|
|
|
@ -70,6 +70,11 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, header
|
||||||
topic.ContentHTML = common.ParseMessage(topic.Content, topic.ParentID, "forums")
|
topic.ContentHTML = common.ParseMessage(topic.Content, topic.ParentID, "forums")
|
||||||
topic.ContentLines = strings.Count(topic.Content, "\n")
|
topic.ContentLines = strings.Count(topic.Content, "\n")
|
||||||
|
|
||||||
|
header.OGDesc = topic.Content
|
||||||
|
if len(header.OGDesc) > 200 {
|
||||||
|
header.OGDesc = header.OGDesc[:197] + "..."
|
||||||
|
}
|
||||||
|
|
||||||
postGroup, err := common.Groups.Get(topic.Group)
|
postGroup, err := common.Groups.Get(topic.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
|
@ -123,6 +128,10 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, header
|
||||||
|
|
||||||
// Get the replies if we have any...
|
// Get the replies if we have any...
|
||||||
if topic.PostCount > 0 {
|
if topic.PostCount > 0 {
|
||||||
|
var pFrag int
|
||||||
|
if strings.HasPrefix(r.URL.Fragment, "post-") {
|
||||||
|
pFrag, _ = strconv.Atoi(strings.TrimPrefix(r.URL.Fragment, "post-"))
|
||||||
|
}
|
||||||
var likedMap map[int]int
|
var likedMap map[int]int
|
||||||
if user.Liked > 0 {
|
if user.Liked > 0 {
|
||||||
likedMap = make(map[int]int)
|
likedMap = make(map[int]int)
|
||||||
|
@ -156,6 +165,13 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, header
|
||||||
replyItem.ContentHtml = common.ParseMessage(replyItem.Content, topic.ParentID, "forums")
|
replyItem.ContentHtml = common.ParseMessage(replyItem.Content, topic.ParentID, "forums")
|
||||||
replyItem.ContentLines = strings.Count(replyItem.Content, "\n")
|
replyItem.ContentLines = strings.Count(replyItem.Content, "\n")
|
||||||
|
|
||||||
|
if replyItem.ID == pFrag {
|
||||||
|
header.OGDesc = replyItem.Content
|
||||||
|
if len(header.OGDesc) > 200 {
|
||||||
|
header.OGDesc = header.OGDesc[:197] + "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
postGroup, err = common.Groups.Get(replyItem.Group)
|
postGroup, err = common.Groups.Get(replyItem.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
{{if not .HideFromThemes}}<option val="{{.Name}}"{{if eq $.Header.Theme.Name .Name}} selected{{end}}>{{.FriendlyName}}</option>{{end}}
|
{{if not .HideFromThemes}}<option val="{{.Name}}"{{if eq $.Header.Theme.Name .Name}} selected{{end}}>{{.FriendlyName}}</option>{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</select>
|
</select>
|
||||||
|
<noscript><input type="submit" /></noscript>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
<meta property="og:site_name" content="{{.Header.Site.Name}}">
|
<meta property="og:site_name" content="{{.Header.Site.Name}}">
|
||||||
<meta property="og:title" content="{{.Title}} | {{.Header.Site.Name}}">
|
<meta property="og:title" content="{{.Title}} | {{.Header.Site.Name}}">
|
||||||
<meta name="twitter:title" content="{{.Title}} | {{.Header.Site.Name}}" />
|
<meta name="twitter:title" content="{{.Title}} | {{.Header.Site.Name}}" />
|
||||||
|
{{if .OGDesc}}<meta property="og:description" content="{{.OGDesc}}" />
|
||||||
|
<meta property="twitter:description" content="{{.OGDesc}}" />{{end}}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{if not .CurrentUser.IsSuperMod}}<style>.supermod_only { display: none !important; }</style>{{end}}
|
{{if not .CurrentUser.IsSuperMod}}<style>.supermod_only { display: none !important; }</style>{{end}}
|
||||||
|
|
|
@ -15,6 +15,5 @@
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
|
||||||
{{template "panel_analytics_script.html" . }}
|
{{template "panel_analytics_script.html" . }}
|
||||||
{{template "footer.html" . }}
|
{{template "footer.html" . }}
|
||||||
|
|
|
@ -153,6 +153,12 @@ li a {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #444444;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +167,9 @@ li a {
|
||||||
padding-top: 14px !important;
|
padding-top: 14px !important;
|
||||||
padding-bottom: 14px !important;
|
padding-bottom: 14px !important;
|
||||||
}
|
}
|
||||||
|
.widget_simple.rowhead .rowitem {
|
||||||
|
padding-bottom: 4px !important;
|
||||||
|
}
|
||||||
.the_form {
|
.the_form {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
|
|
|
@ -26,4 +26,18 @@ $(document).ready(() => {
|
||||||
alerts.className += " selectedAlert";
|
alerts.className += " selectedAlert";
|
||||||
document.getElementById("back").className += " alertActive"
|
document.getElementById("back").className += " alertActive"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Move the alerts above the first header
|
||||||
|
let colSel = $(".colstack_right .colstack_head:first");
|
||||||
|
let colSelAlt = $(".colstack_right .colstack_item:first");
|
||||||
|
let colSelAltAlt = $(".colstack_right .coldyn_block:first");
|
||||||
|
if(colSel.length > 0) {
|
||||||
|
$('.alert').insertBefore(colSel);
|
||||||
|
} else if (colSelAlt.length > 0) {
|
||||||
|
$('.alert').insertBefore(colSelAlt);
|
||||||
|
} else if (colSelAltAlt.length > 0) {
|
||||||
|
$('.alert').insertBefore(colSelAltAlt);
|
||||||
|
} else {
|
||||||
|
$('.alert').insertAfter(".rowhead:first");
|
||||||
|
}
|
||||||
});
|
});
|
Loading…
Reference in New Issue