! Copyright (c) 2021 Approximatrix, LLC ! ! Permission is hereby granted, free of charge, to any person obtaining a copy ! of this software and associated documentation files (the "Software"), to deal ! in the Software without restriction, including without limitation the rights ! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! copies of the Software, and to permit persons to whom the Software is ! furnished to do so, subject to the following conditions: ! ! The above copyright notice and this permission notice shall be included in ! all copies or substantial portions of the Software. ! ! The Software shall be used for Good, not Evil. ! ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ! SOFTWARE. program captain use captain_db use config use logging, only: initialize_log => initialize, shutdown_log => shutdown, write_log, LOG_INFO use gemini, only: handle_gemini => handle_request use web, only: handle_web => handle_request implicit none integer::mode integer, parameter::MODE_GEMINI = 1, & MODE_CGI_HTML = 2 call random_seed() ! For possible crypto call parse_options() call initialize_log(log_filename, loglevel) call initialize_db(trim(database_filename)) select case(mode) case(MODE_GEMINI) call handle_gemini() case(MODE_CGI_HTML) call handle_web() end select call shutdown_db() call write_log("Process complete", LOG_INFO) call shutdown_log() contains subroutine usage() implicit none character(len=256)::pname call get_command_argument(0, pname) Print *, "Usage: "//trim(pname)//" " Print *, " " Print *, "Options:" Print *, " -h Display this help" Print *, " -c Use the specified config file" Print *, " -g Operate in Gemini mode" Print *, " -w Operate in CGI mode (default)" Print *, " --new-admin " Print *, " Add a new administrator to the system" Print *, " " Print *, "Config file can also be specified via the environment variables:" Print *, " LEVITATING_CONFIG_CGI Path to config for CGI mode" Print *, " LEVITATING_CONFIG_GEMINI Path to config for Gemini mode" end subroutine usage subroutine parse_options use config use m_crypt use m_uuid, only: generate_uuid4 use captain_db, only: new_admin_db implicit none character(len=1024)::option, username, password character(len=:), pointer::tmp logical::config_loaded integer::i config_loaded = .false. mode = MODE_CGI_HTML loglevel = 3 i = 1 do while(i <= command_argument_count()) call get_command_argument(i, option) if(trim(option) == "-h") then call usage() stop else if(trim(option) == "-g") then mode = MODE_GEMINI else if(trim(option) == "-c") then i = i + 1 call get_command_argument(i, option) call load_configuration(trim(option)) config_loaded = .true. ! This option shouldn't be public, and it just verifies the ! m_crypt module works... else if(trim(option) == "--hash") then i = i + 1 call get_command_argument(i, option) tmp => hash(option) Print *, "Hash: "//trim(tmp) Print *, "Verify: "//trim(option), verify_hash(trim(option), tmp) Print *, "Unverify: "//trim(option)//"X", verify_hash(trim(option)//"X", tmp) stop ! This option shouldn't be public, and it just verifies passwords else if(trim(option) == "--verify") then if(config_loaded) then call initialize_db(trim(database_filename)) i = i + 1 call get_command_argument(i, username) i = i + 1 call get_command_argument(i, password) if(validate_user_db(trim(username), trim(password))) then Print *, "Password accepted!" else Print *, "REJECTED" end if else Print *, "Please specify the configuration file first" end if stop ! This option also shouldn't be public, and it verifies that ! uuids can be generated else if(trim(option) == "--uuid") then if(.not. config_loaded) then ! Look up a directory for temp files - needed below call get_environment_variable("TEMP", temp_dir) end if option = generate_uuid4() print *, trim(option) stop else if(trim(option) == "--new-admin") then ! Config better be loaded by now... if(config_loaded) then call initialize_db(trim(database_filename)) i = i + 1 call get_command_argument(i, username) i = i + 1 call get_command_argument(i, password) if(new_admin_db(trim(username), trim(password))) then Print *, "Admin '"//trim(username)//"' added successfully!" else Print *, "Operation failed." end if else Print *, "Please specify the configuration file first" end if stop end if i = i + 1 end do if(.not. config_loaded) then call get_environment_variable("LEVITATING_CONFIG_CGI", value=option, status=i) if(i == 0) then call load_configuration(trim(option)) config_loaded = .true. mode = MODE_CGI_HTML end if end if if(.not. config_loaded) then call get_environment_variable("LEVITATING_CONFIG_GEMINI", value=option, status=i) if(i == 0) then call load_configuration(trim(option)) config_loaded = .true. mode = MODE_GEMINI end if end if ! Assign working directory from command if not specified if(.not. config_loaded) then Print *, "No configuration file specified" stop end if end subroutine parse_options end program captain