Compare commits
1 commit
master
...
fix_issue_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b39358dd6 |
5 changed files with 56 additions and 13 deletions
|
|
@ -15,6 +15,7 @@
|
|||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=$ga"></script>
|
||||
<script>
|
||||
window.SERVER_URL = "$server_url";
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
|
|
|||
|
|
@ -267,7 +267,9 @@ proc initialise() =
|
|||
{
|
||||
"title": config.title,
|
||||
"timestamp": encodeUrl(CompileDate & CompileTime),
|
||||
"ga": config.ga
|
||||
"ga": config.ga,
|
||||
# An ugly hack, maybe there's a better way?
|
||||
"server_url": "$server_url"
|
||||
}.newStringTable()
|
||||
|
||||
|
||||
|
|
@ -1554,4 +1556,4 @@ routes:
|
|||
|
||||
get re"/(.*)":
|
||||
cond request.matches[0].splitFile.ext == ""
|
||||
resp karaxHtml
|
||||
resp karaxHtml % {"server_url": request.url.jsEscape}.newStringTable
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import options, tables, sugar, httpcore
|
||||
import options, tables, sugar, httpcore, uri
|
||||
from dom import window, Location, document, decodeURI
|
||||
|
||||
include karax/prelude
|
||||
import karax/[kdom]
|
||||
import jester/[patterns]
|
||||
|
||||
import threadlist, postlist, header, profile, newthread, error, about
|
||||
|
|
@ -12,6 +13,7 @@ type
|
|||
State = ref object
|
||||
originalTitle: cstring
|
||||
url: Location
|
||||
serverUri: Uri
|
||||
profile: ProfileState
|
||||
newThread: NewThread
|
||||
about: About
|
||||
|
|
@ -36,6 +38,7 @@ proc newState(): State =
|
|||
State(
|
||||
originalTitle: document.title,
|
||||
url: copyLocation(window.location),
|
||||
serverUri: SERVER_URI,
|
||||
profile: newProfileState(),
|
||||
newThread: newNewThread(),
|
||||
about: newAbout(),
|
||||
|
|
@ -56,6 +59,7 @@ proc onPopState(event: dom.Event) =
|
|||
state.url = copyLocation(window.location)
|
||||
|
||||
redraw()
|
||||
window.location.reload()
|
||||
|
||||
type Params = Table[string, string]
|
||||
type
|
||||
|
|
@ -66,12 +70,12 @@ type
|
|||
proc r(n: string, p: proc (params: Params): VNode): Route = Route(n: n, p: p)
|
||||
proc route(routes: openarray[Route]): VNode =
|
||||
let path =
|
||||
if state.url.pathname.len == 0: "/" else: $state.url.pathname
|
||||
if state.serverUri.path.len == 0: "/" else: state.serverUri.path
|
||||
let prefix = if appName == "/": "" else: appName
|
||||
for route in routes:
|
||||
let pattern = (prefix & route.n).parsePattern()
|
||||
var (matched, params) = pattern.match(path)
|
||||
parseUrlQuery($state.url.search, params)
|
||||
parseUrlQuery($state.serverUri.query, params)
|
||||
if matched:
|
||||
return route.p(params)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import strutils, strformat, parseutils, tables
|
||||
import strutils, strformat, parseutils, tables, uri
|
||||
|
||||
proc parseIntSafe*(s: string, value: var int) {.noSideEffect.} =
|
||||
## parses `s` into an integer in the range `validRange`. If successful,
|
||||
|
|
@ -31,6 +31,10 @@ when defined(js):
|
|||
|
||||
const appName* = "/"
|
||||
|
||||
# Get the server URL that we set in the backend
|
||||
var SERVER_URL* {.importc: "SERVER_URL".}: cstring
|
||||
let SERVER_URI* = parseUri($SERVER_URL)
|
||||
|
||||
proc class*(classes: varargs[tuple[name: string, present: bool]],
|
||||
defaultClasses: string = ""): string =
|
||||
result = defaultClasses & " "
|
||||
|
|
@ -42,11 +46,13 @@ when defined(js):
|
|||
## Concatenates ``relative`` to the current URL in a way that is
|
||||
## (possibly) sane.
|
||||
var relative = relative
|
||||
assert appName in $window.location.pathname
|
||||
assert appName in SERVER_URI.path
|
||||
if relative[0] == '/': relative = relative[1..^1]
|
||||
|
||||
return $window.location.protocol & "//" &
|
||||
$window.location.host &
|
||||
let port = if SERVER_URI.port.len > 0: ":" & SERVER_URI.port else: ""
|
||||
|
||||
return SERVER_URI.scheme & "://" &
|
||||
SERVER_URI.hostname & port &
|
||||
appName &
|
||||
relative &
|
||||
search &
|
||||
|
|
@ -62,7 +68,7 @@ when defined(js):
|
|||
query.add(param[0] & "=" & param[1])
|
||||
|
||||
if query.len > 0:
|
||||
var search = if reuseSearch: $window.location.search else: ""
|
||||
var search = if reuseSearch: SERVER_URI.query else: ""
|
||||
if search.len != 0: search.add("&")
|
||||
search.add(query)
|
||||
if search[0] != '?': search = "?" & search
|
||||
|
|
@ -86,6 +92,7 @@ when defined(js):
|
|||
let url = n.getAttr("href")
|
||||
|
||||
navigateTo(url)
|
||||
window.location.href = url
|
||||
|
||||
proc newFormData*(form: dom.Element): FormData
|
||||
{.importcpp: "new FormData(@)", constructor.}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,21 @@
|
|||
import asyncdispatch, smtp, strutils, json, os, rst, rstgen, xmltree, strtabs,
|
||||
htmlparser, streams, parseutils, options, logging
|
||||
import asyncdispatch, strutils, json, os, rst, rstgen, xmltree, strtabs,
|
||||
htmlparser, streams, parseutils, logging, uri, options, nre, strformat
|
||||
from times import getTime, getGMTime, format
|
||||
|
||||
import jester
|
||||
import jester/private/utils as jesterutils
|
||||
|
||||
when useHttpBeast:
|
||||
import httpbeast except Settings, Request
|
||||
else:
|
||||
import asynchttpserver
|
||||
|
||||
# Used to be:
|
||||
# {'A'..'Z', 'a'..'z', '0'..'9', '_', '\128'..'\255'}
|
||||
let
|
||||
UsernameIdent* = IdentChars # TODO: Double check that everyone follows this.
|
||||
|
||||
import frontend/[karaxutils, error]
|
||||
import frontend/[error]
|
||||
export parseInt
|
||||
|
||||
type
|
||||
|
|
@ -181,3 +189,24 @@ proc rstToHtml*(content: string): string =
|
|||
add(result, node, indWidth=0, addNewLines=false)
|
||||
except:
|
||||
warn("Could not parse rst html.")
|
||||
|
||||
proc jsEscape*(str: string): string =
|
||||
## Escapes a string to be stored in a JS variable. This prevents
|
||||
## XSS attacks. Taken from here: https://portswigger.net/web-security/cross-site-scripting/preventing
|
||||
str.replace(
|
||||
re"[^\w. ]",
|
||||
proc(match: string): string =
|
||||
let code = match[0].ord
|
||||
fmt"\u{code:04x}"
|
||||
)
|
||||
|
||||
proc url*(request: Request): string =
|
||||
## Get the full URL of the request, including the query params
|
||||
let nativeRequest = request.getNativeReq
|
||||
when useHttpBeast:
|
||||
let query = nativeRequest.path.get("").parseUri().query
|
||||
else:
|
||||
let query = nativeRequest.url.query
|
||||
|
||||
let proto = if request.secure: "https" else: "http"
|
||||
result = proto & "://" & request.host & request.path & query
|
||||
Loading…
Add table
Add a link
Reference in a new issue