implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.6.4")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.4.1")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.4.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.5.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.5.0")
- implementation("io.ktor:ktor-server-core-jvm:2.3.0")
- implementation("io.ktor:ktor-server-netty-jvm:2.3.0")
+ implementation("io.ktor:ktor-server-core-jvm:2.3.1")
+ implementation("io.ktor:ktor-server-netty-jvm:2.3.1")
- implementation("io.ktor:ktor-server-call-id:2.3.0")
- implementation("io.ktor:ktor-server-call-logging:2.3.0")
- implementation("io.ktor:ktor-server-conditional-headers:2.3.0")
- implementation("io.ktor:ktor-server-forwarded-header:2.3.0")
- implementation("io.ktor:ktor-server-html-builder:2.3.0")
- implementation("io.ktor:ktor-server-sessions-jvm:2.3.0")
- implementation("io.ktor:ktor-server-status-pages:2.3.0")
+ implementation("io.ktor:ktor-server-call-id:2.3.1")
+ implementation("io.ktor:ktor-server-call-logging:2.3.1")
+ implementation("io.ktor:ktor-server-conditional-headers:2.3.1")
+ implementation("io.ktor:ktor-server-forwarded-header:2.3.1")
+ implementation("io.ktor:ktor-server-html-builder:2.3.1")
+ implementation("io.ktor:ktor-server-sessions-jvm:2.3.1")
+ implementation("io.ktor:ktor-server-status-pages:2.3.1")
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.8.0")
exclude("org.jetbrains.kotlinx", "kotlinx-serialization-core-jvm")
}
- implementation("org.slf4j:slf4j-api:1.7.36")
- implementation("ch.qos.logback:logback-classic:1.3.5")
+ implementation("org.slf4j:slf4j-api:2.0.5")
+ implementation("ch.qos.logback:logback-classic:1.4.7")
}
java {
import info.mechyrdia.data.*
import info.mechyrdia.lore.*
import io.ktor.http.*
-import io.ktor.http.content.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.html.*
import io.ktor.server.plugins.*
import io.ktor.server.plugins.callid.*
import io.ktor.server.plugins.callloging.*
-import io.ktor.server.plugins.conditionalheaders.*
import io.ktor.server.plugins.forwardedheaders.*
import io.ktor.server.plugins.statuspages.*
import io.ktor.server.request.*
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import io.ktor.server.sessions.serialization.*
-import io.ktor.util.*
import org.slf4j.event.Level
import java.io.File
import java.io.IOException
-import java.io.InputStream
import java.util.concurrent.atomic.AtomicLong
lateinit var application: Application
serializer = KotlinxSessionSerializer(UserSession.serializer(), JsonStorageCodec)
- cookie.extensions["SameSite"] = "lax"
+ cookie.httpOnly = true
+ cookie.extensions["SameSite"] = "Lax"
cookie.extensions["Secure"] = null
}
}
package info.mechyrdia.lore
import info.mechyrdia.Configuration
+import kotlinx.serialization.json.JsonPrimitive
import java.io.File
sealed class TextParserTagType<TContext> {
),
H1(
TextParserTagType.Indirect { _, content, _ ->
- "<h1>$content</h1>"
+ "<h1>$content</h1><script>window.checkRedirectTarget();</script>"
}
),
H2(
"<a id=\"$anchor\" name=\"$anchor\"></a>"
}
),
+ REDIRECT(
+ TextParserTagType.Indirect { _, content, _ ->
+ val target = TextParserState.censorText(content)
+ val url = if (target.startsWith('/')) "/lore$target" else "./$target"
+ val string = JsonPrimitive(url).toString()
+
+ "<script>window.factbookRedirect($string);</script>"
+ }
+ ),
// Conlangs
LANG(
link(rel = "stylesheet", href = "/static/style.css")
+ request.queryParameters["redirect"]?.let { redirect ->
+ if (redirect == "no")
+ script {
+ unsafe {
+ raw("window.disableFactbookRedirect = true;")
+ }
+ }
+ }
+
+ script(src = "/static/init.js") {}
+
title {
+pageTitle
}
}
}
}
-
- script(src = "/static/init.js") {}
}
}
}
</encoder>
</appender>
- <root level="any">
+ <root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="LOGDIR"/>
</root>
});
}
});
+
+ window.factbookRedirect = function (redirectTo) {
+ if (window.disableFactbookRedirect) {
+ const redirectTarget = new URL(redirectTo, window.location);
+
+ const redirectTargetUrl = redirectTarget.pathname + redirectTarget.search + redirectTarget.hash;
+
+ const pElement = document.createElement("p");
+ pElement.style.fontWeight = "800";
+ pElement.append(document.createTextNode("Redirect to "));
+
+ const aElement = document.createElement("a");
+ aElement.href = redirectTargetUrl;
+ aElement.append(document.createTextNode(redirectTarget.pathname));
+
+ pElement.append(aElement);
+ document.currentScript.after(pElement);
+ } else {
+ document.cookie = "RedirectedFrom=" + window.location.pathname + "; SameSite=Lax; Secure";
+ window.location = redirectTo;
+ }
+ };
+
+ window.checkRedirectTarget = function () {
+ const redirectSourceValues = document.cookie.split(';').filter(value => value.trim().startsWith("RedirectedFrom="));
+ if (redirectSourceValues.length > 0) {
+ const redirectSource = new URL(redirectSourceValues[0].trim().substring("RedirectedFrom=".length), window.location.origin);
+ if (redirectSource.search.length > 0) {
+ redirectSource.search += "&redirect=no";
+ } else {
+ redirectSource.search = "?redirect=no";
+ }
+
+ const redirectSourceUrl = redirectSource.pathname + redirectSource.search + redirectSource.hash;
+
+ const pElement = document.createElement("p");
+ pElement.style.fontSize = "0.8em";
+ pElement.append(document.createTextNode("Redirected from "));
+
+ const aElement = document.createElement("a");
+ aElement.href = redirectSourceUrl;
+ aElement.append(document.createTextNode(redirectSource.pathname));
+
+ pElement.append(aElement);
+ document.currentScript.after(pElement);
+ }
+
+ document.cookie = "RedirectedFrom=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax; Secure";
+ };
})();