From 4fcf1161320b28509ed7c517d38c93f26157b6af Mon Sep 17 00:00:00 2001 From: Nguyễn Gia Phong Date: Wed, 22 Feb 2023 18:36:48 +0900 Subject: Implement registation form --- hybring.cr | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 6 deletions(-) (limited to 'hybring.cr') diff --git a/hybring.cr b/hybring.cr index 220559f..1c5015e 100644 --- a/hybring.cr +++ b/hybring.cr @@ -1,18 +1,30 @@ -# Hybrid web ring +# Hybrid web ring server # Copyright (C) 2023 Nguyễn Gia Phong # -# This program is free software: you can redistribute it and/or modify +# This file if part of hybring. +# +# Hybring is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, +# Hybring is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with hybring. If not, see . + +require "http/server" +require "uri" + +require "./xhtml" + +MAX_CONTENT_LENGTH = 4096 +OPENNIC_TLD = Set{".bbs", ".chan", ".cyb", ".dyn", ".epic", + ".geek", ".gopher", ".indy", ".libre", ".neo", + ".null", ".o", ".oss", ".oz", ".parody", ".pirate"} @[Link("sqlite3")] lib SQLite @@ -21,14 +33,76 @@ lib SQLite fun open = sqlite3_open(filename : LibC::Char*, db : Database*) : LibC::Int fun prepare = sqlite3_prepare(db : Database, query : LibC::Char*, length : LibC::Int, stmt : Statement*, - query_tail : LibC::Char*) + query_tail : LibC::Char*) : LibC::Int + fun step = sqlite3_step(stmt : Statement) : Int32 + fun column_text = sqlite3_column_text(stmt : Statement, + col : LibC::Int) : LibC::Char* + fun finalize = sqlite3_finalize(stmt : Statement) : LibC::Int fun close = sqlite3_close(db : Database) : LibC::Int end -DB_INIT = "CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY);"; +DB_INIT = "CREATE TABLE member ( + id INTEGER PRIMARY KEY, + nick TEXT NOT NULL UNIQUE, + opennic TEXT NOT NULL UNIQUE, + icann TEXT NOT NULL UNIQUE, +);"; SQLite.open "foo.db", out db begin ensure SQLite.close db end + +def http_error(context, status, message = nil) + context.response.respond_with_status status, message +end + +File.write "index.xhtml", page +server = HTTP::Server.new do |context| + next http_error context, 405 if context.request.method != "POST" + content_length = context.request.content_length + next http_error context, 411 unless content_length + next http_error context, 413 if content_length > MAX_CONTENT_LENGTH + + body = context.request.body.try &.gets_to_end || "" + errors = {} of String => String + params = {} of String => String + invalid_param = false + URI::Params.parse body do |key, value| + params[key] = value + case key + when "nick" + when "opennic" + uri = URI.parse value + next errors["opennic"] = "Must be absolute URL" unless uri.absolute? + if uri.scheme != "http" && uri.scheme != "https" + next errors["opennic"] = "Must be HTTP/S" + end + host = uri.host + unless OPENNIC_TLD.includes? Path[host].extension + next errors["opennic"] = "Must be under OpenNIC domain" + end if host + when "icann" + uri = URI.parse value + next errors["icann"] = "Must be absolute URL" unless uri.absolute? + next errors["icann"] = "Must be HTTPS" unless uri.scheme == "https" + host = uri.host # impractical to check for ICANN TLD + if OPENNIC_TLD.includes? Path[host].extension + next errors["icann"] = "Must not be under OpenNIC domain" + end if host + else + break invalid_param = true + end + end + next http_error context, 400, "Invalid Parameter" if invalid_param + + context.response.status_code = 400 unless errors.empty? + context.response.content_type = "application/xhtml+xml" + context.response.print page errors, params + # TODO: schedule dynamic check +end + +address = server.bind_tcp 8080 +puts "Listening on http://#{address}" +server.listen -- cgit 1.4.1