-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmcp21.tf
158 lines (137 loc) · 4.62 KB
/
mcp21.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/set mcp21_tmpdir=/tmp
;/set mcp21_tmpdir=/homes/bjj/tmp
;;
;; END OF USER CONFIGURATION
;;
/require lisp.tf
/loaded mcp21.tf
; generate an auth key named mcp_${world_name}_auth_key
;
/def mcp_gen_auth_key =\
/eval /set mcp_${world_name}_auth_key=$[rand()]
/def mcp_show_auth_key =\
/eval /eval /echo \%{mcp_${world_name}_auth_key}
/def mcp_check_auth_key =\
/eval /test {mcp_${world_name}_auth_key} =~ {1}
; also need send hook to quote OUTGOING? #$# lines? per the spec...
;
/def -Ttiny.moo -p20002 -aGg -mregexp -t'^#\$"(.*)' mcp21_quote = \
/echo -w %{P1}
; Catch the plain mcp message with the trailing space
;
/def -Ttiny.moo -p20001 -aGg -mregexp -t'^#\$#mcp ' mcp21_hook = \
/mcp21_extract_tags%;\
/mcp21_login_internal %{mcp_tag_version} %{mcp_tag_to}
/def mcp21_login_internal = \
/mcp_gen_auth_key%;\
/mcp21_begin_negotiation%;\
/send -w #\$#mcp authentication-key: $(/mcp_show_auth_key) version: 2.1 to: 2.1
/def -Ttiny.moo -p20001 -aGg -mregexp -t'^#\$#mcp-negotiate-end' = \
/mcp21_send_negotiation
/def mcp21_login = /mcp21_login_internal 2.1 2.1
; take the end of a server request and parse the tag/value pairs per the
; spec. note that you can't use `\' to escape arbitrary characters in the
; values, only `"'. The spec is ambiguous on this point.
;
/def mcp21_extract_tags =\
/while (mcp_tags !~ "") \
/eval /unset $(/car %{mcp_tags})%;\
/set mcp_tags=$(/cdr %{mcp_tags})%;\
/done%;\
/mcp21_extract_tags_internal %{*}%;\
/let l=%{mcp_tags}
; watch out! I'm recursive. also be careful about eval'ing tag values,
; since URLs (in particular) include %'s...
;
/def mcp21_extract_tags_internal = \
/while ({#}) \
/test regmatch('(.*):', {1})%;\
/let name=mcp_tag_$[replace('*','_',replace('-','_',{P1}))]%;\
/if (0 == strchr({2}, '"')) \
/test regmatch(strcat('^"(([^"]|', char(92), char(92),'")*)"(.*)'), {-1})%;\
/let val=%{P1}%;\
/let rest=%{P3}%;\
/while (regmatch('(.*)\\\\"(.*)', val)) \
/let val=%P1"%P2%;\
/done%;\
/eval /set %{name}=\%{val}%;\
/eval /set mcp_tags=%{mcp_tags} %{name}%;\
/mcp21_extract_tags_internal %{rest}%;\
/break%;\
/else \
/eval /set %{name}=\%2%;\
/eval /set mcp_tags=%{mcp_tags} %{name}%;\
/shift 2%;\
/endif %;\
/done
; receive a line of oob data from the MOO. check the authentication string,
; parse the tag/value pairs into mcp_tag_*, then call a handler based on
; the message request, eg #$#edit calls /mcp_edit. At the moment we ignore
; the server-supplied `*' to indicate additional lines of data.
;
/def -Ttiny.moo -mregexp -t'^#\$#([^:* ]*) [^ ]* ' -agG -p20000 mcp21_rec_oob =\
/let request=%{P1}%;\
/if /mcp_check_auth_key %2%;\
/then \
/eval /mcp21_set_world ${world_name}%;\
/mcp21_extract_tags %-2%;\
/mcp21_expect_multiline_values %{request} %{mcp_tags}%;\
/endif
/def -Ttiny.moo -mregexp -t'^#\$#([^:* ]*) [^ ]*$' -agG -p19999 mcp21_rec_oob_nokeyvals =\
/let request=%{P1}%;\
/if /mcp_check_auth_key %2%;\
/then \
/eval /mcp21_set_world ${world_name}%;\
/mcp21_extract_tags%;\
/mcp21_expect_multiline_values %{request}%;\
/endif
; open files for any incoming multiline values. when they're all received
; or if there are none, fire off the handler
;
/def mcp21_expect_multiline_values = \
/let request=%1%;\
/let multiline=0%;\
/let fhs=%;\
/while (shift(), {#}) \
/if (strrchr({1}, "_") == strlen({1})-1) \
/mcp_gen_tempfile%;\
/test h:=tfopen({mcp_tempfile}, "w")%;\
/eval /set %1=\%\{mcp_tempfile}%;\
/let fhs %{fhs} %{h}%;\
/mcp21_init_multiline %{mcp_tag__data_tag} $[substr({1}, 8, strlen({1})-9)] %{h}%;\
/let multiline=$[multiline + 1]%;\
/endif%;\
/done%;\
/set mcp21_mlfh_${world_name}=%{fhs}%;\
/if (multiline < 1) \
/eval /mcp21_%{request}%;\
/else \
/def -p20004 -n1 -mregexp -aGg -t'^#\\\$#\\: %{mcp_tag__data_tag} *\$' mcp21_rec_multiline_${world_name}_%2 = \
/eval /mcp21_close_all x %{fhs}%%;\
/eval /mcp21_%{request}%;\
/endif
/def mcp21_close_all = \
/while (shift(), {#}) \
/test tfclose({1})%;\
/done
/def mcp21_init_multiline = \
/def -p20003 -mregexp -aGg -t'^#\\\$#\\* %1 %2: (.*)\$' mcp21_rec_multiline_${world_name}_%2 = /test tfwrite(%3,{P1})
; make up a temporary file name.
;
/def mcp_gen_tempfile =\
/set mcp_tempfile_seq=$[mcp_tempfile_seq + 1]%;\
/eval /set mcp_tempfile=%{mcp21_tmpdir}/.tfmcp2-$[getpid()].%{mcp_tempfile_seq}
/def mcp21_set_world = \
/eval /set mcp21_fg_world=%1
; (message tag: value ...)
;
/def mcp21_send = \
/send -w%{mcp21_fg_world} #\$#%1 $(/mcp_show_auth_key) %-1
; (key tag filename)
;
/def mcp21_send_file = \
/quote -dsend -S -w%{mcp21_fg_world} \\#\$\\#* %1 %2: '%3
; (key)
;
/def mcp21_send_end = \
/send -w%{mcp21_fg_world} #\$#: %1