aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Armstrong <jeff@approximatrix.com>2020-05-05 07:54:53 -0400
committerJeffrey Armstrong <jeff@approximatrix.com>2020-05-05 07:54:53 -0400
commit723324ae71f8209e4b1757a3f84bd0e66b6c6319 (patch)
tree91737e20dba6e06068ea37bb9bcb79122a12d427
parent1ef40339cc161484b3e70d34ab4d507b758b29eb (diff)
downloadLR-87-723324ae71f8209e4b1757a3f84bd0e66b6c6319.zip
LR-87-723324ae71f8209e4b1757a3f84bd0e66b6c6319.tar.gz
Actual client can now load and display a page using dumb_renderer
-rw-r--r--dumb_render.f9012
-rw-r--r--files.f9032
-rw-r--r--gemini-windows.prj7
-rw-r--r--main.F90137
-rw-r--r--protocol.f9043
-rw-r--r--render.f902
-rw-r--r--request.f904
7 files changed, 224 insertions, 13 deletions
diff --git a/dumb_render.f90 b/dumb_render.f90
index 21d6c34..3980245 100644
--- a/dumb_render.f90
+++ b/dumb_render.f90
@@ -36,6 +36,8 @@ implicit none
procedure :: request_input => dumb_request_input
procedure :: draw_error => dumb_draw_error
+
+ procedure :: report_status => dumb_draw_status
end type dumb_renderer
@@ -224,4 +226,14 @@ contains
end subroutine dumb_draw_error
+ subroutine dumb_draw_status(self, text)
+ implicit none
+
+ class(dumb_renderer)::self
+ character(*), intent(in)::text
+
+ Print *, "*** "//trim(text)//" ***"
+
+ end subroutine dumb_draw_status
+
end module dumb_render \ No newline at end of file
diff --git a/files.f90 b/files.f90
index 45bc116..cbdb44d 100644
--- a/files.f90
+++ b/files.f90
@@ -3,8 +3,29 @@ module file_handling
integer, parameter::file_type_plain_text = 1
integer, parameter::file_type_gemini = 2
+ character(17), parameter::end_indicator = "** END OF FILE **"
+
contains
+ subroutine mark_file_end(unit_number)
+ implicit none
+
+ integer, intent(in)::unit_number
+
+ Write(unit_number, '(A17)') end_indicator
+
+ end subroutine mark_file_end
+
+ function is_file_end_marker(text)
+ implicit none
+
+ character(*), intent(in)::text
+ logical::is_file_end_marker
+
+ is_file_end_marker = (index(text, end_indicator) > 0)
+
+ end function is_file_end_marker
+
function read_line_text(unit_number, iostatus) result(res)
implicit none
@@ -24,7 +45,7 @@ contains
end do
length = (endpos - startpos + 1)
- print '(A10, I8)', "allocated", length
+ !print '(A10, I8)', "allocated", length
allocate(character(len=length) :: res)
res = repeat(' ', length)
@@ -97,7 +118,6 @@ contains
type(line), pointer::first_line
type(line), pointer::walker, next_line
- character::c
integer::iostatus
logical::preformatted_on
@@ -110,9 +130,9 @@ contains
walker=>first_line
- call process_line(walker, file_type, preformatted_on)
-
- do while(iostatus /= -1) ! -1 should be end of file
+ do while(iostatus /= -1 .and. .not. is_file_end_marker(walker%text)) ! -1 should be end of file
+
+ call process_line(walker, file_type, preformatted_on)
allocate(next_line)
next_line%next => null()
@@ -122,8 +142,6 @@ contains
walker => walker%next
walker%text = read_line_text(unit_number, iostatus)
- print *, walker%text
- call process_line(walker, file_type, preformatted_on)
end do
diff --git a/gemini-windows.prj b/gemini-windows.prj
index ba68877..d70f6cd 100644
--- a/gemini-windows.prj
+++ b/gemini-windows.prj
@@ -38,6 +38,9 @@
"filename":".\\layout.f90",
"enabled":"1"
},{
+ "filename":".\\main.F90",
+ "enabled":"1"
+ },{
"filename":".\\protocol.f90",
"enabled":"1"
},{
@@ -87,8 +90,8 @@
"Working Directory":"",
"Launch Using MPI":"false",
"Keep Console":"true",
- "External Console":"false",
- "Command Line Arguments":"-g samples\\sample1.gmi",
+ "External Console":"true",
+ "Command Line Arguments":"gemini://pon.ix.tc",
"Build Before Launch":"true"
},
"Build Options":{
diff --git a/main.F90 b/main.F90
new file mode 100644
index 0000000..cb9e8b1
--- /dev/null
+++ b/main.F90
@@ -0,0 +1,137 @@
+program gemini
+use request
+use dumb_render
+use gemini_protocol
+use layout
+use file_handling
+
+#ifdef WINDOWS
+use wsa_network, only: windows_network_startup => startup
+#endif
+
+implicit none
+
+ character(256)::initial_site
+ character(1024)::current_url
+ type(connection)::conn
+ type(dumb_renderer)::r
+
+ logical::running
+ logical::loaded
+
+ integer::return_code
+
+ integer, parameter::io = 100
+
+ type(line), pointer::first_line
+
+#ifdef WINDOWS
+ call windows_network_startup()
+#endif
+
+ if(command_argument_count() > 0) then
+
+ call get_command_argument(1, initial_site)
+
+ if(index(initial_site, "//") > 0) then
+
+ if(index(initial_site, "gemini://") /= 1) then
+ Print *, "Please provide a gemini URL to start (or nothing at all)"
+ stop
+ end if
+
+ else
+
+ initial_site = "gemini://"//trim(initial_site)
+
+ end if
+
+ else
+
+ initial_site = "gemini://gemini.circumlunar.space/" ! gemini://pon.ix.tc/
+
+ end if
+
+ running = .true.
+ loaded = .false.
+ call r%initialize()
+
+ current_url = initial_site
+
+ open(unit=io, form="formatted", status="scratch", access='stream')
+
+ do while(running)
+
+ if(.not. loaded) then
+
+ call r%report_status("Requesting "//trim(current_url))
+
+ return_code = request_url(trim(current_url), io)
+
+ call update_status(r, current_url, return_code)
+
+ loaded = .true.
+
+ end if
+
+ if(return_code == STATUS_REDIRECT) then
+
+ call get_redirect_url(io, current_url)
+ loaded = .false.
+
+ else
+
+ first_line => load_unit(io, file_type_gemini)
+
+ call r%report_status("Performing Layout")
+ call layout_lines(first_line, r)
+
+ end if
+
+
+ running = .not. loaded
+
+
+
+ end do
+
+ close(io)
+
+contains
+
+ subroutine update_status(r, url, code)
+ use gemini_protocol
+ implicit none
+
+ class(renderer)::r
+ character(*), intent(in)::url
+ integer, intent(in)::code
+
+ select case (code)
+
+ case (STATUS_LOCALFAIL)
+ call r%report_status("Network failure loading "//trim(url))
+
+ case (STATUS_INPUT)
+ call r%report_status("Ok (input)")
+
+ case (STATUS_SUCCESS)
+ call r%report_status("Ok")
+
+ case (STATUS_REDIRECT)
+ call r%report_status("Ok (redirect)")
+
+ case (STATUS_TEMPFAIL)
+ call r%report_status("Server reports temporary failure")
+
+ case (STATUS_PERMFAIL)
+ call r%report_status("Server reports permanent failure")
+
+ case (STATUS_CERTREQ)
+ call r%report_status("Server requesting certificate (unsupported)")
+
+ end select
+
+ end subroutine update_status
+
+end program gemini
diff --git a/protocol.f90 b/protocol.f90
index bd109c1..52b6430 100644
--- a/protocol.f90
+++ b/protocol.f90
@@ -16,6 +16,7 @@ contains
function request_url(url, unit_number, server_name) result(returncode)
use request
use iso_c_binding
+ use file_handling, only: mark_file_end
implicit none
character(*), intent(in)::url
@@ -47,7 +48,7 @@ contains
if(send_string(conn%ssl, url//c_carriage_return//c_new_line, trimming=.false.)) then
bytes_received = retrieve_characters(conn%ssl, buffer)
-
+ Print *, bytes_received
do while(bytes_received > 0)
do i=1, bytes_received
@@ -57,6 +58,8 @@ contains
bytes_received = retrieve_characters(conn%ssl, buffer)
end do
+ call mark_file_end(unit_number)
+
rewind(unit_number)
read(unit_number, '(I1)') returncode
@@ -64,18 +67,52 @@ contains
returncode = -1
write(unit_number, *) "Send Error: Could Not Send Request"
-
+ write(*, *) "Send Error: Could Not Send Request"
end if
else
returncode = -1
write(unit_number, *) "Connection Error: "//trim(translate_connection_code(conn%code))
-
+ write(*, *) "Connection Error: "//trim(translate_connection_code(conn%code))
end if
call close_connection(conn)
end function request_url
+ subroutine get_redirect_url(unit_number, url)
+ implicit none
+
+ integer, intent(in)::unit_number
+ character(*), intent(inout)::url
+
+ character::search
+ integer::i, istat
+
+ rewind(unit_number)
+
+ ! Status code
+ read(unit_number, '(A1)', advance='no') search
+ read(unit_number, '(A1)', advance='no') search
+
+ ! Clear the url
+ url = repeat(" ", len(url))
+
+ ! At least one whitespace, but whatever...
+ read(unit_number, '(A1)', advance='no') search
+ do while(search == " " .or. search == CHAR(9))
+ read(unit_number, '(A1)', advance='no', iostat=istat) search
+ end do
+
+ ! Now search contains our first url component
+ i = 0
+ do while(search /= CHAR(13) .and. i < len(url) .and. istat == 0)
+ i = i + 1
+ url(i:i) = search
+ read(unit_number, '(A1)', advance='no', iostat=istat) search
+ end do
+
+ end subroutine get_redirect_url
+
end module gemini_protocol \ No newline at end of file
diff --git a/render.f90 b/render.f90
index 684197c..6f285f7 100644
--- a/render.f90
+++ b/render.f90
@@ -31,6 +31,8 @@ implicit none
procedure(request_input), deferred::request_input
procedure(draw_text), deferred::draw_error
+
+ procedure(draw_text), deferred::report_status
end type renderer
diff --git a/request.f90 b/request.f90
index 67cc4f7..8a4e4e5 100644
--- a/request.f90
+++ b/request.f90
@@ -158,12 +158,14 @@ contains
if(end_server <= 0) then
end_server = len_trim(url)
else
- end_server = end_server + start_server - 1
+ ! Get rid of trailing slash
+ end_server = end_server + start_server - 2
end if
length = end_server - start_server + 1
allocate(character(len=length) :: server)
server = url(start_server:end_server)
+ Print *, "server is: "//trim(server)
end if
end function get_server_from_url