Commit Diff


commit - dbb4931c96379e3ebe14bdde01eb5c4bc458c970
commit + 479e180db265e5846678bec016865ea6cdcf14ca
blob - b9581c28507eebad79ab8a2d8a5d54bf4c37ed20
blob + 4e83909a70508facb8bc6578a4973f500f3b25da
--- .gitignore
+++ .gitignore
@@ -1,5 +1,6 @@
 syntax: glob
 cert/
 vostok/vostok
+tests/test_parse_url
 **/*.swp
 **/*.o
blob - 3419f6a439dcda6470e1535d68ec645f0d352f8a
blob + bf8d53419335d7b548e224c587ce6faa1931b65b
--- Makefile
+++ Makefile
@@ -1,12 +1,14 @@
-.PHONY: clean all
+.PHONY: server clean run_server tests
 
-all: server
+server:
+	${MAKE} -C vostok
 
 clean:
 	${MAKE} -C vostok clean
+	${MAKE} -C tests clean
 
-server:
-	${MAKE} -C vostok
-
 run_server: server
 	./vostok/vostok -c cert/server.crt -k cert/server.key -f ./
+
+tests:
+	${MAKE} -C tests
blob - 3de45264a86a32f3df81d0b9d4d68f713db43a80
blob + 950b8283fb07a4289fe6d1a462651a2b76773d33
--- vostok/Makefile
+++ vostok/Makefile
@@ -1,4 +1,4 @@
-CXXFLAGS	+= -Wall -Wextra -std=c++11 -I../shared
+CXXFLAGS	+= -Wall -Wextra -std=c++11
 LIBS		= -ltls
 
 CXXFILES	= transport.cc
blob - afe7698e1348e587ce929c920f9b917f807c6a81
blob + 1ae1d8316e4b4cc89f93d82c35e39aa3dbbc9564
--- vostok/parse_url.cc
+++ vostok/parse_url.cc
@@ -20,7 +20,7 @@ class path_normalization
 public:
     using path_components_t = std::list< span<const char> >;
 
-    url_normalization_result operator() (span<char> url_path, zs_url_path_t &zs_url_path);
+    url_normalization_result operator() (span<const char> url_path, zs_url_path_t &zs_url_path);
 
 protected:
     url_normalization_result on_component();
@@ -38,7 +38,7 @@ class path_normalization
 };
 
 
-url_normalization_result path_normalization::operator() (span<char> url_path, zs_url_path_t &zs_url_path)
+url_normalization_result path_normalization::operator() (span<const char> url_path, zs_url_path_t &zs_url_path)
 {
     m_inprogress = path_components_t::value_type{nullptr, 0};
     m_result.clear();
@@ -105,7 +105,7 @@ void path_normalization::fill(zs_url_path_t &zs_url_pa
 }   // namespace <unnamed>
 
 
-url_normalization_result parse_url(span<char> url, zs_url_path_t &zs_url_path)
+url_normalization_result parse_url(span<const char> url, zs_url_path_t &zs_url_path)
 {
     // check and skip scheme
     if (url.size() < gemini_scheme.size())
blob - d79fc3e17d319c79462467e62c21625b3a7ba0a8
blob + 8d8b31570d606dd105c6888b6b7546eb51b7e026
--- vostok/parse_url.h
+++ vostok/parse_url.h
@@ -24,7 +24,7 @@ enum url_normalization_result
 using zs_url_path_t = std::array<char, gemini::MAX_URL_LENGTH + 1>;
 
 /** Extract normalized path from URL as list null-terminated string */
-url_normalization_result parse_url(span<char> url, zs_url_path_t &zs_url_path);
+url_normalization_result parse_url(span<const char> url, zs_url_path_t &zs_url_path);
 
 
 }   // namespace vostok
blob - d80d60dae0f1e151f0e6f93adba30d597190355f
blob + b7a75a85a349403c66a00ae0978b5c7e78d38f4c
--- vostok/transport.cc
+++ vostok/transport.cc
@@ -137,7 +137,7 @@ void accept(
 }
 
 
-span<char> read_request(not_null<struct tls *> ctx, std::array<char, gemini::MAX_REQUEST_LENGTH> &buffer)
+span<const char> read_request(not_null<struct tls *> ctx, std::array<char, gemini::MAX_REQUEST_LENGTH> &buffer)
 {
     span<char> request{buffer};
     if (!read(ctx, request))
@@ -152,7 +152,7 @@ span<char> read_request(not_null<struct tls *> ctx, st
         if (*current == gemini::CRLF[0] && *next == gemini::CRLF[1])
         {
             // > servers MUST ignore anything sent after the first occurrence of a <CR><LF>.
-            return request.first(current - request.begin());
+            return span<const char>{request.begin(), static_cast<std::size_t>(current - request.begin())};
         }
     }
     error::occurred("Parse request", error::none{});
blob - a193575fd5ec3e4fac5f36aa02d94ca060a2b444
blob + ca021031a6a36547413206e674339b82f4dd03f4
--- vostok/transport.h
+++ vostok/transport.h
@@ -69,7 +69,7 @@ void accept(
 
 
 /** Read genimi request and return url (empty url - error) */
-span<char> read_request(not_null<struct tls *> ctx, std::array<char, gemini::MAX_REQUEST_LENGTH> &buffer);
+span<const char> read_request(not_null<struct tls *> ctx, std::array<char, gemini::MAX_REQUEST_LENGTH> &buffer);
 
 
 /** Write gemini response */
blob - /dev/null
blob + af85dcda59bfbc4d7701ab57ec7cf8aaf715b581 (mode 644)
--- /dev/null
+++ tests/Makefile
@@ -0,0 +1,12 @@
+.PHONY: tests clean
+
+CXXFLAGS	+= -I../vostok
+
+tests: test_parse_url
+	./test_parse_url
+
+test_parse_url: test_parse_url.cc ../vostok/parse_url.cc ../vostok/parse_url.h
+	${CXX} ${CXXFLAGS} test_parse_url.cc ../vostok/parse_url.cc -o test_parse_url
+
+clean:
+	rm -f test_parse_url
blob - /dev/null
blob + 65402cd90a810a8d10d86b12a0d6ecf7d0c9eeea (mode 644)
--- /dev/null
+++ tests/test_parse_url.cc
@@ -0,0 +1,67 @@
+#include "parse_url.h"
+#include <string.h>
+#include <iostream>
+
+#include "tests.h"
+
+
+namespace vostok
+{
+
+int test_parse_url()
+{
+    int ret = 0;
+    zs_url_path_t zs_url_path;
+
+
+    IS_TRUE(parse_url(cut_null("gemini://host"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host/"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host/a"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "a") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host/a/b"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "a/b") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host:port"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host:port/"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host:port/a"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "a") == 0);
+
+    IS_TRUE(parse_url(cut_null("gemini://host:port/a/b"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "a/b") == 0);
+
+    IS_TRUE(parse_url(cut_null(""), zs_url_path) == url_too_short);
+    IS_TRUE(parse_url(cut_null("g"), zs_url_path) == url_too_short);
+    IS_TRUE(parse_url(cut_null("gemini:/"), zs_url_path) == url_too_short);
+
+    IS_TRUE(parse_url(cut_null("gemini1://"), zs_url_path) == url_non_gemini);
+
+    IS_TRUE(parse_url(cut_null("gemini://host/../secret.txt"), zs_url_path) == url_root_traverse);
+    IS_TRUE(parse_url(cut_null("gemini://host/dir/../../secret.txt"), zs_url_path) == url_root_traverse);
+
+    IS_TRUE(parse_url(cut_null("gemini://host/a/b/../c/./d"), zs_url_path) == url_ok);
+    IS_TRUE(strcmp(zs_url_path.begin(), "a/c/d") == 0);
+
+    if (ret == 0)
+        std::cout << __FUNCTION__ << " successfully passed!" << std::endl;
+
+    return ret;
+}
+
+}   // namespace vostok
+
+
+extern "C"
+int
+main(int, char **)
+{
+   return vostok::test_parse_url();
+}
blob - /dev/null
blob + afce9cc5b57c18bc8ba16f4a33292f2baffe5471 (mode 644)
--- /dev/null
+++ tests/tests.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#define IS_TRUE(x) if(!(x)){std::cout<<__FUNCTION__<<" failed on line "<<__LINE__<<std::endl;ret=1;}