mirror of https://github.com/dirtbags/moth.git
Merge remote-tracking branch 'origin/add_yaml_support' into add_objectives_support
This commit is contained in:
commit
4e19e39872
|
@ -9,7 +9,8 @@ RUN apk --no-cache add \
|
||||||
&& \
|
&& \
|
||||||
pip3 install \
|
pip3 install \
|
||||||
scapy==2.4.2 \
|
scapy==2.4.2 \
|
||||||
pillow==5.4.1
|
pillow==5.4.1 \
|
||||||
|
PyYAML==5.1.1
|
||||||
|
|
||||||
|
|
||||||
COPY devel /app/
|
COPY devel /app/
|
||||||
|
|
145
devel/moth.py
145
devel/moth.py
|
@ -13,6 +13,7 @@ import random
|
||||||
import string
|
import string
|
||||||
import tempfile
|
import tempfile
|
||||||
import shlex
|
import shlex
|
||||||
|
import yaml
|
||||||
|
|
||||||
messageChars = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
messageChars = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||||
|
|
||||||
|
@ -126,59 +127,101 @@ class Puzzle:
|
||||||
|
|
||||||
def read_stream(self, stream):
|
def read_stream(self, stream):
|
||||||
header = True
|
header = True
|
||||||
|
line = ""
|
||||||
|
if stream.read(3) == "---":
|
||||||
|
header = "yaml"
|
||||||
|
else:
|
||||||
|
header = "moth"
|
||||||
|
|
||||||
|
stream.seek(0)
|
||||||
|
|
||||||
|
if header == "yaml":
|
||||||
|
self.read_yaml_header(stream)
|
||||||
|
elif header == "moth":
|
||||||
|
self.read_moth_header(stream)
|
||||||
|
|
||||||
for line in stream:
|
for line in stream:
|
||||||
if header:
|
self.body.write(line)
|
||||||
line = line.strip()
|
|
||||||
if not line:
|
def read_yaml_header(self, stream):
|
||||||
header = False
|
contents = ""
|
||||||
continue
|
header = False
|
||||||
key, val = line.split(':', 1)
|
for line in stream:
|
||||||
key = key.lower()
|
if line.strip() == "---" and header: # Handle last line
|
||||||
val = val.strip()
|
break
|
||||||
if key == 'author':
|
elif line.strip() == "---": # Handle first line
|
||||||
self.authors.append(val)
|
header = True
|
||||||
elif key == 'summary':
|
continue
|
||||||
self.summary = val
|
|
||||||
elif key == 'answer':
|
|
||||||
self.answers.append(val)
|
|
||||||
elif key == 'pattern':
|
|
||||||
self.pattern = val
|
|
||||||
elif key == 'hint':
|
|
||||||
self.hint = val
|
|
||||||
elif key == 'name':
|
|
||||||
pass
|
|
||||||
elif key == 'file':
|
|
||||||
parts = shlex.split(val)
|
|
||||||
name = parts[0]
|
|
||||||
hidden = False
|
|
||||||
stream = open(name, 'rb')
|
|
||||||
try:
|
|
||||||
name = parts[1]
|
|
||||||
hidden = (parts[2].lower() == "hidden")
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
self.files[name] = PuzzleFile(stream, name, not hidden)
|
|
||||||
elif key == 'script':
|
|
||||||
stream = open(val, 'rb')
|
|
||||||
# Make sure this shows up in the header block of the HTML output.
|
|
||||||
self.files[val] = PuzzleFile(stream, val, visible=False)
|
|
||||||
self.scripts.append(val)
|
|
||||||
elif key == "objective":
|
|
||||||
self.objective = val
|
|
||||||
elif key == "success":
|
|
||||||
self.success = val
|
|
||||||
elif key == "success.acceptable":
|
|
||||||
self.success.acceptable = val
|
|
||||||
elif key == "success.mastery":
|
|
||||||
self.success.mastery = val
|
|
||||||
elif key == "solution":
|
|
||||||
self.solution = val
|
|
||||||
elif key == "ksa":
|
|
||||||
self.ksas.append(val)
|
|
||||||
else:
|
|
||||||
raise ValueError("Unrecognized header field: {}".format(key))
|
|
||||||
else:
|
else:
|
||||||
self.body.write(line)
|
contents += line
|
||||||
|
|
||||||
|
config = yaml.safe_load(contents)
|
||||||
|
for key, value in config.items():
|
||||||
|
key = key.lower()
|
||||||
|
self.handle_header_key(key, value)
|
||||||
|
|
||||||
|
def read_moth_header(self, stream):
|
||||||
|
for line in stream:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
|
||||||
|
key, val = line.split(':', 1)
|
||||||
|
key = key.lower()
|
||||||
|
val = val.strip()
|
||||||
|
self.handle_header_key(key, val)
|
||||||
|
|
||||||
|
def handle_header_key(self, key, val):
|
||||||
|
if key == 'author':
|
||||||
|
self.authors.append(val)
|
||||||
|
elif key == 'summary':
|
||||||
|
self.summary = val
|
||||||
|
elif key == 'answer':
|
||||||
|
if not isinstance(val, str):
|
||||||
|
raise ValueError("Answers must be strings, got %s, instead" % (type(val),))
|
||||||
|
self.answers.append(val)
|
||||||
|
elif key == "answers":
|
||||||
|
for answer in val:
|
||||||
|
if not isinstance(answer, str):
|
||||||
|
raise ValueError("Answers must be strings, got %s, instead" % (type(answer),))
|
||||||
|
self.answers.append(answer)
|
||||||
|
elif key == 'pattern':
|
||||||
|
self.pattern = val
|
||||||
|
elif key == 'hint':
|
||||||
|
self.hint = val
|
||||||
|
elif key == 'name':
|
||||||
|
pass
|
||||||
|
elif key == 'file':
|
||||||
|
parts = shlex.split(val)
|
||||||
|
name = parts[0]
|
||||||
|
hidden = False
|
||||||
|
stream = open(name, 'rb')
|
||||||
|
try:
|
||||||
|
name = parts[1]
|
||||||
|
hidden = (parts[2].lower() == "hidden")
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
self.files[name] = PuzzleFile(stream, name, not hidden)
|
||||||
|
elif key == 'script':
|
||||||
|
stream = open(val, 'rb')
|
||||||
|
# Make sure this shows up in the header block of the HTML output.
|
||||||
|
self.files[val] = PuzzleFile(stream, val, visible=False)
|
||||||
|
self.scripts.append(val)
|
||||||
|
elif key == "objective":
|
||||||
|
self.objective = val
|
||||||
|
elif key == "success":
|
||||||
|
self.success = val
|
||||||
|
elif key == "success.acceptable":
|
||||||
|
self.success.acceptable = val
|
||||||
|
elif key == "success.mastery":
|
||||||
|
self.success.mastery = val
|
||||||
|
elif key == "solution":
|
||||||
|
self.solution = val
|
||||||
|
elif key == "ksa":
|
||||||
|
self.ksas.append(val)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unrecognized header field: {}".format(key))
|
||||||
|
|
||||||
|
|
||||||
def read_directory(self, path):
|
def read_directory(self, path):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue