Initial commit -- RFC1288 parser is passing unit tests.
This commit is contained in:
parent
13bf1649a8
commit
b7513a86fa
|
@ -1,3 +1,13 @@
|
||||||
|
*#
|
||||||
|
.#*
|
||||||
|
*~
|
||||||
|
*.orig
|
||||||
|
*.aux
|
||||||
|
*.log
|
||||||
|
*.out
|
||||||
|
*.pdf
|
||||||
|
*.bk
|
||||||
|
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
*.exe
|
*.exe
|
||||||
*.dll
|
*.dll
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
# MONOLOGUED
|
||||||
|
|
||||||
|
Monologued is an implementation of an
|
||||||
|
[RFC1288](https://tools.ietf.org/html/rfc1288) protocol server in Go.
|
||||||
|
|
||||||
|
That's right. Monologued is a
|
||||||
|
*[Finger](https://en.wikipedia.org/wiki/Finger_protocol)* server.
|
||||||
|
|
||||||
|
# WHY‽‽‽‽
|
||||||
|
|
||||||
|
While what I really wanted was to
|
||||||
|
[learn Rust](https://github.com/elfsternberg/monologued), work decided that
|
||||||
|
Go was a better choice. Since I have to learn it, this seemed like the
|
||||||
|
best way to go about it. Still not thrilled with the decision, but maybe
|
||||||
|
I'll get a blog post out of it.
|
||||||
|
|
||||||
|
# Status
|
||||||
|
|
||||||
|
Monologued is still very much not working. Don't even bother
|
||||||
|
downloading. It's mostly something to cut my teeth on while I try to
|
||||||
|
figure out how Go works.
|
||||||
|
|
||||||
|
# Thanks
|
||||||
|
|
||||||
|
Thanks to my friend Nathaniel for the answer to my original question,
|
||||||
|
"In a movie, when the villain is explaining his plans at length, what is
|
||||||
|
that called?" Nathaniel explained that "He's monologuing," and now you
|
||||||
|
know why it has that name.
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
Apache 2.0. See the accompanying LICENSE file in this directory.
|
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("What the fuck, over?", extraNonsense())
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package rfc1288
|
||||||
|
|
||||||
|
import(
|
||||||
|
"bytes"
|
||||||
|
// "fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func is_unix_conventional(c byte) bool {
|
||||||
|
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
|
||||||
|
}
|
||||||
|
|
||||||
|
var Rfc1288ErrorMsgs = []string {
|
||||||
|
"",
|
||||||
|
"Protocol prefix not recognized",
|
||||||
|
"Protocol request does not meet specifications",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rfc1288ErrorCode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Ok Rfc1288ErrorCode = 0
|
||||||
|
BadProtocol Rfc1288ErrorCode = 1
|
||||||
|
BadRequest Rfc1288ErrorCode = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Rfc1288RequestType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserList Rfc1288RequestType = 0
|
||||||
|
User Rfc1288RequestType = 1
|
||||||
|
Remote Rfc1288RequestType = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Rfc1288Request struct {
|
||||||
|
Type Rfc1288RequestType
|
||||||
|
User* string
|
||||||
|
Host* string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse_rfc1288_request(Buffer string) (Rfc1288ErrorCode, *Rfc1288Request) {
|
||||||
|
Buflen := len(Buffer)
|
||||||
|
|
||||||
|
if Buflen < 2 {
|
||||||
|
return BadProtocol, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if Buffer[0] != '/' || (Buffer[1] != 'W' && Buffer[1] != 'w') {
|
||||||
|
return BadProtocol, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(Buffer) == 2 {
|
||||||
|
return Ok, &Rfc1288Request{UserList, nil, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
index := 2
|
||||||
|
for index < Buflen && Buffer[index] == ' ' {
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if Buflen == index {
|
||||||
|
return Ok, &Rfc1288Request{Type: UserList, User: nil, Host: nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
user := bytes.NewBufferString("")
|
||||||
|
host := bytes.NewBufferString("")
|
||||||
|
|
||||||
|
for index < Buflen && is_unix_conventional(Buffer[index]) {
|
||||||
|
user.WriteByte(Buffer[index])
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if index == Buflen || (index < Buflen && Buffer[index] == ' ') {
|
||||||
|
ruser := user.String()
|
||||||
|
return Ok, &Rfc1288Request{Type: User, User: &ruser, Host: nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
if Buffer[index] != '@' {
|
||||||
|
return BadRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
for index < Buflen && Buffer[index] != ' ' {
|
||||||
|
host.WriteByte(Buffer[index])
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ruser := user.String()
|
||||||
|
rhost := host.String()
|
||||||
|
return Ok, &Rfc1288Request{Type: Remote, User: &ruser, Host: &rhost}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
package rfc1288
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestGood_List(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/W")
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != UserList {
|
||||||
|
t.Error("Expected UserList as a return type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGood_ListWSpaces(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/W ");
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != UserList {
|
||||||
|
t.Error("Expected UserList as a return type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBad_Start(t *testing.T) {
|
||||||
|
res, _ := parse_rfc1288_request("")
|
||||||
|
if res != BadProtocol {
|
||||||
|
t.Error("Expected BadProtocol")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBad_Start1(t *testing.T) {
|
||||||
|
res, _ := parse_rfc1288_request("/")
|
||||||
|
if res != BadProtocol {
|
||||||
|
t.Error("Expected BadProtocol")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBad_Start2(t *testing.T) {
|
||||||
|
res, _ := parse_rfc1288_request("/X")
|
||||||
|
if res != BadProtocol {
|
||||||
|
t.Error("Expected BadProtocol, got", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGood_Name(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/W foozle")
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != User {
|
||||||
|
t.Error("Expected User as a return type")
|
||||||
|
}
|
||||||
|
if *req.User != "foozle" {
|
||||||
|
t.Error("The user name did not match passed in value.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGood_NameExtraSpace(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/W foozle ")
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != User {
|
||||||
|
t.Error("Expected User as a return type")
|
||||||
|
}
|
||||||
|
if *req.User != "foozle" {
|
||||||
|
t.Error("The user name did not match passed in value.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGood_NameWHost(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/W foozle@localhost")
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != Remote {
|
||||||
|
t.Error("Expected Remote as a return type")
|
||||||
|
}
|
||||||
|
if *req.User != "foozle" {
|
||||||
|
t.Error("The user name did not match passed in value.")
|
||||||
|
}
|
||||||
|
if *req.Host != "localhost" {
|
||||||
|
t.Error("The host name did not match passed in value.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGood_NameWHostAndSpaces(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/W foozle@localhost ")
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != Remote {
|
||||||
|
t.Error("Expected Remote as a return type")
|
||||||
|
}
|
||||||
|
if *req.User != "foozle" {
|
||||||
|
t.Error("The user name did not match passed in value.")
|
||||||
|
}
|
||||||
|
if *req.Host != "localhost" {
|
||||||
|
t.Error("The host name did not match passed in value.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGood_NameWHostAndSpacesAndLowerW(t *testing.T) {
|
||||||
|
res, req := parse_rfc1288_request("/w foozle@localhost ")
|
||||||
|
if res != Ok {
|
||||||
|
t.Error("Expected a good return")
|
||||||
|
}
|
||||||
|
if req.Type != Remote {
|
||||||
|
t.Error("Expected Remote as a return type")
|
||||||
|
}
|
||||||
|
if *req.User != "foozle" {
|
||||||
|
t.Error("The user name did not match passed in value.")
|
||||||
|
}
|
||||||
|
if *req.Host != "localhost" {
|
||||||
|
t.Error("The host name did not match passed in value.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBad_Name(t *testing.T) {
|
||||||
|
res, _ := parse_rfc1288_request("/W foozle.. ")
|
||||||
|
if res != BadRequest {
|
||||||
|
t.Error("Expected BadRequest")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue