From be976a38f1d95258f19d94f4cf5dc4c677041ed9 Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Mon, 29 Mar 2021 16:38:00 -0400 Subject: Changed how temp files work on UNIX-y stuff. Fixed templates, which were quite broken. --- captain/captian.f90 | 1 + captain/config.f90 | 5 +++ captain/external.f90 | 17 ++++++---- captain/gemini.f90 | 83 ++++++++++++++++++++++++++++++++++++++++++----- captain/template.f90 | 91 +++++++++++++++++++++++++++++----------------------- common/utilities.F90 | 32 +++++++++--------- 6 files changed, 160 insertions(+), 69 deletions(-) diff --git a/captain/captian.f90 b/captain/captian.f90 index 24fc34c..2c3cab4 100644 --- a/captain/captian.f90 +++ b/captain/captian.f90 @@ -2,6 +2,7 @@ program captain use captain_db use config use logging, only: initialize_log => initialize, logunit +use gemini, only: handle_gemini => handle_request implicit none integer::mode diff --git a/captain/config.f90 b/captain/config.f90 index 338dc4d..dc26ef4 100644 --- a/captain/config.f90 +++ b/captain/config.f90 @@ -36,6 +36,7 @@ contains i = index(str, '=') if(i > 0) then + i = i - 1 ! Remove the equal sign v = adjustl(str(1:i)) end if @@ -107,6 +108,10 @@ contains call get_variable(line, cvariable) call get_value(line, cvalue) + + ! Debugging + ! Print *, trim(cvariable)//" => "//trim(cvalue) + call assign_config(trim(cvariable), trim(cvalue)) end if diff --git a/captain/external.f90 b/captain/external.f90 index 86efe94..aa65e71 100644 --- a/captain/external.f90 +++ b/captain/external.f90 @@ -4,18 +4,23 @@ implicit none contains - function external_request_gemini(request) result(renderunit) + function external_request_gemini(request) result(disk_filename) use page_template + use config, only: template_filepath + use logging, only: write_log implicit none character(*), intent(in)::request + character(len=:), pointer::disk_filename integer::renderunit character(1024)::template_file type(template)::page + character(16)::log_tmp ! Open the base template call template_filepath("index.gmi", template_file) - call page%init(template_file) + + call page%init(trim(template_file)) if(trim(request) == "/" .or. trim(request) == "/index.gmi") then @@ -42,11 +47,11 @@ contains call page%assign('title', 'Not Found') end if - - open(newunit=renderunit, form="formatted", status="scratch", access='stream') - - call page%render(renderunit) + + call page%render() + disk_filename => page%output_filename + end function external_request_gemini end module external_handling \ No newline at end of file diff --git a/captain/gemini.f90 b/captain/gemini.f90 index 31b1deb..841bcc4 100644 --- a/captain/gemini.f90 +++ b/captain/gemini.f90 @@ -1,8 +1,34 @@ module gemini implicit none + private + + public :: handle_request + contains + subroutine simplify_request(full_request, local_request) + use logging, only: write_log + implicit none + + character(*), intent(in)::full_request + character(*), intent(out)::local_request + + integer::i, j + + ! Get the file of interest + i = index(full_request, "://") + if(i <= 0) then + local_request = full_request + else + j = index(full_request(i+3:len_trim(full_request)), "/") + local_request = full_request((i+j+2):len_trim(full_request)) + end if + + call write_log("Simplified Local Request: "//trim(local_request)) + + end subroutine simplify_request + subroutine read_request(ssl, req) use jessl, only: ssl_read use iso_c_binding @@ -70,6 +96,7 @@ contains subroutine write_file(ssl, unit_number, mimetype) use iso_c_binding, only: c_ptr, c_carriage_return, c_new_line use jessl, only: ssl_write + use logging implicit none type(c_ptr)::ssl @@ -87,6 +114,28 @@ contains end do end subroutine write_file + + subroutine write_string(ssl, string) + use jessl, only: ssl_write + use iso_c_binding, only: c_ptr + implicit none + + type(c_ptr)::ssl + character(*)::string + character, dimension(:), allocatable::buf + integer::i + + allocate(buf(len(string))) + + do i = 1, len(string) + buf(i) = string(i:i) + end do + + i = ssl_write(ssl, buf) + + deallocate(buf) + + end subroutine write_string subroutine handle_request() use jessl @@ -94,6 +143,7 @@ contains use config use iso_fortran_env use external_handling, only: external_request_gemini + use logging, only: write_log implicit none ! For our TLS connection @@ -103,13 +153,17 @@ contains integer(kind=c_long)::res ! Requested file - character(1024)::request + character(1024)::request, local_request character(512)::mimetype + + character(len=:), pointer::filename_ptr - integer::rendered_unit + integer::rendered_unit, ioerror call library_init() + filename_ptr => null() + method = tls_server_method() ctx = ctx_new(method) @@ -167,20 +221,33 @@ contains call read_request(ssl, request) call write_log("Request is "//trim(request)) + + call simplify_request(request, local_request) - if(len_trim(request) .ge. 4) then - if(request(1:4) == '/api') then + if(len_trim(local_request) .ge. 4) then + if(local_request(1:4) == '/api') then !call handle_api_request(request) else - rendered_unit = external_request_gemini(request) + filename_ptr => external_request_gemini(local_request) end if else - rendered_unit = external_request_gemini(request) + filename_ptr => external_request_gemini(local_request) end if - call write_file(ssl, rendered_unit, "text/gemini") + if(associated(filename_ptr)) then + open(newunit=rendered_unit, file=trim(filename_ptr), status="old", & + form="unformatted", iostat=ioerror, access="stream") + + call write_log("transferring "//trim(filename_ptr)) + call write_file(ssl, rendered_unit, "text/gemini") - close(rendered_unit) + close(rendered_unit) + + if(filename_ptr(1:5) == '/tmp/') then + call unlink(filename_ptr) + end if + deallocate(filename_ptr) + end if end subroutine handle_request diff --git a/captain/template.f90 b/captain/template.f90 index 6b5429d..f8a6625 100644 --- a/captain/template.f90 +++ b/captain/template.f90 @@ -31,6 +31,7 @@ implicit none character(len=:), pointer::base_filename type(variable), dimension(:), pointer::variables + character(len=:), pointer::output_filename contains @@ -39,11 +40,10 @@ implicit none procedure :: assign_integer => template_assign_integer procedure :: assign_string => template_assign_string procedure :: assign_logical => template_assign_logical - procedure :: render_unit => template_render_unit - procedure :: render_filename => template_render_filename + procedure :: render => template_render procedure :: evaluate => template_evaluate + procedure :: generate_output_filename => template_generate_output_filename - generic :: render => render_unit, render_filename generic :: assign => assign_integer, assign_string, assign_logical end type @@ -84,15 +84,12 @@ contains end subroutine variable_shallow_copy subroutine variable_set_name(self, name) + use logging implicit none class(variable)::self character(*), intent(in)::name - - if(associated(self%vname)) then - deallocate(self%vname) - end if - + allocate(character(len=max(len_trim(name), 1)) :: self%vname) if(len_trim(name) == 0) then self%vname = " " @@ -140,15 +137,16 @@ contains end subroutine variable_assign_integer subroutine variable_assign_string(self, name, str) + use logging implicit none class(variable)::self character(*), intent(in)::name, str - call self%set_name(name) + call self%set_name(name) self%vtype = VTYPE_STRING call self%set_string_value(str) - + end subroutine variable_assign_string subroutine variable_assign_logical(self, name, lg) @@ -182,6 +180,8 @@ contains allocate(self%variables(32)) self%variables%vtype = VTYPE_NONE + self%output_filename => null() + end subroutine template_init subroutine template_destroy(self) @@ -196,6 +196,17 @@ contains end subroutine template_destroy + subroutine template_generate_output_filename(self) + use utilities, only: generate_temporary_filename + use logging + implicit none + + class(template)::self + + self%output_filename => generate_temporary_filename() + + end subroutine template_generate_output_filename + function template_available_variable_index(self) result(i) implicit none @@ -212,6 +223,9 @@ contains ! Need to expand if(i > size(self%variables)) then allocate(tmp(size(self%variables)+32)) + + tmp%vtype = VTYPE_NONE + do j=1, i-1 call tmp(j)%shallow_copy(self%variables(j)) end do @@ -239,6 +253,7 @@ contains end subroutine template_assign_integer subroutine template_assign_string(self, name, value) + use logging implicit none class(template)::self @@ -246,6 +261,7 @@ contains integer::i i = template_available_variable_index(self) + call self%variables(i)%assign(name, value) end subroutine template_assign_string @@ -259,30 +275,17 @@ contains integer::i i = template_available_variable_index(self) + call self%variables(i)%assign(name, value) end subroutine template_assign_logical - - subroutine template_render_filename(self, filename) - implicit none - - class(template)::self - character(*), intent(in)::filename - integer::unit_number - - open(file=filename, newunit=unit_number, status="unknown", form="formatted", action="write") - call self%render_unit(unit_number) - - close(unit_number) - - end subroutine template_render_filename - - subroutine template_render_unit(self, unum) + subroutine template_render(self, filename) + use logging implicit none class(template)::self - integer, intent(in)::unum + character(*), intent(in), optional::filename character::this_char, last_char character(len=2)::running_pair, closing_pair @@ -293,14 +296,22 @@ contains logical::writing_now - integer::input, istat, i - - open(newunit=input, file=self%base_filename, status="old", form="formatted", action="read") + integer::input, istat, i, unum + + if(present(filename)) then + allocate(character(len=len_trim(filename)) :: self%output_filename) + self%output_filename = trim(filename) + else + call self%generate_output_filename() + end if + + open(newunit=unum, file=trim(self%output_filename), status="new", form="formatted", access="stream", action="write") + open(newunit=input, file=trim(self%base_filename), status="old", form="unformatted", access="stream") writing_now = .true. last_char = ' ' - read(input, '(A1)', iostat=istat) this_char + read(input, iostat=istat) this_char do while(istat == 0) running_pair = last_char//this_char @@ -314,17 +325,17 @@ contains brace_internals = ' ' - read(input, '(A1)', iostat=istat) this_char + read(input, iostat=istat) this_char i = 1 - do while(istat == 0 .and. .not. (running_pair /= closing_pair)) + do while(istat == 0 .and. (running_pair /= closing_pair)) brace_internals(i:i) = this_char i = i + 1 last_char = this_char - read(input, '(A1)', iostat=istat) this_char + read(input, iostat=istat) this_char running_pair = last_char//this_char end do - brace_internals(i:i) = ' ' ! Remove trailing bracket + brace_internals(i-1:i-1) = ' ' ! Remove trailing bracket brace_internals = adjustl(brace_internals) ! Simple variable @@ -333,7 +344,7 @@ contains if(associated(replacement)) then do i=1, len_trim(replacement) - write(unum, '(A1)', advance='no') replacement(i:i) + write(unum, '(A1)', advance='no') replacement(i:i) end do replacement => null() ! do not free - internal strings end if @@ -348,18 +359,18 @@ contains write(unum, '(A1)', advance='no') last_char write(unum, '(A1)', advance='no') this_char - else + else if(this_char /= '{') then write(unum, '(A1)', advance='no') this_char - end if last_char = this_char - read(input, '(A1)', iostat=istat) this_char + read(input, iostat=istat) this_char end do + close(unum) close(input) - end subroutine template_render_unit + end subroutine template_render function template_evaluate(self, txt) result(res) implicit none diff --git a/common/utilities.F90 b/common/utilities.F90 index 2e19031..3ce3363 100644 --- a/common/utilities.F90 +++ b/common/utilities.F90 @@ -122,6 +122,7 @@ contains function generate_temporary_filename() result(fullpath) use iso_c_binding + use logging implicit none character(len=:), pointer::fullpath @@ -177,24 +178,13 @@ contains res = GetTempFileName(tmp_path, c_null_ptr, 0, tmp_name) call c_free(tmp_path) -#else - interface - function tmpnam(p) bind(c, name='tmpnam') - use iso_c_binding - type(c_ptr), value::p - type(c_ptr)::tmpnam - end function tmpnam - end interface - type(c_ptr)::ignored - - tmp_name = c_malloc(int(1024, kind=c_size_t)) - - ignored = tmpnam(tmp_name) -#endif - ! Convert the C Ptr to a Fortran object clength = c_strlen(tmp_name) + if(clength == 0) then + call write_log("temp name is zero length") + stop + end if call c_f_pointer(tmp_name, cfullpath, (/ clength /)) allocate(character(len=clength)::fullpath) do i = 1, clength @@ -204,6 +194,18 @@ contains cfullpath => null() call c_free(tmp_name) +#else + character(32)::num_text + real::rnum + + allocate(character(len=1024) :: fullpath) + + call random_number(rnum) + write(num_text, *) abs(rnum) + fullpath = "/tmp/lv."//trim(adjustl(num_text))//".tmp" + +#endif + end function generate_temporary_filename subroutine delete_file(filename) -- cgit v1.2.3