mirror of https://github.com/Corewala/Buran
Compare commits
4 Commits
79a3564569
...
53c1980fa6
Author | SHA1 | Date |
---|---|---|
Corewala | 53c1980fa6 | |
Corewala | 0ae42a214d | |
Corewala | 319b0b4d14 | |
Corewala | 13f21bc09b |
|
@ -29,7 +29,7 @@ Buran is a simple Gemini protocol browser for Android.
|
||||||
- [X] Attention guide mode
|
- [X] Attention guide mode
|
||||||
- [ ] Simple A/B page switching system
|
- [ ] Simple A/B page switching system
|
||||||
- [ ] Pass [Egsam test](https://github.com/pitr/egsam)
|
- [ ] Pass [Egsam test](https://github.com/pitr/egsam)
|
||||||
- [ ] Option to define an HTTPS gateway
|
- [X] Option to define an HTTPS gateway
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,14 @@ class OmniTerm(private val listener: Listener) {
|
||||||
println("OmniTerm resolved address: $address")
|
println("OmniTerm resolved address: $address")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getGlobalUri(reference: String): String {
|
||||||
|
return when {
|
||||||
|
reference.contains(":") -> reference
|
||||||
|
reference.startsWith("//") -> "gemini:$reference"
|
||||||
|
else -> uri.resolve(reference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun reset(){
|
fun reset(){
|
||||||
uri = penultimate.copy()
|
uri = penultimate.copy()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package corewala.buran
|
package corewala.buran
|
||||||
|
|
||||||
const val SCHEME = "gemini://"
|
import corewala.toURI
|
||||||
|
|
||||||
|
const val GEMSCHEME = "gemini://"
|
||||||
const val TRAVERSE = "../"
|
const val TRAVERSE = "../"
|
||||||
const val SOLIDUS = "/"
|
const val SOLIDUS = "/"
|
||||||
const val DIREND = "/"
|
const val DIREND = "/"
|
||||||
|
@ -15,21 +17,28 @@ class OppenURI constructor(private var ouri: String) {
|
||||||
constructor(): this("")
|
constructor(): this("")
|
||||||
|
|
||||||
var host: String = ""
|
var host: String = ""
|
||||||
|
var scheme: String = ""
|
||||||
|
|
||||||
init {
|
init {
|
||||||
extractHost()
|
if(ouri.isNotEmpty()){
|
||||||
|
host = ouri.toURI().host
|
||||||
|
scheme = ouri.toURI().scheme
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun set(ouri: String){
|
fun set(ouri: String){
|
||||||
this.ouri = ouri
|
this.ouri = ouri
|
||||||
extractHost()
|
if(ouri.isNotEmpty()){
|
||||||
|
host = ouri.toURI().host
|
||||||
|
scheme = ouri.toURI().scheme
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolve(reference: String): String{
|
fun resolve(reference: String): String{
|
||||||
if(ouri == "$SCHEME$host") ouri = "$ouri/"
|
if(ouri == "$GEMSCHEME$host") ouri = "$ouri/"
|
||||||
when {
|
when {
|
||||||
reference.startsWith(SCHEME) -> set(reference)
|
reference.startsWith(GEMSCHEME) -> set(reference)
|
||||||
reference.startsWith(SOLIDUS) -> ouri = "$SCHEME$host$reference"
|
reference.startsWith(SOLIDUS) -> ouri = "$scheme://$host$reference"
|
||||||
reference.startsWith(TRAVERSE) -> {
|
reference.startsWith(TRAVERSE) -> {
|
||||||
if(!ouri.endsWith(DIREND)) ouri = ouri.removeFile()
|
if(!ouri.endsWith(DIREND)) ouri = ouri.removeFile()
|
||||||
val traversalCount = reference.split(TRAVERSE).size - 1
|
val traversalCount = reference.split(TRAVERSE).size - 1
|
||||||
|
@ -46,16 +55,16 @@ class OppenURI constructor(private var ouri: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun traverse(): OppenURI{
|
fun traverse(): OppenURI{
|
||||||
val path = ouri.removePrefix("$SCHEME$host")
|
val path = ouri.removePrefix("$GEMSCHEME$host")
|
||||||
val segments = path.split(SOLIDUS).filter { it.isNotEmpty() }
|
val segments = path.split(SOLIDUS).filter { it.isNotEmpty() }
|
||||||
|
|
||||||
var nouri = "$SCHEME$host"
|
var nouri = "$GEMSCHEME$host"
|
||||||
|
|
||||||
when (ouri) {
|
when (ouri) {
|
||||||
"" -> {
|
"" -> {
|
||||||
}
|
}
|
||||||
SCHEME -> ouri = ""
|
GEMSCHEME -> ouri = ""
|
||||||
"$nouri/" -> ouri = SCHEME
|
"$nouri/" -> ouri = GEMSCHEME
|
||||||
else -> {
|
else -> {
|
||||||
when {
|
when {
|
||||||
segments.isNotEmpty() -> {
|
segments.isNotEmpty() -> {
|
||||||
|
@ -74,10 +83,10 @@ class OppenURI constructor(private var ouri: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun traverse(count: Int): String{
|
private fun traverse(count: Int): String{
|
||||||
val path = ouri.removePrefix("$SCHEME$host")
|
val path = ouri.removePrefix("$GEMSCHEME$host")
|
||||||
val segments = path.split(SOLIDUS).filter { it.isNotEmpty() }
|
val segments = path.split(SOLIDUS).filter { it.isNotEmpty() }
|
||||||
val segmentCount = segments.size
|
val segmentCount = segments.size
|
||||||
var nouri = "$SCHEME$host"
|
var nouri = "$GEMSCHEME$host"
|
||||||
|
|
||||||
segments.forEachIndexed{ index, segment ->
|
segments.forEachIndexed{ index, segment ->
|
||||||
if(index < segmentCount - count){
|
if(index < segmentCount - count){
|
||||||
|
@ -89,15 +98,6 @@ class OppenURI constructor(private var ouri: String) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractHost(){
|
|
||||||
if(ouri.isEmpty()) return
|
|
||||||
val urn = ouri.removePrefix(SCHEME)
|
|
||||||
host = when {
|
|
||||||
urn.contains(SOLIDUS) -> urn.substring(0, urn.indexOf(SOLIDUS))
|
|
||||||
else -> urn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copy(): OppenURI = OppenURI(ouri)
|
fun copy(): OppenURI = OppenURI(ouri)
|
||||||
|
|
||||||
override fun toString(): String = ouri
|
override fun toString(): String = ouri
|
||||||
|
|
|
@ -147,7 +147,7 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
||||||
when {
|
when {
|
||||||
currentRequestAddress != uri.toString() -> {}
|
currentRequestAddress != uri.toString() -> {}
|
||||||
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
|
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
|
||||||
header.code == GeminiResponse.REDIRECT -> onUpdate(GemState.Redirect(resolve(uri, header.meta)))
|
header.code == GeminiResponse.REDIRECT -> onUpdate(GemState.Redirect(header.meta))
|
||||||
header.code == GeminiResponse.CLIENT_CERTIFICATE_REQUIRED -> onUpdate(GemState.ClientCertRequired(uri, header))
|
header.code == GeminiResponse.CLIENT_CERTIFICATE_REQUIRED -> onUpdate(GemState.ClientCertRequired(uri, header))
|
||||||
header.code != GeminiResponse.SUCCESS -> onUpdate(GemState.ResponseError(header))
|
header.code != GeminiResponse.SUCCESS -> onUpdate(GemState.ResponseError(header))
|
||||||
header.meta.startsWith("text/gemini") -> getGemtext(bufferedReader, requestEntity.trim().toURI(), header, onUpdate)
|
header.meta.startsWith("text/gemini") -> getGemtext(bufferedReader, requestEntity.trim().toURI(), header, onUpdate)
|
||||||
|
@ -173,8 +173,6 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
||||||
outWriter.close()
|
outWriter.close()
|
||||||
|
|
||||||
socket.close()
|
socket.close()
|
||||||
|
|
||||||
currentRequestAddress = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGemtext(reader: BufferedReader, uri: URI, header: GeminiResponse.Header, onUpdate: (state: GemState) -> Unit){
|
private fun getGemtext(reader: BufferedReader, uri: URI, header: GeminiResponse.Header, onUpdate: (state: GemState) -> Unit){
|
||||||
|
@ -241,12 +239,6 @@ class GeminiDatasource(private val context: Context, val history: BuranHistory):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolve(uri: URI, address: String): String{
|
|
||||||
val ouri = OppenURI()
|
|
||||||
ouri.set(uri.scheme + uri.host)
|
|
||||||
return ouri.resolve(address)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canGoBack(): Boolean = runtimeHistory.isEmpty() || runtimeHistory.size > 1
|
override fun canGoBack(): Boolean = runtimeHistory.isEmpty() || runtimeHistory.size > 1
|
||||||
|
|
||||||
//This just forces the factory to rebuild before the next request
|
//This just forces the factory to rebuild before the next request
|
||||||
|
|
|
@ -97,11 +97,7 @@ class GemActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private val onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit = { uri, longTap, _: Int ->
|
private val onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit = { uri, longTap, _: Int ->
|
||||||
if(longTap){
|
if(longTap){
|
||||||
val globalURI = if(!uri.toString().contains("//") and !uri.toString().contains(":")){
|
val globalURI = omniTerm.getGlobalUri(uri.toString())
|
||||||
(omniTerm.getCurrent() + uri.toString()).replace("//", "/").replace(":/", "://")
|
|
||||||
} else {
|
|
||||||
uri.toString()
|
|
||||||
}
|
|
||||||
Intent().apply {
|
Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
putExtra(Intent.EXTRA_TEXT, globalURI)
|
putExtra(Intent.EXTRA_TEXT, globalURI)
|
||||||
|
@ -462,7 +458,7 @@ class GemActivity : AppCompatActivity() {
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
is GemState.Redirect -> gemRequest(state.uri)
|
is GemState.Redirect -> gemRequest(omniTerm.getGlobalUri(state.uri))
|
||||||
|
|
||||||
is GemState.ClientCertRequired -> runOnUiThread {
|
is GemState.ClientCertRequired -> runOnUiThread {
|
||||||
loadingView(false)
|
loadingView(false)
|
||||||
|
|
Loading…
Reference in New Issue